diff options
author | Anton Khirnov <anton@khirnov.net> | 2016-09-22 15:24:34 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2016-10-16 20:27:30 +0200 |
commit | 8e2ea691351c5079cdab245ff7bfa5c0f3e3bfe4 (patch) | |
tree | 9bad99ec03a48d9d04a7c8f35240e5f2694a3c30 /libavformat/utils.c | |
parent | 89b35a139e838deeb32ec20d8d034c81014401d0 (diff) | |
download | ffmpeg-8e2ea691351c5079cdab245ff7bfa5c0f3e3bfe4.tar.gz |
lavf: use the new bitstream filter for extracting extradata
This also fixes a minor bug introduced in the codecpar conversion, where
the termination condition for extracting the extradata does not match
the actual extradata setting code. As a result, the packet durations
made up by lavf go back to their values before the codecpar conversion.
That is of little consequence since that code should eventually be
dropped completely.
Diffstat (limited to 'libavformat/utils.c')
-rw-r--r-- | libavformat/utils.c | 123 |
1 files changed, 110 insertions, 13 deletions
diff --git a/libavformat/utils.c b/libavformat/utils.c index 0e94b15b72..1c93326ab2 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2089,6 +2089,104 @@ static int get_std_framerate(int i) return ((const int[]) { 24, 30, 60, 12, 15 })[i - 60 * 12] * 1000 * 12; } +static int extract_extradata_init(AVStream *st) +{ + AVStreamInternal *i = st->internal; + const AVBitStreamFilter *f; + int ret; + + f = av_bsf_get_by_name("extract_extradata"); + if (!f) + goto finish; + + i->extract_extradata.pkt = av_packet_alloc(); + if (!i->extract_extradata.pkt) + return AVERROR(ENOMEM); + + ret = av_bsf_alloc(f, &i->extract_extradata.bsf); + if (ret < 0) + goto fail; + + ret = avcodec_parameters_copy(i->extract_extradata.bsf->par_in, + st->codecpar); + if (ret < 0) + goto fail; + + i->extract_extradata.bsf->time_base_in = st->time_base; + + /* if init fails here, we assume extracting extradata is just not + * supported for this codec, so we return success */ + ret = av_bsf_init(i->extract_extradata.bsf); + if (ret < 0) { + av_bsf_free(&i->extract_extradata.bsf); + ret = 0; + } + +finish: + i->extract_extradata.inited = 1; + + return 0; +fail: + av_bsf_free(&i->extract_extradata.bsf); + av_packet_free(&i->extract_extradata.pkt); + return ret; +} + +static int extract_extradata(AVStream *st, AVPacket *pkt) +{ + AVStreamInternal *i = st->internal; + AVPacket *pkt_ref; + int ret; + + if (!i->extract_extradata.inited) { + ret = extract_extradata_init(st); + if (ret < 0) + return ret; + } + + if (i->extract_extradata.inited && !i->extract_extradata.bsf) + return 0; + + pkt_ref = i->extract_extradata.pkt; + ret = av_packet_ref(pkt_ref, pkt); + if (ret < 0) + return ret; + + ret = av_bsf_send_packet(i->extract_extradata.bsf, pkt_ref); + if (ret < 0) { + av_packet_unref(pkt_ref); + return ret; + } + + while (ret >= 0 && !i->avctx->extradata) { + int extradata_size; + uint8_t *extradata; + + ret = av_bsf_receive_packet(i->extract_extradata.bsf, pkt_ref); + if (ret < 0) { + if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + return ret; + continue; + } + + extradata = av_packet_get_side_data(pkt_ref, AV_PKT_DATA_NEW_EXTRADATA, + &extradata_size); + + if (extradata) { + i->avctx->extradata = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!i->avctx->extradata) { + av_packet_unref(pkt_ref); + return AVERROR(ENOMEM); + } + memcpy(i->avctx->extradata, extradata, extradata_size); + i->avctx->extradata_size = extradata_size; + } + av_packet_unref(pkt_ref); + } + + return 0; +} + int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) { int i, count, ret, read_size, j; @@ -2194,8 +2292,10 @@ FF_ENABLE_DEPRECATION_WARNINGS st->codec_info_nb_frames < fps_analyze_framecount && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) break; - if (st->parser && st->parser->parser->split && - !st->codecpar->extradata) + if (!st->codecpar->extradata && + !st->internal->avctx->extradata && + (!st->internal->extract_extradata.inited || + st->internal->extract_extradata.bsf)) break; if (st->first_dts == AV_NOPTS_VALUE && st->codec_info_nb_frames < ic->max_ts_probe && @@ -2331,17 +2431,10 @@ FF_ENABLE_DEPRECATION_WARNINGS break; } } - if (st->parser && st->parser->parser->split && !avctx->extradata) { - int i = st->parser->parser->split(avctx, pkt->data, pkt->size); - if (i > 0 && i < FF_MAX_EXTRADATA_SIZE) { - avctx->extradata_size = i; - avctx->extradata = av_mallocz(avctx->extradata_size + - AV_INPUT_BUFFER_PADDING_SIZE); - if (!avctx->extradata) - return AVERROR(ENOMEM); - memcpy(avctx->extradata, pkt->data, - avctx->extradata_size); - } + if (!st->internal->avctx->extradata) { + ret = extract_extradata(st, pkt); + if (ret < 0) + goto find_stream_info_err; } /* If still no information, we try to open the codec and to @@ -2468,6 +2561,8 @@ FF_ENABLE_DEPRECATION_WARNINGS find_stream_info_err: for (i = 0; i < ic->nb_streams; i++) { av_freep(&ic->streams[i]->info); + av_bsf_free(&ic->streams[i]->internal->extract_extradata.bsf); + av_packet_free(&ic->streams[i]->internal->extract_extradata.pkt); } return ret; } @@ -2575,6 +2670,8 @@ static void free_stream(AVStream **pst) if (st->internal) { avcodec_free_context(&st->internal->avctx); + av_bsf_free(&st->internal->extract_extradata.bsf); + av_packet_free(&st->internal->extract_extradata.pkt); } av_freep(&st->internal); |