Commit 1c193ac1 authored by James Almer's avatar James Almer

Merge commit '8e2ea691'

* commit '8e2ea691':
  lavf: use the new bitstream filter for extracting extradata
Merged-by: 's avatarJames Almer <jamrial@gmail.com>
parents 7ebc9f8d 8e2ea691
...@@ -178,6 +178,15 @@ struct AVStreamInternal { ...@@ -178,6 +178,15 @@ struct AVStreamInternal {
enum AVCodecID orig_codec_id; 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) * Whether the internal avctx needs to be updated from codecpar (after a late change to codecpar)
*/ */
......
...@@ -3370,6 +3370,104 @@ void ff_rfps_calculate(AVFormatContext *ic) ...@@ -3370,6 +3370,104 @@ void ff_rfps_calculate(AVFormatContext *ic)
} }
} }
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 avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
{ {
int i, count = 0, ret = 0, j; int i, count = 0, ret = 0, j;
...@@ -3529,8 +3627,10 @@ FF_ENABLE_DEPRECATION_WARNINGS ...@@ -3529,8 +3627,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
if (count < fps_analyze_framecount) if (count < fps_analyze_framecount)
break; break;
} }
if (st->parser && st->parser->parser->split && if (!st->codecpar->extradata &&
!st->internal->avctx->extradata) !st->internal->avctx->extradata &&
(!st->internal->extract_extradata.inited ||
st->internal->extract_extradata.bsf))
break; break;
if (st->first_dts == AV_NOPTS_VALUE && if (st->first_dts == AV_NOPTS_VALUE &&
!(ic->iformat->flags & AVFMT_NOTIMESTAMPS) && !(ic->iformat->flags & AVFMT_NOTIMESTAMPS) &&
...@@ -3680,17 +3780,10 @@ FF_ENABLE_DEPRECATION_WARNINGS ...@@ -3680,17 +3780,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
ff_rfps_add_frame(ic, st, pkt->dts); ff_rfps_add_frame(ic, st, pkt->dts);
#endif #endif
if (st->parser && st->parser->parser->split && !avctx->extradata) { if (!st->internal->avctx->extradata) {
int i = st->parser->parser->split(avctx, pkt->data, pkt->size); ret = extract_extradata(st, pkt);
if (i > 0 && i < FF_MAX_EXTRADATA_SIZE) { if (ret < 0)
avctx->extradata_size = i; goto find_stream_info_err;
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 still no information, we try to open the codec and to /* If still no information, we try to open the codec and to
...@@ -3950,6 +4043,8 @@ find_stream_info_err: ...@@ -3950,6 +4043,8 @@ find_stream_info_err:
if (st->info) if (st->info)
av_freep(&st->info->duration_error); av_freep(&st->info->duration_error);
av_freep(&ic->streams[i]->info); 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) if (ic->pb)
av_log(ic, AV_LOG_DEBUG, "After avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d frames:%d\n", av_log(ic, AV_LOG_DEBUG, "After avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d frames:%d\n",
...@@ -4137,6 +4232,8 @@ static void free_stream(AVStream **pst) ...@@ -4137,6 +4232,8 @@ static void free_stream(AVStream **pst)
av_bsf_free(&st->internal->bsfcs[i]); av_bsf_free(&st->internal->bsfcs[i]);
av_freep(&st->internal->bsfcs); 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); av_freep(&st->internal);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment