[FFmpeg-devel] [PATCH 3/4] lavf/concat: switch to new BSF API.

Nicolas George george at nsup.org
Thu May 19 09:47:11 CEST 2016


Signed-off-by: Nicolas George <george at nsup.org>
---
 libavformat/concatdec.c | 165 ++++++++++++++++++++++--------------------------
 1 file changed, 76 insertions(+), 89 deletions(-)


Unchanged.


diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c
index b3a430e..bbea158 100644
--- a/libavformat/concatdec.c
+++ b/libavformat/concatdec.c
@@ -34,7 +34,7 @@ typedef enum ConcatMatchMode {
 } ConcatMatchMode;
 
 typedef struct ConcatStream {
-    AVBitStreamFilterContext *bsf;
+    AVBSFContext *bsf;
     AVCodecContext *avctx;
     int out_stream_index;
 } ConcatStream;
@@ -58,6 +58,7 @@ typedef struct {
     ConcatFile *cur_file;
     unsigned nb_files;
     AVFormatContext *avf;
+    ConcatStream *active_bsf;
     int safe;
     int seekable;
     int eof;
@@ -195,39 +196,54 @@ static int detect_stream_specific(AVFormatContext *avf, int idx)
 {
     ConcatContext *cat = avf->priv_data;
     AVStream *st = cat->avf->streams[idx];
+    AVStream *ost;
     ConcatStream *cs = &cat->cur_file->streams[idx];
-    AVBitStreamFilterContext *bsf;
+    AVBSFContext *bsf = NULL;
+    const AVBitStreamFilter *filter;
+    const char *filter_name = NULL;
     int ret;
 
-    if (cat->auto_convert && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
-        (st->codecpar->extradata_size < 4 || AV_RB32(st->codecpar->extradata) != 1)) {
-        av_log(cat->avf, AV_LOG_INFO,
-               "Auto-inserting h264_mp4toannexb bitstream filter\n");
-        if (!(bsf = av_bitstream_filter_init("h264_mp4toannexb"))) {
-            av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb bitstream filter "
-                   "required for H.264 streams\n");
-            return AVERROR_BSF_NOT_FOUND;
-        }
-        cs->bsf = bsf;
-
-        cs->avctx = avcodec_alloc_context3(NULL);
-        if (!cs->avctx)
-            return AVERROR(ENOMEM);
-
-        /* This really should be part of the bsf work.
-           Note: input bitstream filtering will not work with bsf that
-           create extradata from the first packet. */
-        av_freep(&st->codecpar->extradata);
-        st->codecpar->extradata_size = 0;
+    if (cs->out_stream_index < 0)
+        return 0;
+    ost = avf->streams[cs->out_stream_index];
 
-        ret = avcodec_parameters_to_context(cs->avctx, st->codecpar);
-        if (ret < 0) {
-            avcodec_free_context(&cs->avctx);
-            return ret;
-        }
+    if (cat->auto_convert && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
+        (st->codecpar->extradata_size < 4 || AV_RB32(st->codecpar->extradata) != 1))
+        filter_name = "h264_mp4toannexb";
 
+    if (filter_name)
+        av_log(cat->avf, AV_LOG_INFO,
+               "Auto-inserting %s bitstream filter\n", filter_name);
+    else
+        filter_name = "null";
+
+    filter = av_bsf_get_by_name(filter_name);
+    if (!filter) {
+        av_log(avf, AV_LOG_ERROR,
+               "%s bitstream filter required for %s streams\n",
+               filter_name, avcodec_get_name(st->codecpar->codec_id));
+        return AVERROR_BSF_NOT_FOUND;
     }
+    ret = av_bsf_alloc(filter, &bsf);
+    if (ret < 0)
+        return ret;
+    ret = avcodec_parameters_copy(bsf->par_in, st->codecpar);
+    if (ret < 0)
+        goto fail;
+    bsf->time_base_in = st->time_base;
+    ret = av_bsf_init(bsf);
+    if (ret < 0)
+        goto fail;
+    ret = avcodec_parameters_copy(ost->codecpar, bsf->par_out);
+    if (ret < 0)
+        goto fail;
+    ost->time_base = bsf->time_base_out;
+    cs->bsf = bsf;
     return 0;
+
+fail:
+    av_bsf_free(&bsf);
+    return ret;
 }
 
 static int match_streams_one_to_one(AVFormatContext *avf)
@@ -368,8 +384,7 @@ static int concat_read_close(AVFormatContext *avf)
         for (j = 0; j < cat->files[i].nb_streams; j++) {
             if (cat->files[i].streams[j].avctx)
                 avcodec_free_context(&cat->files[i].streams[j].avctx);
-            if (cat->files[i].streams[j].bsf)
-                av_bitstream_filter_close(cat->files[i].streams[j].bsf);
+            av_bsf_free(&cat->files[i].streams[j].bsf);
         }
         av_freep(&cat->files[i].streams);
         av_dict_free(&cat->files[i].metadata);
@@ -518,62 +533,6 @@ static int open_next_file(AVFormatContext *avf)
     return open_file(avf, fileno);
 }
 
-static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt)
-{
-    AVStream *st = avf->streams[cs->out_stream_index];
-    AVBitStreamFilterContext *bsf;
-    AVPacket pkt2;
-    int ret;
-
-    av_assert0(cs->out_stream_index >= 0);
-    for (bsf = cs->bsf; bsf; bsf = bsf->next) {
-        pkt2 = *pkt;
-
-        ret = av_bitstream_filter_filter(bsf, cs->avctx, NULL,
-                                         &pkt2.data, &pkt2.size,
-                                         pkt->data, pkt->size,
-                                         !!(pkt->flags & AV_PKT_FLAG_KEY));
-        if (ret < 0) {
-            av_packet_unref(pkt);
-            return ret;
-        }
-
-        if (cs->avctx->extradata_size > st->codecpar->extradata_size) {
-            int eret;
-            if (st->codecpar->extradata)
-                av_freep(&st->codecpar->extradata);
-
-            eret = ff_alloc_extradata(st->codecpar, cs->avctx->extradata_size);
-            if (eret < 0) {
-                av_packet_unref(pkt);
-                return AVERROR(ENOMEM);
-            }
-            st->codecpar->extradata_size = cs->avctx->extradata_size;
-            memcpy(st->codecpar->extradata, cs->avctx->extradata, cs->avctx->extradata_size);
-        }
-
-        av_assert0(pkt2.buf);
-        if (ret == 0 && pkt2.data != pkt->data) {
-            if ((ret = av_copy_packet(&pkt2, pkt)) < 0) {
-                av_free(pkt2.data);
-                return ret;
-            }
-            ret = 1;
-        }
-        if (ret > 0) {
-            av_packet_unref(pkt);
-            pkt2.buf = av_buffer_create(pkt2.data, pkt2.size,
-                                        av_buffer_default_free, NULL, 0);
-            if (!pkt2.buf) {
-                av_free(pkt2.data);
-                return AVERROR(ENOMEM);
-            }
-        }
-        *pkt = pkt2;
-    }
-    return 0;
-}
-
 /* Returns true if the packet dts is greater or equal to the specified outpoint. */
 static int packet_after_outpoint(ConcatContext *cat, AVPacket *pkt)
 {
@@ -599,6 +558,29 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
         return AVERROR(EIO);
 
     while (1) {
+        /* First, try to drain the bitstream filter.
+           Note: bitstream filtering on input will notwork with bitstream
+           filters that change the DTS (it would require re-interleaving
+           with the other streams) or that use the first packets to change
+           the extradata. */
+        cs = cat->active_bsf;
+        if (cs) {
+            ret = av_bsf_receive_packet(cs->bsf, pkt);
+            if (ret == AVERROR(EAGAIN)) {
+                cat->active_bsf = NULL;
+                continue;
+            }
+            /* Currently, only h264_mp4toannexb is used, and it does not
+               require flushing: therefore, do not bother with that. If a
+               filter requires flushing, then EOF must be sent to all
+               streans, and the resulting packets must be ordered by DTS:
+               only implement that when there is a test case. */
+            av_assert0(ret != AVERROR_EOF);
+            if (ret < 0)
+                return ret;
+            break;
+        }
+
         ret = av_read_frame(cat->avf, pkt);
         if (ret == AVERROR_EOF) {
             if ((ret = open_next_file(avf)) < 0)
@@ -622,11 +604,16 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
             av_packet_unref(pkt);
             continue;
         }
-        pkt->stream_index = cs->out_stream_index;
-        break;
+
+        if (!cs->bsf)
+            break;
+        ret = av_bsf_send_packet(cs->bsf, pkt);
+        if (ret < 0)
+            return ret;
+        cat->active_bsf = cs;
+        /* Receive the filtered packet on the next run of the loop */
     }
-    if ((ret = filter_packet(avf, cs, pkt)))
-        return ret;
+    pkt->stream_index = cs->out_stream_index;
 
     st = cat->avf->streams[pkt->stream_index];
     av_log(avf, AV_LOG_DEBUG, "file:%d stream:%d pts:%s pts_time:%s dts:%s dts_time:%s",
-- 
2.8.1



More information about the ffmpeg-devel mailing list