OSDN Git Service

stagefright-plugins: Fix eos flush problem.
authorKeith Mok <kmok@cyngn.com>
Fri, 22 Apr 2016 21:55:11 +0000 (14:55 -0700)
committerKeith Mok <kmok@cyngn.com>
Fri, 22 Apr 2016 22:21:23 +0000 (15:21 -0700)
When input stream eos encounter, the output
buffer are not flushed correctly. a null data
must be passed to the ffmpeg decodebr
(avcodec_decode_video2) when the codec is
with flag CODEC_CAP_DELAY.

This fix cts testEOSBehaviorMpeg4 and testCodecEarlyEOSMpeg4
under package android.media.cts.DecoderTest.

This can be simulate on other devices by disable the h/w
mpeg4 omx component.

FEIJ-88

Change-Id: I84ffd7c2a1e4844afe4c891f0440ed4e3c7effe3

omx/SoftFFmpegVideo.cpp

index 36b35c6..8dd29be 100644 (file)
@@ -458,15 +458,20 @@ int32_t SoftFFmpegVideo::decodeVideo() {
     int len = 0, err = 0;
     int gotPic = false;
     int32_t ret = ERR_OK;
-    bool is_flush = (mEOSStatus != INPUT_DATA_AVAILABLE);
     List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
     BufferInfo *inInfo = NULL;
     OMX_BUFFERHEADERTYPE *inHeader = NULL;
 
-    if (!is_flush) {
+    if (!inQueue.empty()) {
         inInfo = *inQueue.begin();
-        CHECK(inInfo != NULL);
-        inHeader = inInfo->mHeader;
+        if (inInfo != NULL)  {
+            inHeader = inInfo->mHeader;
+        }
+    }
+
+    if (mEOSStatus == INPUT_EOS_SEEN && (!inHeader || inHeader->nFilledLen == 0)
+        && !(mCtx->codec->capabilities & CODEC_CAP_DELAY)) {
+        return ERR_FLUSHED;
     }
 
     AVPacket pkt;
@@ -485,7 +490,8 @@ int32_t SoftFFmpegVideo::decodeVideo() {
         if (!gotPic) {
             ALOGI("ffmpeg video decoder failed to get frame.");
             //stop sending empty packets if the decoder is finished
-            if (is_flush && mCtx->codec->capabilities & CODEC_CAP_DELAY) {
+            if (mEOSStatus != INPUT_DATA_AVAILABLE && mCtx->codec->capabilities & CODEC_CAP_DELAY &&
+                !inHeader || inHeader->nFilledLen == 0) {
                 ret = ERR_FLUSHED;
             } else {
                 ret = ERR_NO_FRM;
@@ -495,10 +501,12 @@ int32_t SoftFFmpegVideo::decodeVideo() {
         }
     }
 
-    if (!is_flush) {
+    if (!inQueue.empty()) {
         inQueue.erase(inQueue.begin());
-        inInfo->mOwnedByUs = false;
-        notifyEmptyBufferDone(inHeader);
+        if (inInfo) {
+            inInfo->mOwnedByUs = false;
+            notifyEmptyBufferDone(inHeader);
+        }
     }
 
     return ret;
@@ -596,12 +604,6 @@ void SoftFFmpegVideo::drainAllOutputBuffers() {
        return;
    }
 
-    if(!(mCtx->codec->capabilities & CODEC_CAP_DELAY)) {
-        drainEOSOutputBuffer();
-        mEOSStatus = OUTPUT_FRAMES_FLUSHED;
-        return;
-    }
-
     while (!outQueue.empty()) {
         int32_t err = decodeVideo();
         if (err < ERR_OK) {
@@ -611,6 +613,8 @@ void SoftFFmpegVideo::drainAllOutputBuffers() {
         } else if (err == ERR_FLUSHED) {
             drainEOSOutputBuffer();
             return;
+        } else if (err == ERR_NO_FRM) {
+            continue;
         } else {
             CHECK_EQ(err, ERR_OK);
         }
@@ -672,6 +676,11 @@ void SoftFFmpegVideo::onQueueFilled(OMX_U32 portIndex __unused) {
             continue;
         }
 
+        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+            mEOSStatus = INPUT_EOS_SEEN;
+            continue;
+        }
+
         if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
             ALOGD("ffmpeg got codecconfig buffer");
             if (handleExtradata() != ERR_OK) {
@@ -681,10 +690,6 @@ void SoftFFmpegVideo::onQueueFilled(OMX_U32 portIndex __unused) {
             continue;
         }
 
-        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
-            mEOSStatus = INPUT_EOS_SEEN;
-        }
-
         if (!mCodecAlreadyOpened) {
             if (openDecoder() != ERR_OK) {
                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
@@ -737,6 +742,7 @@ void SoftFFmpegVideo::onReset() {
     SoftVideoDecoderOMXComponent::onReset();
     mSignalledError = false;
     mExtradataReady = false;
+    mEOSStatus = INPUT_DATA_AVAILABLE;
 }
 
 SoftOMXComponent* SoftFFmpegVideo::createSoftOMXComponent(