summaryrefslogtreecommitdiff
path: root/libavformat/utils.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2014-06-18 20:42:52 +0200
committerAnton Khirnov <anton@khirnov.net>2016-02-23 17:01:58 +0100
commit9200514ad8717c63f82101dc394f4378854325bf (patch)
tree566b8d48565a88303363198acc81de06363daa7a /libavformat/utils.c
parenta8068346e48e123f8d3bdf4d64464d81e53e5fc7 (diff)
lavf: replace AVStream.codec with AVStream.codecpar
Currently, AVStream contains an embedded AVCodecContext instance, which is used by demuxers to export stream parameters to the caller and by muxers to receive stream parameters from the caller. It is also used internally as the codec context that is passed to parsers. In addition, it is also widely used by the callers as the decoding (when demuxer) or encoding (when muxing) context, though this has been officially discouraged since Libav 11. There are multiple important problems with this approach: - the fields in AVCodecContext are in general one of * stream parameters * codec options * codec state However, it's not clear which ones are which. It is consequently unclear which fields are a demuxer allowed to set or a muxer allowed to read. This leads to erratic behaviour depending on whether decoding or encoding is being performed or not (and whether it uses the AVStream embedded codec context). - various synchronization issues arising from the fact that the same context is used by several different APIs (muxers/demuxers, parsers, bitstream filters and encoders/decoders) simultaneously, with there being no clear rules for who can modify what and the different processes being typically delayed with respect to each other. - avformat_find_stream_info() making it necessary to support opening and closing a single codec context multiple times, thus complicating the semantics of freeing various allocated objects in the codec context. Those problems are resolved by replacing the AVStream embedded codec context with a newly added AVCodecParameters instance, which stores only the stream parameters exported by the demuxers or read by the muxers.
Diffstat (limited to 'libavformat/utils.c')
-rw-r--r--libavformat/utils.c323
1 files changed, 232 insertions, 91 deletions
diff --git a/libavformat/utils.c b/libavformat/utils.c
index c5cc8b951c..a70746aa99 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -167,8 +167,14 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st,
fmt->name, score);
for (i = 0; fmt_id_type[i].name; i++) {
if (!strcmp(fmt->name, fmt_id_type[i].name)) {
- st->codec->codec_id = fmt_id_type[i].id;
- st->codec->codec_type = fmt_id_type[i].type;
+ st->codecpar->codec_id = fmt_id_type[i].id;
+ st->codecpar->codec_type = fmt_id_type[i].type;
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+ st->codec->codec_type = st->codecpar->codec_type;
+ st->codec->codec_id = st->codecpar->codec_id;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
break;
}
}
@@ -253,11 +259,33 @@ static int queue_attached_pictures(AVFormatContext *s)
return 0;
}
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+static int update_stream_avctx(AVFormatContext *s)
+{
+ int i, ret;
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+
+ if (!st->internal->need_codec_update)
+ continue;
+
+ ret = avcodec_parameters_to_context(st->codec, st->codecpar);
+ if (ret < 0)
+ return ret;
+
+ st->internal->need_codec_update = 0;
+ }
+ return 0;
+}
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
int avformat_open_input(AVFormatContext **ps, const char *filename,
AVInputFormat *fmt, AVDictionary **options)
{
AVFormatContext *s = *ps;
- int ret = 0;
+ int i, ret = 0;
AVDictionary *tmp = NULL;
ID3v2ExtraMeta *id3v2_extra_meta = NULL;
@@ -321,6 +349,13 @@ int avformat_open_input(AVFormatContext **ps, const char *filename,
s->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;
+#if FF_API_LAVF_AVCTX
+ update_stream_avctx(s);
+#endif
+
+ for (i = 0; i < s->nb_streams; i++)
+ s->streams[i]->internal->orig_codec_id = s->streams[i]->codecpar->codec_id;
+
if (options) {
av_dict_free(options);
*options = tmp;
@@ -342,7 +377,7 @@ fail:
static int probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt)
{
- if (st->codec->codec_id == AV_CODEC_ID_PROBE) {
+ if (st->codecpar->codec_id == AV_CODEC_ID_PROBE) {
AVProbeData *pd = &st->probe_data;
av_log(s, AV_LOG_DEBUG, "probing stream %d\n", st->index);
--st->probe_packets;
@@ -368,7 +403,7 @@ static int probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt)
av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)) {
set_codec_from_probe_data(s, st, pd, st->probe_packets > 0
? AVPROBE_SCORE_MAX / 4 : 0);
- if (st->codec->codec_id != AV_CODEC_ID_PROBE) {
+ if (st->codecpar->codec_id != AV_CODEC_ID_PROBE) {
pd->buf_size = 0;
av_freep(&pd->buf);
av_log(s, AV_LOG_DEBUG, "probed stream %d\n", st->index);
@@ -389,7 +424,7 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
if (pktl) {
*pkt = pktl->pkt;
st = s->streams[pkt->stream_index];
- if (st->codec->codec_id != AV_CODEC_ID_PROBE ||
+ if (st->codecpar->codec_id != AV_CODEC_ID_PROBE ||
!st->probe_packets ||
s->internal->raw_packet_buffer_remaining_size < pkt->size) {
AVProbeData *pd;
@@ -441,22 +476,22 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
st = s->streams[pkt->stream_index];
- switch (st->codec->codec_type) {
+ switch (st->codecpar->codec_type) {
case AVMEDIA_TYPE_VIDEO:
if (s->video_codec_id)
- st->codec->codec_id = s->video_codec_id;
+ st->codecpar->codec_id = s->video_codec_id;
break;
case AVMEDIA_TYPE_AUDIO:
if (s->audio_codec_id)
- st->codec->codec_id = s->audio_codec_id;
+ st->codecpar->codec_id = s->audio_codec_id;
break;
case AVMEDIA_TYPE_SUBTITLE:
if (s->subtitle_codec_id)
- st->codec->codec_id = s->subtitle_codec_id;
+ st->codecpar->codec_id = s->subtitle_codec_id;
break;
}
- if (!pktl && (st->codec->codec_id != AV_CODEC_ID_PROBE ||
+ if (!pktl && (st->codecpar->codec_id != AV_CODEC_ID_PROBE ||
!st->probe_packets))
return ret;
@@ -479,13 +514,13 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
void ff_compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, AVStream *st,
AVCodecParserContext *pc, AVPacket *pkt)
{
- AVRational codec_framerate = s->iformat ? st->codec->framerate :
- av_inv_q(st->codec->time_base);
+ AVRational codec_framerate = s->iformat ? st->internal->avctx->framerate :
+ (AVRational){ 0, 1 };
int frame_size;
*pnum = 0;
*pden = 0;
- switch (st->codec->codec_type) {
+ switch (st->codecpar->codec_type) {
case AVMEDIA_TYPE_VIDEO:
if (st->avg_frame_rate.num) {
*pnum = st->avg_frame_rate.den;
@@ -505,16 +540,16 @@ void ff_compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, AVStrea
/* If this codec can be interlaced or progressive then we need
* a parser to compute duration of a packet. Thus if we have
* no parser in such case leave duration undefined. */
- if (st->codec->ticks_per_frame > 1 && !pc)
+ if (st->internal->avctx->ticks_per_frame > 1 && !pc)
*pnum = *pden = 0;
}
break;
case AVMEDIA_TYPE_AUDIO:
- frame_size = av_get_audio_frame_duration(st->codec, pkt->size);
- if (frame_size <= 0 || st->codec->sample_rate <= 0)
+ frame_size = av_get_audio_frame_duration2(st->codecpar, pkt->size);
+ if (frame_size <= 0 || st->codecpar->sample_rate <= 0)
break;
*pnum = frame_size;
- *pden = st->codec->sample_rate;
+ *pden = st->codecpar->sample_rate;
break;
default:
break;
@@ -591,10 +626,10 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st,
pktl->pkt.dts == AV_NOPTS_VALUE &&
!pktl->pkt.duration) {
pktl->pkt.dts = cur_dts;
- if (!st->codec->has_b_frames)
+ if (!st->internal->avctx->has_b_frames)
pktl->pkt.pts = cur_dts;
cur_dts += duration;
- if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO)
+ if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
pktl->pkt.duration = duration;
} else
break;
@@ -616,7 +651,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
pkt->dts = AV_NOPTS_VALUE;
/* do we have a video B-frame ? */
- delay = st->codec->has_b_frames;
+ delay = st->internal->avctx->has_b_frames;
presentation_delayed = 0;
/* XXX: need has_b_frame, but cannot get it if the codec is
@@ -641,7 +676,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
pkt->dts = AV_NOPTS_VALUE;
}
- if (pkt->duration == 0 && st->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
+ if (pkt->duration == 0 && st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
ff_compute_frame_duration(s, &num, &den, st, pc, pkt);
if (den && num) {
pkt->duration = av_rescale_rnd(1, num * (int64_t) st->time_base.den,
@@ -679,7 +714,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
/* Interpolate PTS and DTS if they are not present. We skip H.264
* currently because delay and has_b_frames are not reliably set. */
if ((delay == 0 || (delay == 1 && pc)) &&
- st->codec->codec_id != AV_CODEC_ID_H264) {
+ st->codecpar->codec_id != AV_CODEC_ID_H264) {
if (presentation_delayed) {
/* DTS = decompression timestamp */
/* PTS = presentation timestamp */
@@ -702,9 +737,9 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
} else if (pkt->pts != AV_NOPTS_VALUE ||
pkt->dts != AV_NOPTS_VALUE ||
pkt->duration ||
- st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+ st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
int duration = pkt->duration;
- if (!duration && st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+ if (!duration && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
ff_compute_frame_duration(s, &num, &den, st, pc, pkt);
if (den && num) {
duration = av_rescale_rnd(1,
@@ -740,7 +775,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
if (pkt->dts == AV_NOPTS_VALUE)
pkt->dts = st->pts_buffer[0];
// We skipped it above so we try here.
- if (st->codec->codec_id == AV_CODEC_ID_H264)
+ if (st->codecpar->codec_id == AV_CODEC_ID_H264)
// This should happen on the first packet
update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts);
if (pkt->dts > st->cur_dts)
@@ -752,7 +787,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
presentation_delayed, delay, pkt->pts, pkt->dts, st->cur_dts);
/* update flags */
- if (is_intra_only(st->codec->codec_id))
+ if (is_intra_only(st->codecpar->codec_id))
pkt->flags |= AV_PKT_FLAG_KEY;
#if FF_API_CONVERGENCE_DURATION
FF_DISABLE_DEPRECATION_WARNINGS
@@ -796,7 +831,7 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
int len;
av_init_packet(&out_pkt);
- len = av_parser_parse2(st->parser, st->codec,
+ len = av_parser_parse2(st->parser, st->internal->avctx,
&out_pkt.data, &out_pkt.size, data, size,
pkt->pts, pkt->dts, pkt->pos);
@@ -819,11 +854,11 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
/* set the duration */
out_pkt.duration = 0;
- if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
- if (st->codec->sample_rate > 0) {
+ if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+ if (st->internal->avctx->sample_rate > 0) {
out_pkt.duration =
av_rescale_q_rnd(st->parser->duration,
- (AVRational) { 1, st->codec->sample_rate },
+ (AVRational) { 1, st->internal->avctx->sample_rate },
st->time_base,
AV_ROUND_DOWN);
}
@@ -928,7 +963,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
cur_pkt.size, cur_pkt.duration, cur_pkt.flags);
if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE)) {
- st->parser = av_parser_init(st->codec->codec_id);
+ st->parser = av_parser_init(st->codecpar->codec_id);
if (!st->parser)
/* no parser available: just output the raw packets */
st->need_parsing = AVSTREAM_PARSE_NONE;
@@ -969,6 +1004,10 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
av_opt_set_dict_val(s, "metadata", NULL, AV_OPT_SEARCH_CHILDREN);
}
+#if FF_API_LAVF_AVCTX
+ update_stream_avctx(s);
+#endif
+
if (s->debug & FF_FDEBUG_TS)
av_log(s, AV_LOG_DEBUG,
"read_frame_internal stream=%d, pts=%"PRId64", dts=%"PRId64", "
@@ -1057,12 +1096,12 @@ int av_find_default_stream_index(AVFormatContext *s)
return -1;
for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
- if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+ if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
!(st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
return i;
}
if (first_audio_index < 0 &&
- st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+ st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
first_audio_index = i;
}
return first_audio_index >= 0 ? first_audio_index : 0;
@@ -1665,12 +1704,12 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic)
int bit_rate = 0;
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
- if (st->codec->bit_rate > 0) {
- if (INT_MAX - st->codec->bit_rate < bit_rate) {
+ if (st->codecpar->bit_rate > 0) {
+ if (INT_MAX - st->codecpar->bit_rate < bit_rate) {
bit_rate = 0;
break;
}
- bit_rate += st->codec->bit_rate;
+ bit_rate += st->codecpar->bit_rate;
}
}
ic->bit_rate = bit_rate;
@@ -1712,7 +1751,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->start_time == AV_NOPTS_VALUE && st->first_dts == AV_NOPTS_VALUE)
- av_log(st->codec, AV_LOG_WARNING,
+ av_log(ic, AV_LOG_WARNING,
"start time is not set in estimate_timings_from_pts\n");
if (st->parser) {
@@ -1822,7 +1861,7 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
static int has_codec_parameters(AVStream *st)
{
- AVCodecContext *avctx = st->codec;
+ AVCodecContext *avctx = st->internal->avctx;
int val;
switch (avctx->codec_type) {
@@ -1846,14 +1885,15 @@ static int has_codec_parameters(AVStream *st)
static int has_decode_delay_been_guessed(AVStream *st)
{
- return st->codec->codec_id != AV_CODEC_ID_H264 ||
+ return st->internal->avctx->codec_id != AV_CODEC_ID_H264 ||
st->info->nb_decoded_frames >= 6;
}
/* returns 1 or 0 if or if not decoded data was returned, or a negative error */
-static int try_decode_frame(AVStream *st, AVPacket *avpkt,
+static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt,
AVDictionary **options)
{
+ AVCodecContext *avctx = st->internal->avctx;
const AVCodec *codec;
int got_picture = 1, ret = 0;
AVFrame *frame = av_frame_alloc();
@@ -1862,11 +1902,17 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt,
if (!frame)
return AVERROR(ENOMEM);
- if (!avcodec_is_open(st->codec) && !st->info->found_decoder) {
+ if (!avcodec_is_open(avctx) && !st->info->found_decoder) {
AVDictionary *thread_opt = NULL;
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
codec = st->codec->codec ? st->codec->codec
- : avcodec_find_decoder(st->codec->codec_id);
+ : avcodec_find_decoder(st->codecpar->codec_id);
+FF_ENABLE_DEPRECATION_WARNINGS
+#else
+ codec = avcodec_find_decoder(st->codecpar->codec_id);
+#endif
if (!codec) {
st->info->found_decoder = -1;
@@ -1877,7 +1923,7 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt,
/* Force thread count to 1 since the H.264 decoder will not extract
* SPS and PPS to extradata during multi-threaded decoding. */
av_dict_set(options ? options : &thread_opt, "threads", "1", 0);
- ret = avcodec_open2(st->codec, codec, options ? options : &thread_opt);
+ ret = avcodec_open2(avctx, codec, options ? options : &thread_opt);
if (!options)
av_dict_free(&thread_opt);
if (ret < 0) {
@@ -1897,15 +1943,15 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt,
ret >= 0 &&
(!has_codec_parameters(st) || !has_decode_delay_been_guessed(st) ||
(!st->codec_info_nb_frames &&
- (st->codec->codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF)))) {
+ (avctx->codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF)))) {
got_picture = 0;
- switch (st->codec->codec_type) {
+ switch (avctx->codec_type) {
case AVMEDIA_TYPE_VIDEO:
- ret = avcodec_decode_video2(st->codec, frame,
+ ret = avcodec_decode_video2(avctx, frame,
&got_picture, &pkt);
break;
case AVMEDIA_TYPE_AUDIO:
- ret = avcodec_decode_audio4(st->codec, frame, &got_picture, &pkt);
+ ret = avcodec_decode_audio4(avctx, frame, &got_picture, &pkt);
break;
default:
break;
@@ -2047,6 +2093,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
{
int i, count, ret, read_size, j;
AVStream *st;
+ AVCodecContext *avctx;
AVPacket pkt1, *pkt;
int64_t old_offset = avio_tell(ic->pb);
// new streams might appear, no options for those
@@ -2056,30 +2103,58 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
const AVCodec *codec;
AVDictionary *thread_opt = NULL;
st = ic->streams[i];
+ avctx = st->internal->avctx;
// only for the split stuff
if (!st->parser && !(ic->flags & AVFMT_FLAG_NOPARSE)) {
- st->parser = av_parser_init(st->codec->codec_id);
+ st->parser = av_parser_init(st->codecpar->codec_id);
if (st->need_parsing == AVSTREAM_PARSE_HEADERS && st->parser)
st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
}
+
+ /* check if the caller has overridden the codec id */
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (st->codec->codec_id != st->internal->orig_codec_id) {
+ st->codecpar->codec_id = st->codec->codec_id;
+ st->codecpar->codec_type = st->codec->codec_type;
+ st->internal->orig_codec_id = st->codec->codec_id;
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ if (st->codecpar->codec_id != st->internal->orig_codec_id)
+ st->internal->orig_codec_id = st->codecpar->codec_id;
+
+ ret = avcodec_parameters_to_context(avctx, st->codecpar);
+ if (ret < 0)
+ goto find_stream_info_err;
+ if (st->codecpar->codec_id != AV_CODEC_ID_PROBE &&
+ st->codecpar->codec_id != AV_CODEC_ID_NONE)
+ st->internal->avctx_inited = 1;
+
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
codec = st->codec->codec ? st->codec->codec
- : avcodec_find_decoder(st->codec->codec_id);
+ : avcodec_find_decoder(st->codecpar->codec_id);
+FF_ENABLE_DEPRECATION_WARNINGS
+#else
+ codec = avcodec_find_decoder(st->codecpar->codec_id);
+#endif
/* Force thread count to 1 since the H.264 decoder will not extract
* SPS and PPS to extradata during multi-threaded decoding. */
av_dict_set(options ? &options[i] : &thread_opt, "threads", "1", 0);
/* Ensure that subtitle_header is properly set. */
- if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE
- && codec && !st->codec->codec)
- avcodec_open2(st->codec, codec,
+ if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE
+ && codec && !avctx->codec)
+ avcodec_open2(avctx, codec,
options ? &options[i] : &thread_opt);
// Try to just open decoders, in case this is enough to get parameters.
if (!has_codec_parameters(st)) {
- if (codec && !st->codec->codec)
- avcodec_open2(st->codec, codec,
+ if (codec && !avctx->codec)
+ avcodec_open2(avctx, codec,
options ? &options[i] : &thread_opt);
}
if (!options)
@@ -2117,15 +2192,15 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
/* variable fps and no guess at the real fps */
if (!st->avg_frame_rate.num &&
st->codec_info_nb_frames < fps_analyze_framecount &&
- st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+ st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
break;
if (st->parser && st->parser->parser->split &&
- !st->codec->extradata)
+ !st->codecpar->extradata)
break;
if (st->first_dts == AV_NOPTS_VALUE &&
st->codec_info_nb_frames < ic->max_ts_probe &&
- (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
- st->codec->codec_type == AVMEDIA_TYPE_AUDIO))
+ (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
+ st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO))
break;
}
if (i == ic->nb_streams) {
@@ -2166,7 +2241,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
/* flush the decoders */
if (st->info->found_decoder == 1) {
do {
- err = try_decode_frame(st, &empty_pkt,
+ err = try_decode_frame(ic, st, &empty_pkt,
(options && i < orig_nb_streams)
? &options[i] : NULL);
} while (err > 0 && !has_codec_parameters(st));
@@ -2177,7 +2252,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
"decoding for stream %d failed\n", st->index);
} else if (!has_codec_parameters(st)) {
char buf[256];
- avcodec_string(buf, sizeof(buf), st->codec, 0);
+ avcodec_string(buf, sizeof(buf), st->internal->avctx, 0);
av_log(ic, AV_LOG_WARNING,
"Could not find codec parameters (%s)\n", buf);
} else {
@@ -2199,6 +2274,14 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
read_size += pkt->size;
st = ic->streams[pkt->stream_index];
+ avctx = st->internal->avctx;
+ if (!st->internal->avctx_inited) {
+ ret = avcodec_parameters_to_context(avctx, st->codecpar);
+ if (ret < 0)
+ goto find_stream_info_err;
+ st->internal->avctx_inited = 1;
+ }
+
if (pkt->dts != AV_NOPTS_VALUE && st->codec_info_nb_frames > 1) {
/* check for non-increasing dts */
if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
@@ -2248,16 +2331,16 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
break;
}
}
- if (st->parser && st->parser->parser->split && !st->codec->extradata) {
- int i = st->parser->parser->split(st->codec, pkt->data, pkt->size);
+ 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) {
- st->codec->extradata_size = i;
- st->codec->extradata = av_mallocz(st->codec->extradata_size +
- AV_INPUT_BUFFER_PADDING_SIZE);
- if (!st->codec->extradata)
+ avctx->extradata_size = i;
+ avctx->extradata = av_mallocz(avctx->extradata_size +
+ AV_INPUT_BUFFER_PADDING_SIZE);
+ if (!avctx->extradata)
return AVERROR(ENOMEM);
- memcpy(st->codec->extradata, pkt->data,
- st->codec->extradata_size);
+ memcpy(avctx->extradata, pkt->data,
+ avctx->extradata_size);
}
}
@@ -2270,7 +2353,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
* least one frame of codec data, this makes sure the codec initializes
* the channel configuration and does not only trust the values from
* the container. */
- try_decode_frame(st, pkt,
+ try_decode_frame(ic, st, pkt,
(options && i < orig_nb_streams) ? &options[i] : NULL);
if (ic->flags & AVFMT_FLAG_NOBUFFER)
@@ -2283,11 +2366,12 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
// close codecs which were opened in try_decode_frame()
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
- avcodec_close(st->codec);
+ avcodec_close(st->internal->avctx);
}
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
- if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ avctx = st->internal->avctx;
+ if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
/* estimate average framerate if not set by demuxer */
if (!st->avg_frame_rate.num &&
st->info->fps_last_dts != st->info->fps_first_dts) {
@@ -2322,12 +2406,12 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
best_fps, 12 * 1001, INT_MAX);
}
- } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
- if (!st->codec->bits_per_coded_sample)
- st->codec->bits_per_coded_sample =
- av_get_bits_per_sample(st->codec->codec_id);
+ } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
+ if (!avctx->bits_per_coded_sample)
+ avctx->bits_per_coded_sample =
+ av_get_bits_per_sample(avctx->codec_id);
// set stream disposition based on audio service type
- switch (st->codec->audio_service_type) {
+ switch (avctx->audio_service_type) {
case AV_AUDIO_SERVICE_TYPE_EFFECTS:
st->disposition = AV_DISPOSITION_CLEAN_EFFECTS;
break;
@@ -2351,9 +2435,38 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
compute_chapters_end(ic);
+ /* update the stream parameters from the internal codec contexts */
+ for (i = 0; i < ic->nb_streams; i++) {
+ st = ic->streams[i];
+ if (!st->internal->avctx_inited)
+ continue;
+
+ ret = avcodec_parameters_from_context(st->codecpar, st->internal->avctx);
+ if (ret < 0)
+ goto find_stream_info_err;
+
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+ ret = avcodec_parameters_to_context(st->codec, st->codecpar);
+ if (ret < 0)
+ goto find_stream_info_err;
+
+ if (st->internal->avctx->subtitle_header) {
+ st->codec->subtitle_header = av_malloc(st->internal->avctx->subtitle_header_size);
+ if (!st->codec->subtitle_header)
+ goto find_stream_info_err;
+ st->codec->subtitle_header_size = st->internal->avctx->subtitle_header_size;
+ memcpy(st->codec->subtitle_header, st->internal->avctx->subtitle_header,
+ st->codec->subtitle_header_size);
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+ st->internal->avctx_inited = 0;
+ }
+
find_stream_info_err:
for (i = 0; i < ic->nb_streams; i++) {
- ic->streams[i]->codec->thread_count = 0;
av_freep(&ic->streams[i]->info);
}
return ret;
@@ -2389,8 +2502,8 @@ int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type,
for (i = 0; i < nb_streams; i++) {
int real_stream_index = program ? program[i] : i;
AVStream *st = ic->streams[real_stream_index];
- AVCodecContext *avctx = st->codec;
- if (avctx->codec_type != type)
+ AVCodecParameters *par = st->codecpar;
+ if (par->codec_type != type)
continue;
if (wanted_stream_nb >= 0 && real_stream_index != wanted_stream_nb)
continue;
@@ -2398,7 +2511,7 @@ int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type,
AV_DISPOSITION_VISUAL_IMPAIRED))
continue;
if (decoder_ret) {
- decoder = avcodec_find_decoder(st->codec->codec_id);
+ decoder = avcodec_find_decoder(par->codec_id);
if (!decoder) {
if (ret < 0)
ret = AVERROR_DECODER_NOT_FOUND;
@@ -2460,14 +2573,22 @@ static void free_stream(AVStream **pst)
if (st->attached_pic.data)
av_packet_unref(&st->attached_pic);
+ if (st->internal) {
+ avcodec_free_context(&st->internal->avctx);
+ }
av_freep(&st->internal);
av_dict_free(&st->metadata);
+ avcodec_parameters_free(&st->codecpar);
av_freep(&st->probe_data.buf);
av_free(st->index_entries);
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
av_free(st->codec->extradata);
av_free(st->codec->subtitle_header);
av_free(st->codec);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
av_free(st->priv_data);
av_free(st->info);
@@ -2547,20 +2668,28 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
return NULL;
}
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
st->codec = avcodec_alloc_context3(c);
if (!st->codec) {
av_free(st->info);
av_free(st);
return NULL;
}
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
st->internal = av_mallocz(sizeof(*st->internal));
if (!st->internal)
goto fail;
if (s->iformat) {
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
/* no default bitrate if decoding */
st->codec->bit_rate = 0;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
/* default pts setting is MPEG-like */
avpriv_set_pts_info(st, 33, 1, 90000);
@@ -2573,6 +2702,14 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
st->cur_dts = AV_NOPTS_VALUE;
}
+ st->codecpar = avcodec_parameters_alloc();
+ if (!st->codecpar)
+ goto fail;
+
+ st->internal->avctx = avcodec_alloc_context3(NULL);
+ if (!st->internal->avctx)
+ goto fail;
+
st->index = s->nb_streams;
st->start_time = AV_NOPTS_VALUE;
st->duration = AV_NOPTS_VALUE;
@@ -2588,6 +2725,10 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
st->info->fps_first_dts = AV_NOPTS_VALUE;
st->info->fps_last_dts = AV_NOPTS_VALUE;
+#if FF_API_LAVF_AVCTX
+ st->internal->need_codec_update = 1;
+#endif
+
s->streams[s->nb_streams++] = st;
return st;
fail:
@@ -3094,18 +3235,18 @@ int ff_generate_avci_extradata(AVStream *st)
const uint8_t *data = NULL;
int size = 0;
- if (st->codec->width == 1920) {
- if (st->codec->field_order == AV_FIELD_PROGRESSIVE) {
+ if (st->codecpar->width == 1920) {
+ if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) {
data = avci100_1080p_extradata;
size = sizeof(avci100_1080p_extradata);
} else {
data = avci100_1080i_extradata;
size = sizeof(avci100_1080i_extradata);
}
- } else if (st->codec->width == 1440) {
+ } else if (st->codecpar->width == 1440) {
data = avci50_1080i_extradata;
size = sizeof(avci50_1080i_extradata);
- } else if (st->codec->width == 1280) {
+ } else if (st->codecpar->width == 1280) {
data = avci100_720p_extradata;
size = sizeof(avci100_720p_extradata);
}
@@ -3113,14 +3254,14 @@ int ff_generate_avci_extradata(AVStream *st)
if (!size)
return 0;
- av_freep(&st->codec->extradata);
- st->codec->extradata_size = 0;
- st->codec->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
- if (!st->codec->extradata)
+ av_freep(&st->codecpar->extradata);
+ st->codecpar->extradata_size = 0;
+ st->codecpar->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
+ if (!st->codecpar->extradata)
return AVERROR(ENOMEM);
- memcpy(st->codec->extradata, data, size);
- st->codec->extradata_size = size;
+ memcpy(st->codecpar->extradata, data, size);
+ st->codecpar->extradata_size = size;
return 0;
}