Bug 1043710 - Expose decode timestamp. r=edwin
authorAnthony Jones <ajones@mozilla.com>
Wed, 27 Aug 2014 14:08:00 -0700
changeset 223703 632d5a8709cbd78fe679de85eb7776bd863ebbb2
parent 223702 102eaae71580397d34ef0b2dabbe7d31dbf3f32f
child 223704 feb4a53fd308b7a28ff372d7f8f378131fadcc65
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersedwin
bugs1043710
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1043710 - Expose decode timestamp. r=edwin
content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp
media/libstagefright/binding/DecoderData.cpp
media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp
media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
media/libstagefright/frameworks/av/media/libstagefright/include/SampleIterator.h
media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h
--- a/content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp
+++ b/content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp
@@ -51,16 +51,17 @@ void
 FFmpegH264Decoder<LIBAV_VER>::DecodeFrame(mp4_demuxer::MP4Sample* aSample)
 {
   AVPacket packet;
   av_init_packet(&packet);
 
   aSample->Pad(FF_INPUT_BUFFER_PADDING_SIZE);
   packet.data = aSample->data;
   packet.size = aSample->size;
+  packet.dts = aSample->decode_timestamp;
   packet.pts = aSample->composition_timestamp;
   packet.flags = aSample->is_sync_point ? AV_PKT_FLAG_KEY : 0;
   packet.pos = aSample->byte_offset;
 
   if (!PrepareFrame()) {
     NS_WARNING("FFmpeg h264 decoder failed to allocate frame.");
     mCallback->Error();
     return;
--- a/media/libstagefright/binding/DecoderData.cpp
+++ b/media/libstagefright/binding/DecoderData.cpp
@@ -181,16 +181,17 @@ VideoDecoderConfig::Update(sp<MetaData>&
 bool
 VideoDecoderConfig::IsValid()
 {
   return display_width > 0 && display_height > 0;
 }
 
 MP4Sample::MP4Sample()
   : mMediaBuffer(nullptr)
+  , decode_timestamp(0)
   , composition_timestamp(0)
   , duration(0)
   , byte_offset(0)
   , is_sync_point(0)
   , data(nullptr)
   , size(0)
 {
 }
@@ -201,16 +202,17 @@ MP4Sample::~MP4Sample()
     mMediaBuffer->release();
   }
 }
 
 void
 MP4Sample::Update()
 {
   sp<MetaData> m = mMediaBuffer->meta_data();
+  decode_timestamp = FindInt64(m, kKeyDecodingTime);
   composition_timestamp = FindInt64(m, kKeyTime);
   duration = FindInt64(m, kKeyDuration);
   byte_offset = FindInt64(m, kKey64BitFileOffset);
   is_sync_point = FindInt32(m, kKeyIsSyncFrame);
   data = reinterpret_cast<uint8_t*>(mMediaBuffer->data());
   size = mMediaBuffer->range_length();
 
   crypto.Update(m);
--- a/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
@@ -132,16 +132,17 @@ class MP4Sample
 public:
   MP4Sample();
   ~MP4Sample();
   void Update();
   void Pad(size_t aPaddingBytes);
 
   stagefright::MediaBuffer* mMediaBuffer;
 
+  Microseconds decode_timestamp;
   Microseconds composition_timestamp;
   Microseconds duration;
   int64_t byte_offset;
   bool is_sync_point;
 
   uint8_t* data;
   size_t size;
 
--- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
@@ -3227,27 +3227,28 @@ status_t MPEG4Source::read(
             mBuffer = NULL;
         }
 
         // fall through
     }
 
     off64_t offset = 0;
     size_t size = 0;
+    uint32_t dts = 0;
     uint32_t cts = 0;
     uint32_t duration = 0;
     bool isSyncSample = false;
     bool newBuffer = false;
     if (mBuffer == NULL) {
         newBuffer = true;
 
         status_t err =
             mSampleTable->getMetaDataForSample(
                     mCurrentSampleIndex, &offset, &size, &cts, &duration,
-                    &isSyncSample);
+                    &isSyncSample, &dts);
 
         if (err != OK) {
             return err;
         }
 
         int32_t max_size;
         CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
         mBuffer = new MediaBuffer(max_size);
@@ -3269,16 +3270,18 @@ status_t MPEG4Source::read(
             CHECK(mBuffer != NULL);
             mBuffer->set_range(0, size);
             mBuffer->meta_data()->clear();
             mBuffer->meta_data()->setInt64(kKey64BitFileOffset, offset);
             if (!mTimescale) {
                 return ERROR_MALFORMED;
             }
             mBuffer->meta_data()->setInt64(
+                    kKeyDecodingTime, ((int64_t)dts * 1000000) / mTimescale);
+            mBuffer->meta_data()->setInt64(
                     kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
             mBuffer->meta_data()->setInt64(
                     kKeyDuration, ((int64_t)duration * 1000000) / mTimescale);
 
             if (targetSampleTimeUs >= 0) {
                 mBuffer->meta_data()->setInt64(
                         kKeyTargetTime, targetSampleTimeUs);
             }
@@ -3396,16 +3399,18 @@ status_t MPEG4Source::read(
         }
 
         mBuffer->meta_data()->clear();
         mBuffer->meta_data()->setInt64(kKey64BitFileOffset, offset);
         if (!mTimescale) {
             return ERROR_MALFORMED;
         }
         mBuffer->meta_data()->setInt64(
+                kKeyDecodingTime, ((int64_t)dts * 1000000) / mTimescale);
+        mBuffer->meta_data()->setInt64(
                 kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
         mBuffer->meta_data()->setInt64(
                 kKeyDuration, ((int64_t)duration * 1000000) / mTimescale);
 
         if (targetSampleTimeUs >= 0) {
             mBuffer->meta_data()->setInt64(
                     kKeyTargetTime, targetSampleTimeUs);
         }
@@ -3475,16 +3480,17 @@ status_t MPEG4Source::fragmentedRead(
             mBuffer = NULL;
         }
 
         // fall through
     }
 
     off64_t offset = 0;
     size_t size = 0;
+    uint32_t dts = 0;
     uint32_t cts = 0;
     uint32_t duration = 0;
     bool isSyncSample = false;
     bool newBuffer = false;
     if (mBuffer == NULL) {
         newBuffer = true;
 
         if (mCurrentSampleIndex >= mCurrentSamples.size()) {
@@ -3514,16 +3520,17 @@ status_t MPEG4Source::fragmentedRead(
             if (mTrackFragmentData.mPresent) {
                 mCurrentTime = mTrackFragmentData.mBaseMediaDecodeTime;
             }
         }
 
         const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
         offset = smpl->offset;
         size = smpl->size;
+        dts = mCurrentTime;
         cts = mCurrentTime + smpl->ctsOffset;
         duration = smpl->duration;
         mCurrentTime += smpl->duration;
         isSyncSample = (mCurrentSampleIndex == 0); // XXX
 
         int32_t max_size;
         CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
         mBuffer = new MediaBuffer(max_size);
@@ -3559,16 +3566,18 @@ status_t MPEG4Source::fragmentedRead(
             }
 
             CHECK(mBuffer != NULL);
             mBuffer->set_range(0, size);
             if (!mTimescale) {
                 return ERROR_MALFORMED;
             }
             mBuffer->meta_data()->setInt64(
+                    kKeyDecodingTime, ((int64_t)dts * 1000000) / mTimescale);
+            mBuffer->meta_data()->setInt64(
                     kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
             mBuffer->meta_data()->setInt64(
                     kKeyDuration, ((int64_t)duration * 1000000) / mTimescale);
 
             if (targetSampleTimeUs >= 0) {
                 mBuffer->meta_data()->setInt64(
                         kKeyTargetTime, targetSampleTimeUs);
             }
@@ -3686,16 +3695,18 @@ status_t MPEG4Source::fragmentedRead(
             CHECK(mBuffer != NULL);
             mBuffer->set_range(0, dstOffset);
         }
 
         if (!mTimescale) {
             return ERROR_MALFORMED;
         }
         mBuffer->meta_data()->setInt64(
+                kKeyDecodingTime, ((int64_t)dts * 1000000) / mTimescale);
+        mBuffer->meta_data()->setInt64(
                 kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
         mBuffer->meta_data()->setInt64(
                 kKeyDuration, ((int64_t)duration * 1000000) / mTimescale);
 
         if (targetSampleTimeUs >= 0) {
             mBuffer->meta_data()->setInt64(
                     kKeyTargetTime, targetSampleTimeUs);
         }
--- a/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp
@@ -136,17 +136,18 @@ status_t SampleIterator::seekTo(uint32_t
     status_t err;
     if ((err = findSampleTime(sampleIndex, &mCurrentSampleTime)) != OK) {
         ALOGE("findSampleTime return error");
         return err;
     }
 
     // mTTSDuration is set by findSampleTime()
     mCurrentSampleDuration = mTTSDuration;
-
+    mCurrentSampleDecodeTime = mTTSSampleTime + mTTSDuration * (sampleIndex -
+        mTTSSampleIndex);
     mCurrentSampleIndex = sampleIndex;
 
     mInitialized = true;
 
     return OK;
 }
 
 status_t SampleIterator::findChunkRange(uint32_t sampleIndex) {
--- a/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
@@ -775,17 +775,18 @@ status_t SampleTable::getSampleSize_l(
 }
 
 status_t SampleTable::getMetaDataForSample(
         uint32_t sampleIndex,
         off64_t *offset,
         size_t *size,
         uint32_t *compositionTime,
         uint32_t *duration,
-        bool *isSyncSample) {
+        bool *isSyncSample,
+        uint32_t *decodeTime) {
     Mutex::Autolock autoLock(mLock);
 
     status_t err;
     if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
         return err;
     }
 
     if (offset) {
@@ -795,16 +796,20 @@ status_t SampleTable::getMetaDataForSamp
     if (size) {
         *size = mSampleIterator->getSampleSize();
     }
 
     if (compositionTime) {
         *compositionTime = mSampleIterator->getSampleTime();
     }
 
+    if (decodeTime) {
+        *decodeTime = mSampleIterator->getSampleDecodeTime();
+    }
+
     if (duration) {
         *duration = mSampleIterator->getSampleDuration();
     }
 
     if (isSyncSample) {
         *isSyncSample = false;
         if (mSyncSampleOffset < 0) {
             // Every sample is a sync sample.
--- a/media/libstagefright/frameworks/av/media/libstagefright/include/SampleIterator.h
+++ b/media/libstagefright/frameworks/av/media/libstagefright/include/SampleIterator.h
@@ -28,16 +28,17 @@ struct SampleIterator {
 
     status_t seekTo(uint32_t sampleIndex);
 
     uint32_t getChunkIndex() const { return mCurrentChunkIndex; }
     uint32_t getDescIndex() const { return mChunkDesc; }
     off64_t getSampleOffset() const { return mCurrentSampleOffset; }
     size_t getSampleSize() const { return mCurrentSampleSize; }
     uint32_t getSampleTime() const { return mCurrentSampleTime; }
+    uint32_t getSampleDecodeTime() const { return mCurrentSampleDecodeTime; }
     uint32_t getSampleDuration() const { return mCurrentSampleDuration; }
 
     status_t getSampleSizeDirect(
             uint32_t sampleIndex, size_t *size);
 
 private:
     SampleTable *mTable;
 
@@ -60,16 +61,17 @@ private:
     uint32_t mTTSSampleTime;
     uint32_t mTTSCount;
     uint32_t mTTSDuration;
 
     uint32_t mCurrentSampleIndex;
     off64_t mCurrentSampleOffset;
     size_t mCurrentSampleSize;
     uint32_t mCurrentSampleTime;
+    uint32_t mCurrentSampleDecodeTime;
     uint32_t mCurrentSampleDuration;
 
     void reset();
     status_t findChunkRange(uint32_t sampleIndex);
     status_t getChunkOffset(uint32_t chunk, off64_t *offset);
     status_t findSampleTime(uint32_t sampleIndex, uint32_t *time);
 
     SampleIterator(const SampleIterator &);
--- a/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h
@@ -62,17 +62,18 @@ public:
     status_t getMaxSampleSize(size_t *size);
 
     status_t getMetaDataForSample(
             uint32_t sampleIndex,
             off64_t *offset,
             size_t *size,
             uint32_t *compositionTime,
             uint32_t *duration = NULL,
-            bool *isSyncSample = NULL);
+            bool *isSyncSample = NULL,
+            uint32_t *decodeTime = NULL);
 
     enum {
         kFlagBefore,
         kFlagAfter,
         kFlagClosest
     };
     status_t findSampleAtTime(
             uint32_t req_time, uint32_t *sample_index, uint32_t flags);