Signed-off-by: Nicolas George <geo...@nsup.org> --- libavformat/concatdec.c | 165 ++++++++++++++++++++++-------------------------- 1 file changed, 76 insertions(+), 89 deletions(-)
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.0.rc3 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel