Bug 1120075: Use Movie Extend Header's duration as fallback when available. r=kentuckyfriedtakahe
authorJean-Yves Avenard <jyavenard@mozilla.com>
Fri, 16 Jan 2015 23:49:01 +1100
changeset 224162 0bf6cb3e40dcd971ae25e4679c38daf6ef4904c6
parent 224161 f1d37b792c4a29731d237effd798f918218c43e6
child 224163 936880d652de4cc4d2ef90b5681d8fefc4a5efbd
push id54147
push userjyavenard@mozilla.com
push dateFri, 16 Jan 2015 12:54:44 +0000
treeherdermozilla-inbound@797403411392 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskentuckyfriedtakahe
bugs1120075
milestone38.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 1120075: Use Movie Extend Header's duration as fallback when available. r=kentuckyfriedtakahe
media/libstagefright/binding/mp4_demuxer.cpp
media/libstagefright/frameworks/av/include/media/stagefright/MetaData.h
media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
--- a/media/libstagefright/binding/mp4_demuxer.cpp
+++ b/media/libstagefright/binding/mp4_demuxer.cpp
@@ -139,16 +139,23 @@ MP4Demuxer::Init()
       if (index->IsFragmented() && !mVideoConfig.crypto.valid) {
         mPrivate->mVideoIterator = new SampleIterator(index);
       }
     }
   }
   sp<MetaData> metaData = e->getMetaData();
   mCrypto.Update(metaData);
 
+  int64_t movieDuration;
+  if (!mVideoConfig.duration && !mAudioConfig.duration &&
+      metaData->findInt64(kKeyMovieDuration, &movieDuration)) {
+    // No duration were found in either tracks, use movie extend header box one.
+    mVideoConfig.duration = mAudioConfig.duration = movieDuration;
+  }
+
   return mPrivate->mAudio.get() || mPrivate->mVideo.get();
 }
 
 bool
 MP4Demuxer::HasValidAudio()
 {
   mMonitor->AssertCurrentThreadOwns();
   return mPrivate->mAudio.get() && mAudioConfig.IsValid();
--- a/media/libstagefright/frameworks/av/include/media/stagefright/MetaData.h
+++ b/media/libstagefright/frameworks/av/include/media/stagefright/MetaData.h
@@ -62,16 +62,17 @@ enum {
     kKeyIsCodecConfig     = 'conf',  // int32_t (bool)
     kKeyTime              = 'time',  // int64_t (usecs)
     kKeyDecodingTime      = 'decT',  // int64_t (decoding timestamp in usecs)
     kKeyNTPTime           = 'ntpT',  // uint64_t (ntp-timestamp)
     kKeyTargetTime        = 'tarT',  // int64_t (usecs)
     kKeyDriftTime         = 'dftT',  // int64_t (usecs)
     kKeyAnchorTime        = 'ancT',  // int64_t (usecs)
     kKeyDuration          = 'dura',  // int64_t (usecs)
+    kKeyMovieDuration     = 'mdur',  // int64_t (usecs)
     kKeyColorFormat       = 'colf',
     kKeyPlatformPrivate   = 'priv',  // pointer
     kKeyDecoderComponent  = 'decC',  // cstring
     kKeyBufferID          = 'bfID',
     kKeyMaxInputSize      = 'inpS',
     kKeyThumbnailTime     = 'thbT',  // int64_t (usecs)
     kKeyTrackID           = 'trID',
     kKeyIsDRM             = 'idrm',  // int32_t (bool)
--- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
@@ -1692,16 +1692,56 @@ status_t MPEG4Extractor::parseChunk(off6
             if (s.length()) {
                 mFileMetaData->setCString(kKeyDate, s.string());
             }
 
             *offset += chunk_size;
             break;
         }
 
+        case FOURCC('m', 'e', 'h', 'd'):
+        {
+            if (chunk_data_size < 8) {
+                return ERROR_MALFORMED;
+            }
+
+            uint8_t version;
+            if (mDataSource->readAt(
+                        data_offset, &version, sizeof(version))
+                    < (ssize_t)sizeof(version)) {
+                return ERROR_IO;
+            }
+            if (version > 1) {
+                break;
+            }
+            int64_t duration = 0;
+            if (version == 1) {
+                if (mDataSource->readAt(
+                            data_offset + 4, &duration, sizeof(duration))
+                        < (ssize_t)sizeof(duration)) {
+                    return ERROR_IO;
+                }
+                duration = ntoh64(duration);
+            } else {
+                uint32_t duration32;
+                if (mDataSource->readAt(
+                            data_offset + 4, &duration32, sizeof(duration32))
+                        < (ssize_t)sizeof(duration32)) {
+                    return ERROR_IO;
+                }
+                duration = ntohl(duration32);
+            }
+            if (duration) {
+              mFileMetaData->setInt64(kKeyMovieDuration, duration * 1000LL);
+            }
+
+            *offset += chunk_size;
+            break;
+        }
+
         case FOURCC('m', 'd', 'a', 't'):
         {
             ALOGV("mdat chunk, drm: %d", mIsDrm);
             if (!mIsDrm) {
                 *offset += chunk_size;
                 break;
             }