[FFmpeg-devel] [PATCH 5/6] ffmpeg: use new decode API

wm4 nfxjfg at googlemail.com
Tue Mar 1 19:21:40 CET 2016


---
Unfortunately requires a hack to make FATE pass: ffmpeg.c will pass
a flush AVPacket (data/size are null) with the dts field set, and will
expect to get the dts back with the flushed frame. Should probably be
fixed somehow. I'm not even sure if this is valid API usage (with the
old API).
---
 ffmpeg.c           | 44 +++++++++++++++++++++++++++++++++-----------
 libavcodec/utils.c |  4 +++-
 2 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/ffmpeg.c b/ffmpeg.c
index f24ee41..54eb14e 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -1916,6 +1916,31 @@ int guess_input_channel_layout(InputStream *ist)
     return 1;
 }
 
+static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt)
+{
+    int ret;
+    int consumed = 0;
+
+    *got_frame = 0;
+
+    // This relies on the fact that the decoder will not buffer additional
+    // packets internally, but returns AVERROR(EAGAIN) if there are still
+    // decoded frames to be returned.
+    ret = avcodec_send_packet(avctx, pkt);
+    if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
+        return ret;
+    if (ret >= 0)
+        consumed = pkt->size;
+
+    ret = avcodec_receive_frame(avctx, frame);
+    if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
+        return ret;
+    if (ret >= 0)
+        *got_frame = 1;
+
+    return consumed;
+}
+
 static void check_decode_result(InputStream *ist, int *got_output, int ret)
 {
     if (*got_output || ret<0)
@@ -1946,7 +1971,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
     decoded_frame = ist->decoded_frame;
 
     update_benchmark(NULL);
-    ret = avcodec_decode_audio4(avctx, decoded_frame, got_output, pkt);
+    ret = decode(avctx, decoded_frame, got_output, pkt);
     update_benchmark("decode_audio %d.%d", ist->file_index, ist->st->index);
 
     if (ret >= 0 && avctx->sample_rate <= 0) {
@@ -2072,8 +2097,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
     pkt->dts  = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base);
 
     update_benchmark(NULL);
-    ret = avcodec_decode_video2(ist->dec_ctx,
-                                decoded_frame, got_output, pkt);
+    ret = decode(ist->dec_ctx, decoded_frame, got_output, pkt);
     update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index);
 
     // The following line may be required in some cases where there is no parser
@@ -2141,8 +2165,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
                ist->st->time_base.num, ist->st->time_base.den);
     }
 
-    pkt->size = 0;
-
     if (ist->st->sample_aspect_ratio.num)
         decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
 
@@ -2181,12 +2203,12 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
                 break;
         } else
             f = decoded_frame;
-        ret = av_buffersrc_add_frame_flags(ist->filters[i]->filter, f, AV_BUFFERSRC_FLAG_PUSH);
-        if (ret == AVERROR_EOF) {
-            ret = 0; /* ignore */
-        } else if (ret < 0) {
+        err = av_buffersrc_add_frame_flags(ist->filters[i]->filter, f, AV_BUFFERSRC_FLAG_PUSH);
+        if (err == AVERROR_EOF) {
+            err = 0; /* ignore */
+        } else if (err < 0) {
             av_log(NULL, AV_LOG_FATAL,
-                   "Failed to inject frame into filter network: %s\n", av_err2str(ret));
+                   "Failed to inject frame into filter network: %s\n", av_err2str(err));
             exit_program(1);
         }
     }
@@ -2357,7 +2379,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo
 
         // touch data and size only if not EOF
         if (pkt) {
-            if(ist->dec_ctx->codec_type != AVMEDIA_TYPE_AUDIO)
+            if(ist->dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE)
                 ret = avpkt.size;
             avpkt.data += ret;
             avpkt.size -= ret;
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index a0ec269..0667754 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -2747,7 +2747,9 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke
 
     if (!avpkt || !avpkt->size) {
         avctx->internal->draining = 1;
-        avpkt = NULL;
+        // Crazy things ffmpeg.c requires: it sets a dts on a flush packet, and
+        // wants this dts back in the flushed AVFrame.
+        //avpkt = NULL;
 
         if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY))
             return 0;
-- 
2.7.0



More information about the ffmpeg-devel mailing list