[FFmpeg-devel] [PATCH 2/3] lavf/concat: switch to new BSF API.
Nicolas George
george at nsup.org
Thu Apr 28 11:06:44 CEST 2016
Signed-off-by: Nicolas George <george at 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
More information about the ffmpeg-devel
mailing list