OSDN Git Service

Allow to build with libav and ffmpeg
[android-x86/external-stagefright-plugins.git] / omx / SoftFFmpegVideo.cpp
index 1cba05e..101d3ef 100644 (file)
@@ -86,12 +86,6 @@ void SoftFFmpegVideo::setDefaultCtx(AVCodecContext *avctx, const AVCodec *codec)
     int fast = 1;
 
     avctx->workaround_bugs   = 1;
-    avctx->lowres            = 0;
-    if(avctx->lowres > codec->max_lowres){
-        ALOGW("The maximum value for lowres supported by the decoder is %d",
-                codec->max_lowres);
-        avctx->lowres= codec->max_lowres;
-    }
     avctx->idct_algo         = 0;
     avctx->skip_frame        = AVDISCARD_DEFAULT;
     avctx->skip_idct         = AVDISCARD_DEFAULT;
@@ -99,10 +93,11 @@ void SoftFFmpegVideo::setDefaultCtx(AVCodecContext *avctx, const AVCodec *codec)
     avctx->error_concealment = 3;
     avctx->thread_count      = 0;
 
-    if(avctx->lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
-    if (fast)   avctx->flags2 |= CODEC_FLAG2_FAST;
-    if(codec->capabilities & CODEC_CAP_DR1)
+    if (fast)   avctx->flags2 |= AV_CODEC_FLAG2_FAST;
+#ifdef CODEC_FLAG_EMU_EDGE
+    if (codec->capabilities & AV_CODEC_CAP_DR1)
         avctx->flags |= CODEC_FLAG_EMU_EDGE;
+#endif
 }
 
 status_t SoftFFmpegVideo::initDecoder(enum AVCodecID codecID) {
@@ -142,12 +137,13 @@ void SoftFFmpegVideo::deInitDecoder() {
         }
         if (mCodecAlreadyOpened) {
             avcodec_close(mCtx);
-            av_free(mCtx);
-            mCtx = NULL;
+            mCodecAlreadyOpened = false;
         }
+        av_free(mCtx);
+        mCtx = NULL;
     }
     if (mFrame) {
-        av_freep(&mFrame);
+        av_frame_free(&mFrame);
         mFrame = NULL;
     }
     if (mImgConvertCtx) {
@@ -365,7 +361,7 @@ int32_t SoftFFmpegVideo::handleExtradata() {
             int orig_extradata_size = mCtx->extradata_size;
             mCtx->extradata_size += inHeader->nFilledLen;
             mCtx->extradata = (uint8_t *)realloc(mCtx->extradata,
-                    mCtx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+                    mCtx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
             if (!mCtx->extradata) {
                 ALOGE("ffmpeg video decoder failed to alloc extradata memory.");
                 return ERR_OOM;
@@ -375,7 +371,7 @@ int32_t SoftFFmpegVideo::handleExtradata() {
                     inHeader->pBuffer + inHeader->nOffset,
                     inHeader->nFilledLen);
             memset(mCtx->extradata + mCtx->extradata_size, 0,
-                    FF_INPUT_BUFFER_PADDING_SIZE);
+                    AV_INPUT_BUFFER_PADDING_SIZE);
         }
     }
 
@@ -458,15 +454,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 & AV_CODEC_CAP_DELAY)) {
+        return ERR_FLUSHED;
     }
 
     AVPacket pkt;
@@ -475,6 +476,7 @@ int32_t SoftFFmpegVideo::decodeVideo() {
     av_frame_unref(mFrame);
 
     err = avcodec_decode_video2(mCtx, mFrame, &gotPic, &pkt);
+    av_packet_unref(&pkt);
 
     if (err < 0) {
         ALOGE("ffmpeg video decoder failed to decode frame. (%d)", err);
@@ -484,7 +486,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 & AV_CODEC_CAP_DELAY) &&
+                !inHeader) || inHeader->nFilledLen == 0) {
                 ret = ERR_FLUSHED;
             } else {
                 ret = ERR_NO_FRM;
@@ -494,10 +497,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;
@@ -508,33 +513,34 @@ int32_t SoftFFmpegVideo::drainOneOutputBuffer() {
     BufferInfo *outInfo = *outQueue.begin();
     OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
 
-    AVPicture pict;
+    uint8_t *data[4];
+    int linesize[4];
+
     int64_t pts = AV_NOPTS_VALUE;
     uint8_t *dst = outHeader->pBuffer;
 
     uint32_t width = outputBufferWidth();
     uint32_t height = outputBufferHeight();
 
-    memset(&pict, 0, sizeof(AVPicture));
-    pict.data[0] = dst;
-    pict.data[1] = dst + width * height;
-    pict.data[2] = pict.data[1] + (width / 2  * height / 2);
-    pict.linesize[0] = width;
-    pict.linesize[1] = width / 2;
-    pict.linesize[2] = width / 2;
+    data[0] = dst;
+    data[1] = dst + width * height;
+    data[2] = data[1] + (width / 2  * height / 2);
+    linesize[0] = width;
+    linesize[1] = width / 2;
+    linesize[2] = width / 2;
 
     ALOGV("drainOneOutputBuffer: frame_width=%d frame_height=%d width=%d height=%d ctx_width=%d ctx_height=%d", mFrame->width, mFrame->height, width, height, mCtx->width, mCtx->height);
 
     int sws_flags = SWS_BICUBIC;
     mImgConvertCtx = sws_getCachedContext(mImgConvertCtx,
            mFrame->width, mFrame->height, (AVPixelFormat)mFrame->format, width, height,
-           PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL);
+           AV_PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL);
     if (mImgConvertCtx == NULL) {
         ALOGE("Cannot initialize the conversion context");
         return ERR_SWS_FAILED;
     }
     sws_scale(mImgConvertCtx, mFrame->data, mFrame->linesize,
-            0, height, pict.data, pict.linesize);
+            0, height, data, linesize);
 
     outHeader->nOffset = 0;
     outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2;
@@ -544,9 +550,12 @@ int32_t SoftFFmpegVideo::drainOneOutputBuffer() {
     }
 
     //process timestamps
+#ifndef LIBAV_CONFIG_H
     if (decoder_reorder_pts == -1) {
         pts = av_frame_get_best_effort_timestamp(mFrame);
-    } else if (decoder_reorder_pts) {
+    } else
+#endif
+    if (decoder_reorder_pts) {
         pts = mFrame->pkt_pts;
     } else {
         pts = mFrame->pkt_dts;
@@ -595,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) {
@@ -610,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);
         }
@@ -671,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) {
@@ -680,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);
@@ -733,9 +739,13 @@ void SoftFFmpegVideo::onPortFlushCompleted(OMX_U32 portIndex) {
 
 void SoftFFmpegVideo::onReset() {
     ALOGV("onReset()");
+    enum AVCodecID codecID = mCtx->codec_id;
+    deInitDecoder();
+    initDecoder(codecID);
     SoftVideoDecoderOMXComponent::onReset();
     mSignalledError = false;
     mExtradataReady = false;
+    mEOSStatus = INPUT_DATA_AVAILABLE;
 }
 
 SoftOMXComponent* SoftFFmpegVideo::createSoftOMXComponent(