PRInt64 nsTheoraState::StartTime(PRInt64 granulepos) {
  if (granulepos < 0 || !mActive || mInfo.fps_numerator == 0) {
    return -1;
  }
  PRInt64 t = 0;
  PRInt64 frameno = th_granule_frame(mCtx, granulepos);
  if (!MulOverflow(frameno, 1000, t))
    return -1;
  if (!MulOverflow(t, mInfo.fps_denominator, t))
    return -1;
  return t / mInfo.fps_numerator;
}
// Converts from microseconds to number of audio samples, given the specified
// audio rate.
PRBool UsecsToSamples(PRInt64 aUsecs, PRUint32 aRate, PRInt64& aOutSamples)
{
  PRInt64 x;
  if (!MulOverflow(aUsecs, aRate, x))
    return PR_FALSE;
  aOutSamples = x / USECS_PER_S;
  return PR_TRUE;
}
// Converts from number of audio samples to microseconds, given the specified
// audio rate.
PRBool SamplesToUsecs(PRInt64 aSamples, PRUint32 aRate, PRInt64& aOutUsecs)
{
  PRInt64 x;
  if (!MulOverflow(aSamples, USECS_PER_S, x))
    return PR_FALSE;
  aOutUsecs = x / aRate;
  return PR_TRUE;
}
PRInt64 nsVorbisState::Time(vorbis_info* aInfo, PRInt64 aGranulepos)
{
  if (aGranulepos == -1 || aInfo->rate == 0) {
    return -1;
  }
  PRInt64 t = 0;
  MulOverflow(1000, aGranulepos, t);
  return t / aInfo->rate;
}
Beispiel #5
0
PRInt64 nsVorbisState::Time(PRInt64 granulepos)
{
    if (granulepos == -1 || !mActive || mDsp.vi->rate == 0) {
        return -1;
    }
    PRInt64 t = 0;
    MulOverflow(1000, granulepos, t);
    return t / mDsp.vi->rate;
}
PRInt64 nsTheoraState::Time(th_info* aInfo, PRInt64 aGranulepos)
{
  if (aGranulepos < 0 || aInfo->fps_numerator == 0) {
    return -1;
  }
  PRInt64 t = 0;
  // Implementation of th_granule_frame inlined here to operate
  // on the th_info structure instead of the theora_state.
  int shift = aInfo->keyframe_granule_shift; 
  ogg_int64_t iframe = aGranulepos >> shift;
  ogg_int64_t pframe = aGranulepos - (iframe << shift);
  PRInt64 frameno = iframe + pframe - TH_VERSION_CHECK(aInfo, 3, 2, 1);
  if (!AddOverflow(frameno, 1, t))
    return -1;
  if (!MulOverflow(t, 1000, t))
    return -1;
  if (!MulOverflow(t, aInfo->fps_denominator, t))
    return -1;
  return t / aInfo->fps_numerator;
}
Beispiel #7
0
PRBool nsTheoraState::Init() {
    if (!mActive)
        return PR_FALSE;

    PRInt64 n = mInfo.fps_numerator;
    PRInt64 d = mInfo.fps_denominator;

    PRInt64 f;
    if (!MulOverflow(1000, d, f)) {
        return mActive = PR_FALSE;
    }
    f /= n;
    if (f > PR_UINT32_MAX) {
        return mActive = PR_FALSE;
    }
    mFrameDuration = static_cast<PRUint32>(f);

    n = mInfo.aspect_numerator;

    d = mInfo.aspect_denominator;
    mPixelAspectRatio = (n == 0 || d == 0) ?
                        1.0f : static_cast<float>(n) / static_cast<float>(d);

    // Ensure the frame region isn't larger than our prescribed maximum.
    PRUint32 pixels;
    if (!MulOverflow32(mInfo.frame_width, mInfo.frame_height, pixels) ||
            pixels > MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT ||
            pixels == 0)
    {
        return mActive = PR_FALSE;
    }

    // Ensure the picture region isn't larger than our prescribed maximum.
    if (!MulOverflow32(mInfo.pic_width, mInfo.pic_height, pixels) ||
            pixels > MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT ||
            pixels == 0)
    {
        return mActive = PR_FALSE;
    }

    mCtx = th_decode_alloc(&mInfo, mSetup);
    if (mCtx == NULL) {
        return mActive = PR_FALSE;
    }

    return PR_TRUE;
}
PRInt64
nsTheoraState::MaxKeyframeOffset()
{
  // Determine the maximum time in microseconds by which a key frame could
  // offset for the theora bitstream. Theora granulepos encode time as:
  // ((key_frame_number << granule_shift) + frame_offset).
  // Therefore the maximum possible time by which any frame could be offset
  // from a keyframe is the duration of (1 << granule_shift) - 1) frames.
  PRInt64 frameDuration;
  
  // Max number of frames keyframe could possibly be offset.
  PRInt64 keyframeDiff = (1 << mInfo.keyframe_granule_shift) - 1;

  // Length of frame in usecs.
  PRInt64 d = 0; // d will be 0 if multiplication overflows.
  MulOverflow(USECS_PER_S, mInfo.fps_denominator, d);
  frameDuration = d / mInfo.fps_numerator;

  // Total time in usecs keyframe can be offset from any given frame.
  return frameDuration * keyframeDiff;
}
PRBool nsTheoraState::Init() {
  if (!mActive)
    return PR_FALSE;

  PRInt64 n = mInfo.fps_numerator;
  PRInt64 d = mInfo.fps_denominator;

  PRInt64 f;
  if (!MulOverflow(1000, d, f)) {
    return mActive = PR_FALSE;
  }
  f /= n;
  if (f > PR_UINT32_MAX) {
    return mActive = PR_FALSE;
  }
  mFrameDuration = static_cast<PRUint32>(f);

  n = mInfo.aspect_numerator;

  d = mInfo.aspect_denominator;
  mPixelAspectRatio = (n == 0 || d == 0) ?
    1.0f : static_cast<float>(n) / static_cast<float>(d);

  // Ensure the frame and picture regions aren't larger than our prescribed
  // maximum, or zero sized.
  nsIntSize frame(mInfo.frame_width, mInfo.frame_height);
  nsIntRect picture(mInfo.pic_x, mInfo.pic_y, mInfo.pic_width, mInfo.pic_height);
  if (!nsVideoInfo::ValidateVideoRegion(frame, picture, frame)) {
    return mActive = PR_FALSE;
  }

  mCtx = th_decode_alloc(&mInfo, mSetup);
  if (mCtx == NULL) {
    return mActive = PR_FALSE;
  }

  return PR_TRUE;
}
Beispiel #10
0
PRBool nsSkeletonState::DecodeIndex(ogg_packet* aPacket)
{
  NS_ASSERTION(aPacket->bytes >= SKELETON_4_0_MIN_INDEX_LEN,
               "Index must be at least minimum size");
  if (!mActive) {
    return PR_FALSE;
  }

  PRUint32 serialno = LEUint32(aPacket->packet + INDEX_SERIALNO_OFFSET);
  PRInt64 numKeyPoints = LEInt64(aPacket->packet + INDEX_NUM_KEYPOINTS_OFFSET);

  PRInt64 n = 0;
  PRInt64 endTime = 0, startTime = 0;
  const unsigned char* p = aPacket->packet;

  PRInt64 timeDenom = LEInt64(aPacket->packet + INDEX_TIME_DENOM_OFFSET);
  if (timeDenom == 0) {
    LOG(PR_LOG_DEBUG, ("Ogg Skeleton Index packet for stream %u has 0 "
                       "timestamp denominator.", serialno));
    return (mActive = PR_FALSE);
  }

  // Extract the start time.
  n = LEInt64(p + INDEX_FIRST_NUMER_OFFSET);
  PRInt64 t;
  if (!MulOverflow(n, 1000, t)) {
    return (mActive = PR_FALSE);
  } else {
    startTime = t / timeDenom;
  }

  // Extract the end time.
  n = LEInt64(p + INDEX_LAST_NUMER_OFFSET);
  if (!MulOverflow(n, 1000, t)) {
    return (mActive = PR_FALSE);
  } else {
    endTime = t / timeDenom;
  }

  // Check the numKeyPoints value read, ensure we're not going to run out of
  // memory while trying to decode the index packet.
  PRInt64 minPacketSize;
  if (!MulOverflow(numKeyPoints, MIN_KEY_POINT_SIZE, minPacketSize) ||
      !AddOverflow(INDEX_KEYPOINT_OFFSET, minPacketSize, minPacketSize))
  {
    return (mActive = PR_FALSE);
  }
  
  PRInt64 sizeofIndex = aPacket->bytes - INDEX_KEYPOINT_OFFSET;
  PRInt64 maxNumKeyPoints = sizeofIndex / MIN_KEY_POINT_SIZE;
  if (aPacket->bytes < minPacketSize ||
      numKeyPoints > maxNumKeyPoints || 
      numKeyPoints < 0)
  {
    // Packet size is less than the theoretical minimum size, or the packet is
    // claiming to store more keypoints than it's capable of storing. This means
    // that the numKeyPoints field is too large or small for the packet to
    // possibly contain as many packets as it claims to, so the numKeyPoints
    // field is possibly malicious. Don't try decoding this index, we may run
    // out of memory.
    LOG(PR_LOG_DEBUG, ("Possibly malicious number of key points reported "
                       "(%lld) in index packet for stream %u.",
                       numKeyPoints,
                       serialno));
    return (mActive = PR_FALSE);
  }

  nsAutoPtr<nsKeyFrameIndex> keyPoints(new nsKeyFrameIndex(startTime, endTime));
  
  p = aPacket->packet + INDEX_KEYPOINT_OFFSET;
  const unsigned char* limit = aPacket->packet + aPacket->bytes;
  PRInt64 numKeyPointsRead = 0;
  PRInt64 offset = 0;
  PRInt64 time = 0;
  while (p < limit &&
         numKeyPointsRead < numKeyPoints)
  {
    PRInt64 delta = 0;
    p = ReadVariableLengthInt(p, limit, delta);
    if (p == limit ||
        !AddOverflow(offset, delta, offset) ||
        offset > mLength ||
        offset < 0)
    {
      return (mActive = PR_FALSE);
    }
    p = ReadVariableLengthInt(p, limit, delta);
    if (!AddOverflow(time, delta, time) ||
        time > endTime ||
        time < startTime)
    {
      return (mActive = PR_FALSE);
    }
    PRInt64 timeMs = 0;
    if (!MulOverflow(time, 1000, timeMs))
      return mActive = PR_FALSE;
    timeMs /= timeDenom;
    keyPoints->Add(offset, timeMs);
    numKeyPointsRead++;
  }

  PRInt32 keyPointsRead = keyPoints->Length();
  if (keyPointsRead > 0) {
    mIndex.Put(serialno, keyPoints.forget());
  }

  LOG(PR_LOG_DEBUG, ("Loaded %d keypoints for Skeleton on stream %u",
                     keyPointsRead, serialno));
  return PR_TRUE;
}