diff options
-rw-r--r-- | libavformat/internal.h | 9 | ||||
-rw-r--r-- | libavformat/utils.c | 146 | ||||
-rw-r--r-- | tests/ref/fate/copy-trac2211-avi | 4 | ||||
-rw-r--r-- | tests/ref/fate/h264_mp4toannexb_ticket2991 | 2 | ||||
-rw-r--r-- | tests/ref/fate/h264_mp4toannexb_ticket5927 | 2 | ||||
-rw-r--r-- | tests/ref/fate/h264_mp4toannexb_ticket5927_2 | 2 | ||||
-rw-r--r-- | tests/ref/fate/segment-mp4-to-ts | 2 |
7 files changed, 148 insertions, 19 deletions
diff --git a/libavformat/internal.h b/libavformat/internal.h index 63a1724cfa..c856945ce9 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -178,6 +178,15 @@ struct AVStreamInternal { enum AVCodecID orig_codec_id; + /* the context for extracting extradata in find_stream_info() + * inited=1/bsf=NULL signals that extracting is not possible (codec not + * supported) */ + struct { + AVBSFContext *bsf; + AVPacket *pkt; + int inited; + } extract_extradata; + /** * Whether the internal avctx needs to be updated from codecpar (after a late change to codecpar) */ diff --git a/libavformat/utils.c b/libavformat/utils.c index a059046a2c..ba82a766dc 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -3370,6 +3370,127 @@ void ff_rfps_calculate(AVFormatContext *ic) } } +static int extract_extradata_check(AVStream *st) +{ + const AVBitStreamFilter *f; + + f = av_bsf_get_by_name("extract_extradata"); + if (!f) + return 0; + + if (f->codec_ids) { + const enum AVCodecID *ids; + for (ids = f->codec_ids; *ids != AV_CODEC_ID_NONE; ids++) + if (*ids == st->codecpar->codec_id) + return 1; + } + + return 0; +} + +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; + + /* check that the codec id is supported */ + ret = extract_extradata_check(st); + if (!ret) + 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 = 0, ret = 0, j; @@ -3529,8 +3650,10 @@ FF_ENABLE_DEPRECATION_WARNINGS if (count < fps_analyze_framecount) break; } - if (st->parser && st->parser->parser->split && - !st->internal->avctx->extradata) + if (!st->internal->avctx->extradata && + (!st->internal->extract_extradata.inited || + st->internal->extract_extradata.bsf) && + extract_extradata_check(st)) break; if (st->first_dts == AV_NOPTS_VALUE && !(ic->iformat->flags & AVFMT_NOTIMESTAMPS) && @@ -3680,17 +3803,10 @@ FF_ENABLE_DEPRECATION_WARNINGS if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) ff_rfps_add_frame(ic, st, pkt->dts); #endif - 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 @@ -3950,6 +4066,8 @@ find_stream_info_err: if (st->info) av_freep(&st->info->duration_error); 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); } if (ic->pb) av_log(ic, AV_LOG_DEBUG, "After avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d frames:%d\n", @@ -4137,6 +4255,8 @@ static void free_stream(AVStream **pst) av_bsf_free(&st->internal->bsfcs[i]); av_freep(&st->internal->bsfcs); } + av_bsf_free(&st->internal->extract_extradata.bsf); + av_packet_free(&st->internal->extract_extradata.pkt); } av_freep(&st->internal); diff --git a/tests/ref/fate/copy-trac2211-avi b/tests/ref/fate/copy-trac2211-avi index c22ca3d4da..007349e572 100644 --- a/tests/ref/fate/copy-trac2211-avi +++ b/tests/ref/fate/copy-trac2211-avi @@ -1,5 +1,5 @@ -dd199ecb167b2fa0fc0c17638a655e1c *tests/data/fate/copy-trac2211-avi.avi -1777926 tests/data/fate/copy-trac2211-avi.avi +6f6b211cbc8de9871e8e09e64048e2f9 *tests/data/fate/copy-trac2211-avi.avi +1777924 tests/data/fate/copy-trac2211-avi.avi #tb 0: 1/14 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/fate/h264_mp4toannexb_ticket2991 b/tests/ref/fate/h264_mp4toannexb_ticket2991 index 4c73d7da44..76bdf3cae7 100644 --- a/tests/ref/fate/h264_mp4toannexb_ticket2991 +++ b/tests/ref/fate/h264_mp4toannexb_ticket2991 @@ -1,6 +1,6 @@ 05d66e60ab22ee004720e0051af0fe74 *tests/data/fate/h264_mp4toannexb_ticket2991.h264 1985815 tests/data/fate/h264_mp4toannexb_ticket2991.h264 -#extradata 0: 79, 0x1ec61105 +#extradata 0: 47, 0x3a590d55 #tb 0: 1/1200000 #media_type 0: video #codec_id 0: h264 diff --git a/tests/ref/fate/h264_mp4toannexb_ticket5927 b/tests/ref/fate/h264_mp4toannexb_ticket5927 index 60a1deb8e1..95e35c4d80 100644 --- a/tests/ref/fate/h264_mp4toannexb_ticket5927 +++ b/tests/ref/fate/h264_mp4toannexb_ticket5927 @@ -1,6 +1,6 @@ a3b02fd09392e01619cebc959d4d9ff2 *tests/data/fate/h264_mp4toannexb_ticket5927.h264 595583 tests/data/fate/h264_mp4toannexb_ticket5927.h264 -#extradata 0: 59, 0xf10e1136 +#extradata 0: 33, 0x84fe08f8 #tb 0: 1/1200000 #media_type 0: video #codec_id 0: h264 diff --git a/tests/ref/fate/h264_mp4toannexb_ticket5927_2 b/tests/ref/fate/h264_mp4toannexb_ticket5927_2 index b5f11e3432..8db6a7e54a 100644 --- a/tests/ref/fate/h264_mp4toannexb_ticket5927_2 +++ b/tests/ref/fate/h264_mp4toannexb_ticket5927_2 @@ -1,6 +1,6 @@ a3b02fd09392e01619cebc959d4d9ff2 *tests/data/fate/h264_mp4toannexb_ticket5927_2.h264 595583 tests/data/fate/h264_mp4toannexb_ticket5927_2.h264 -#extradata 0: 59, 0xf10e1136 +#extradata 0: 33, 0x84fe08f8 #tb 0: 1/1200000 #media_type 0: video #codec_id 0: h264 diff --git a/tests/ref/fate/segment-mp4-to-ts b/tests/ref/fate/segment-mp4-to-ts index 8513027b9f..847c1a297d 100644 --- a/tests/ref/fate/segment-mp4-to-ts +++ b/tests/ref/fate/segment-mp4-to-ts @@ -1,4 +1,4 @@ -#extradata 0: 795, 0x395101dc +#extradata 0: 50, 0x4f1b0df9 #tb 0: 1/90000 #media_type 0: video #codec_id 0: h264 |