mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-12-12 18:10:13 +01:00
lavf: use the new bitstream filter for extracting extradata
This merges commits8e2ea69135and096a8effa3by Anton Khirnov, with the following change: - extract_extradata_check() is added to know if the codec is supported by the bsf before trying to initialize it. This behaviour is similar to the old AVCodecParser.split checks. The FATE reference changes are due to the filtered out NAL units that the old AVCodecParser.split implementation left alone. Decoding is unchanged as the functions that parse extradata simply ignored said unnecessary NAL units. Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user