Bug 877461. Part 3: Retry libstagefright audio/video decoding if it fails due to a timeout. r=sotaro
☠☠ backed out by 6a5f8ebc836a ☠ ☠
authorRobert O'Callahan <robert@ocallahan.org>
Thu, 06 Jun 2013 11:43:43 +1200
changeset 145702 1ba9dc37c2efb9187e0a1a853fad2bac571112f7
parent 145701 c6bc2193a72b316ce2546c745922a9798745b60a
child 145704 fd3eb4b732920eb8538e1900f76c123b6dce7ab2
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro
bugs877461
milestone24.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 877461. Part 3: Retry libstagefright audio/video decoding if it fails due to a timeout. r=sotaro
content/media/omx/MediaOmxReader.cpp
content/media/omx/OmxDecoder.cpp
--- a/content/media/omx/MediaOmxReader.cpp
+++ b/content/media/omx/MediaOmxReader.cpp
@@ -135,16 +135,21 @@ bool MediaOmxReader::DecodeVideoFrame(bo
     MPAPI::VideoFrame frame;
     frame.mGraphicBuffer = nullptr;
     frame.mShouldSkip = false;
     if (!mOmxDecoder->ReadVideo(&frame, aTimeThreshold, aKeyframeSkip, doSeek)) {
       mVideoQueue.Finish();
       return false;
     }
 
+    // Ignore empty buffer which stagefright media read will sporadically return
+    if (frame.mSize == 0 && !frame.mGraphicBuffer) {
+      return true;
+    }
+
     parsed++;
     if (frame.mShouldSkip && mSkipCount < MAX_DROPPED_FRAMES) {
       mSkipCount++;
       return true;
     }
 
     mSkipCount = 0;
 
--- a/content/media/omx/OmxDecoder.cpp
+++ b/content/media/omx/OmxDecoder.cpp
@@ -556,21 +556,25 @@ bool OmxDecoder::ReadVideo(VideoFrame *a
     MediaSource::ReadOptions options;
     options.setSeekTo(aTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
     err = mVideoSource->read(&mVideoBuffer, &options);
     {
       Mutex::Autolock autoLock(mSeekLock);
       mIsVideoSeeking = false;
       ReleaseAllPendingVideoBuffersLocked();
     }
+
+    aDoSeek = false;
   } else {
     err = mVideoSource->read(&mVideoBuffer);
   }
 
-  if (err == OK && mVideoBuffer->range_length() > 0) {
+  aFrame->mSize = 0;
+
+  if (err == OK) {
     int64_t timeUs;
     int32_t unreadable;
     int32_t keyFrame;
 
     if (!mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs) ) {
       NS_WARNING("OMX decoder did not return frame time");
       return false;
     }
@@ -597,51 +601,52 @@ bool OmxDecoder::ReadVideo(VideoFrame *a
 
       mozilla::layers::SurfaceDescriptor descWrapper(newDescriptor);
       aFrame->mGraphicBuffer = new mozilla::layers::VideoGraphicBuffer(this, mVideoBuffer, descWrapper);
       aFrame->mRotation = mVideoRotation;
       aFrame->mTimeUs = timeUs;
       aFrame->mKeyFrame = keyFrame;
       aFrame->Y.mWidth = mVideoWidth;
       aFrame->Y.mHeight = mVideoHeight;
-    } else {
+    } else if (mVideoBuffer->range_length() > 0) {
       char *data = static_cast<char *>(mVideoBuffer->data()) + mVideoBuffer->range_offset();
       size_t length = mVideoBuffer->range_length();
 
       if (unreadable) {
         LOG(PR_LOG_DEBUG, "video frame is unreadable");
       }
 
       if (!ToVideoFrame(aFrame, timeUs, data, length, keyFrame)) {
         return false;
       }
     }
 
     if (aKeyframeSkip && timeUs < aTimeUs) {
       aFrame->mShouldSkip = true;
     }
-
   }
   else if (err == INFO_FORMAT_CHANGED) {
     // If the format changed, update our cached info.
     if (!SetVideoFormat()) {
       return false;
     } else {
       return ReadVideo(aFrame, aTimeUs, aKeyframeSkip, aDoSeek);
     }
   }
   else if (err == ERROR_END_OF_STREAM) {
     return false;
   }
-  else if (err == UNKNOWN_ERROR) {
-    // This sometimes is used to mean "out of memory", but regardless,
-    // don't keep trying to decode if the decoder doesn't want to.
-    return false;
+  else if (err == -ETIMEDOUT) {
+    LOG(PR_LOG_DEBUG, "OmxDecoder::ReadVideo timed out, will retry");
+    return true;
   }
-  else if (err != OK && err != -ETIMEDOUT) {
+  else {
+    // UNKNOWN_ERROR is sometimes is used to mean "out of memory", but
+    // regardless, don't keep trying to decode if the decoder doesn't want to.
+    LOG(PR_LOG_DEBUG, "OmxDecoder::ReadVideo failed, err=%d", err);
     return false;
   }
 
   return true;
 }
 
 bool OmxDecoder::ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs)
 {
@@ -659,16 +664,17 @@ bool OmxDecoder::ReadAudio(AudioFrame *a
       err = mAudioSource->read(&mAudioBuffer, &options);
     } else {
       err = mAudioSource->read(&mAudioBuffer);
     }
   }
   mAudioMetadataRead = false;
 
   aSeekTimeUs = -1;
+  aFrame->mSize = 0;
 
   if (err == OK && mAudioBuffer && mAudioBuffer->range_length() != 0) {
     int64_t timeUs;
     if (!mAudioBuffer->meta_data()->findInt64(kKeyTime, &timeUs))
       return false;
 
     return ToAudioFrame(aFrame, timeUs,
                         mAudioBuffer->data(),
@@ -684,20 +690,22 @@ bool OmxDecoder::ReadAudio(AudioFrame *a
       return ReadAudio(aFrame, aSeekTimeUs);
     }
   }
   else if (err == ERROR_END_OF_STREAM) {
     if (aFrame->mSize == 0) {
       return false;
     }
   }
-  else if (err == UNKNOWN_ERROR) {
-    return false;
+  else if (err == -ETIMEDOUT) {
+    LOG(PR_LOG_DEBUG, "OmxDecoder::ReadAudio timed out, will retry");
+    return true;
   }
-  else if (err != OK && err != -ETIMEDOUT) {
+  else if (err != OK) {
+    LOG(PR_LOG_DEBUG, "OmxDecoder::ReadAudio failed, err=%d", err);
     return false;
   }
 
   return true;
 }
 
 nsresult OmxDecoder::Play() {
   if (!mPaused) {