Bug 1098126 - Remove duplication in MP4 demuxer seek; r=mattwoodrow
authorAnthony Jones <ajones@mozilla.com>
Tue, 16 Dec 2014 18:10:44 +1300
changeset 219892 117b38a298abdb575a577df74400973a1120bff3
parent 219891 9f0d701d11c21dd8b817a531eed55727513b0d7d
child 219893 9d83f03575b91c124a2a4d75c869287806da4b0e
push id10419
push usercbook@mozilla.com
push dateTue, 16 Dec 2014 12:45:27 +0000
treeherderfx-team@ec87657146eb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1098126
milestone37.0a1
Bug 1098126 - Remove duplication in MP4 demuxer seek; r=mattwoodrow
media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
--- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
@@ -107,16 +107,17 @@ private:
     size_t parseNALSize(const uint8_t *data) const;
     status_t parseChunk(off64_t *offset);
     status_t parseTrackFragmentData(off64_t offset, off64_t size);
     status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
     status_t parseTrackFragmentRun(off64_t offset, off64_t size);
     status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
     status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
     void lookForMoof();
+    status_t moveToNextFragment();
 
     struct TrackFragmentHeaderInfo {
         enum Flags {
             kBaseDataOffsetPresent         = 0x01,
             kSampleDescriptionIndexPresent = 0x02,
             kDefaultSampleDurationPresent  = 0x08,
             kDefaultSampleSizePresent      = 0x10,
             kDefaultSampleFlagsPresent     = 0x20,
@@ -3578,35 +3579,59 @@ status_t MPEG4Source::read(
 
         *out = mBuffer;
         mBuffer = NULL;
 
         return OK;
     }
 }
 
+status_t MPEG4Source::moveToNextFragment() {
+    off64_t nextMoof = mNextMoofOffset;
+    mCurrentSamples.clear();
+    mDeferredSaio.clear();
+    mDeferredSaiz.clear();
+    mCurrentSampleIndex = 0;
+    uint32_t hdr[2];
+    do {
+        if (mDataSource->readAt(nextMoof, hdr, 8) < 8) {
+            return ERROR_END_OF_STREAM;
+        }
+        uint64_t chunk_size = ntohl(hdr[0]);
+        uint32_t chunk_type = ntohl(hdr[1]);
+
+        // Skip over anything that isn't a moof
+        if (chunk_type != FOURCC('m', 'o', 'o', 'f')) {
+            nextMoof += chunk_size;
+            continue;
+        }
+        mCurrentMoofOffset = nextMoof;
+        status_t ret = parseChunk(&nextMoof);
+        if (ret != OK) {
+            return ret;
+        }
+    } while (mCurrentSamples.size() == 0);
+    return OK;
+}
+
 status_t MPEG4Source::fragmentedRead(
         MediaBuffer **out, const ReadOptions *options) {
 
     ALOGV("MPEG4Source::fragmentedRead");
 
     CHECK(mStarted);
 
     *out = NULL;
 
     int64_t targetSampleTimeUs = -1;
 
     int64_t seekTimeUs;
     ReadOptions::SeekMode mode;
     if (options && options->getSeekTo(&seekTimeUs, &mode)) {
 
-        mCurrentSamples.clear();
-        mDeferredSaio.clear();
-        mDeferredSaiz.clear();
-        mCurrentSampleIndex = 0;
         int numSidxEntries = mSegments.size();
         if (numSidxEntries != 0) {
             int64_t totalTime = 0;
             off64_t totalOffset = mFirstMoofOffset;
             for (int i = 0; i < numSidxEntries; i++) {
                 const SidxEntry *se = &mSegments[i];
                 if (totalTime + se->mDurationUs > seekTimeUs) {
                     // The requested time is somewhere in this segment
@@ -3619,65 +3644,44 @@ status_t MPEG4Source::fragmentedRead(
                         totalOffset += se->mSize;
                     }
                     break;
                 }
                 totalTime += se->mDurationUs;
                 totalOffset += se->mSize;
             }
             mCurrentMoofOffset = totalOffset;
+            mCurrentSamples.clear();
+            mDeferredSaio.clear();
+            mDeferredSaiz.clear();
+            mCurrentSampleIndex = 0;
+            mCurrentTime = totalTime * mTimescale / 1000000ll;
             mNextMoofOffset = totalOffset;
-            mCurrentTime = totalTime * mTimescale / 1000000ll;
         }
         else {
             mNextMoofOffset = mFirstMoofOffset;
             uint32_t seekTime = (int32_t) ((seekTimeUs * mTimescale) / 1000000ll);
             while (true) {
-
-                uint32_t hdr[2];
-                do {
-                    off64_t moofOffset = mNextMoofOffset; // lastSample.offset + lastSample.size;
-                    if (mDataSource->readAt(moofOffset, hdr, 8) < 8) {
-                        ALOGV("Seek ERROR_END_OF_STREAM\n");
-                        return ERROR_END_OF_STREAM;
-                    }
-                    uint64_t chunk_size = ntohl(hdr[0]);
-                    uint32_t chunk_type = ntohl(hdr[1]);
-                    char chunk[5];
-                    MakeFourCCString(chunk_type, chunk);
-
-                    // If we're pointing to a segment type or sidx box then we skip them.
-                    if (chunk_type != FOURCC('m', 'o', 'o', 'f')) {
-                        mNextMoofOffset += chunk_size;
-                        continue;
-                    }
-                    mCurrentMoofOffset = moofOffset;
-                    status_t ret = parseChunk(&moofOffset);
-                    if (ret != OK) {
-                        return ret;
-                    }
-                } while (mCurrentSamples.size() == 0);
+                status_t ret = moveToNextFragment();
+                if (ret != OK) {
+                    return ret;
+                }
                 uint32_t time = mCurrentTime;
                 int i;
                 for (i = 0; i < mCurrentSamples.size() && time <= seekTime; i++) {
                     const Sample *smpl = &mCurrentSamples[i];
                     if (smpl->isSync()) {
                         mCurrentSampleIndex = i;
                         mCurrentTime = time;
                     }
                     time += smpl->duration;
                 }
                 if (i != mCurrentSamples.size()) {
                     break;
                 }
-
-                mCurrentSamples.clear();
-                mDeferredSaio.clear();
-                mDeferredSaiz.clear();
-                mCurrentSampleIndex = 0;
             }
             ALOGV("Seeking offset %d; %ldus\n", mCurrentTime - seekTime,
                     (((int64_t) mCurrentTime - seekTime) * 1000000ll) / mTimescale);
         }
 
         if (mBuffer != NULL) {
             mBuffer->release();
             mBuffer = NULL;
@@ -3692,42 +3696,20 @@ status_t MPEG4Source::fragmentedRead(
     int64_t cts = 0;
     uint32_t duration = 0;
     bool isSyncSample = false;
     bool newBuffer = false;
     if (mBuffer == NULL) {
         newBuffer = true;
 
         if (mCurrentSampleIndex >= mCurrentSamples.size()) {
-            // move to next fragment
-            off64_t nextMoof = mNextMoofOffset; // lastSample.offset + lastSample.size;
-            mCurrentSamples.clear();
-            mDeferredSaio.clear();
-            mDeferredSaiz.clear();
-            mCurrentSampleIndex = 0;
-            uint32_t hdr[2];
-            do {
-                if (mDataSource->readAt(nextMoof, hdr, 8) < 8) {
-                    return ERROR_END_OF_STREAM;
-                }
-                uint64_t chunk_size = ntohl(hdr[0]);
-                uint32_t chunk_type = ntohl(hdr[1]);
-
-                // If we're pointing to a segment type or sidx box then we skip them.
-                if (chunk_type == FOURCC('s', 't', 'y', 'p') ||
-                    chunk_type == FOURCC('s', 'i', 'd', 'x')) {
-                    nextMoof += chunk_size;
-                    continue;
-                }
-                mCurrentMoofOffset = nextMoof;
-                status_t ret = parseChunk(&nextMoof);
-                if (ret != OK) {
-                    return ret;
-                }
-            } while (mCurrentSamples.size() == 0);
+            status_t ret = moveToNextFragment();
+            if (ret != OK) {
+                return ret;
+            }
         }
 
         const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
         offset = smpl->offset;
         size = smpl->size;
         dts = mCurrentTime;
         cts = mCurrentTime + smpl->ctsOffset;
         duration = smpl->duration;