diff --git a/doc/APIchanges b/doc/APIchanges index 11027ef0d9..ed9d560bfd 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,11 @@ libavutil: 2012-10-22 API changes, most recent first: +2014-xx-xx - xxxxxxx - lavf 55.20.0 - avformat.h + The proper way for providing a hint about the desired timebase to the muxers + is now setting AVStream.time_base, instead of AVStream.codec.time_base as was + done previously. The old method is now deprecated. + 2014-06-10 - xxxxxxx - lavf 55.43.100 - avformat.h New field int64_t max_analyze_duration2 instead of deprecated int max_analyze_duration. diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 16c225479d..a2cea10180 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -800,9 +800,12 @@ typedef struct AVStream { * of which frame timestamps are represented. * * decoding: set by libavformat - * encoding: set by libavformat in avformat_write_header. The muxer may use the - * user-provided value of @ref AVCodecContext.time_base "codec->time_base" - * as a hint. + * encoding: May be set by the caller before avformat_write_header() to + * provide a hint to the muxer about the desired timebase. In + * avformat_write_header(), the muxer will overwrite this field + * with the timebase that will actually be used for the timestamps + * written into the file (which may or may not be related to the + * user-provided one, depending on the format). */ AVRational time_base; diff --git a/libavformat/avienc.c b/libavformat/avienc.c index 461d3aa611..c45bac28c4 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -155,6 +155,7 @@ static int avi_write_header(AVFormatContext *s) AVIOContext *pb = s->pb; int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale; AVCodecContext *video_enc; + AVStream *video_st = NULL; int64_t list1, list2, strh, strf; AVDictionaryEntry *t = NULL; int padding; @@ -184,15 +185,18 @@ static int avi_write_header(AVFormatContext *s) for (n = 0; n < s->nb_streams; n++) { AVCodecContext *codec = s->streams[n]->codec; bitrate += codec->bit_rate; - if (codec->codec_type == AVMEDIA_TYPE_VIDEO) + if (codec->codec_type == AVMEDIA_TYPE_VIDEO) { video_enc = codec; + video_st = s->streams[n]; + } } nb_frames = 0; - if (video_enc) - avio_wl32(pb, (uint32_t) (INT64_C(1000000) * video_enc->time_base.num / - video_enc->time_base.den)); + // TODO: should be avg_frame_rate + if (video_st) + avio_wl32(pb, (uint32_t) (INT64_C(1000000) * video_st->time_base.num / + video_st->time_base.den)); else avio_wl32(pb, 0); avio_wl32(pb, bitrate / 8); /* XXX: not quite exact */ @@ -388,7 +392,8 @@ static int avi_write_header(AVFormatContext *s) avio_wl32(pb, 0); // video format = unknown avio_wl32(pb, 0); // video standard = unknown - avio_wl32(pb, lrintf(1.0 / av_q2d(enc->time_base))); + // TODO: should be avg_frame_rate + avio_wl32(pb, lrintf(1.0 / av_q2d(st->time_base))); avio_wl32(pb, enc->width); avio_wl32(pb, enc->height); avio_wl16(pb, den); diff --git a/libavformat/filmstripenc.c b/libavformat/filmstripenc.c index 85d49beec7..7c9bc6dcc0 100644 --- a/libavformat/filmstripenc.c +++ b/libavformat/filmstripenc.c @@ -64,7 +64,8 @@ static int write_trailer(AVFormatContext *s) avio_wb16(pb, st->codec->width); avio_wb16(pb, st->codec->height); avio_wb16(pb, 0); // leading - avio_wb16(pb, st->codec->time_base.den / st->codec->time_base.num); + // TODO: should be avg_frame_rate + avio_wb16(pb, st->time_base.den / st->time_base.num); for (i = 0; i < 16; i++) avio_w8(pb, 0x00); // reserved diff --git a/libavformat/framehash.c b/libavformat/framehash.c index f075c404fc..a8357b04ae 100644 --- a/libavformat/framehash.c +++ b/libavformat/framehash.c @@ -28,7 +28,6 @@ int ff_framehash_write_header(AVFormatContext *s) avio_printf(s->pb, "#software: %s\n", LIBAVFORMAT_IDENT); for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - avpriv_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den); avio_printf(s->pb, "#tb %d: %d/%d\n", i, st->time_base.num, st->time_base.den); avio_flush(s->pb); } diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 55c7e523e9..bb515747ad 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -907,10 +907,10 @@ static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track) else if (track->enc->pix_fmt == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p'); else tag = MKTAG('d','v','p','p'); } else if (track->enc->height == 720) { /* HD 720 line */ - if (track->enc->time_base.den == 50) tag = MKTAG('d','v','h','q'); + if (track->st->time_base.den == 50) tag = MKTAG('d','v','h','q'); else tag = MKTAG('d','v','h','p'); } else if (track->enc->height == 1080) { /* HD 1080 line */ - if (track->enc->time_base.den == 25) tag = MKTAG('d','v','h','5'); + if (track->st->time_base.den == 25) tag = MKTAG('d','v','h','5'); else tag = MKTAG('d','v','h','6'); } else { av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n"); @@ -3057,10 +3057,12 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s) { + AVStream *video_st = s->streams[0]; AVCodecContext *video_codec = s->streams[0]->codec; AVCodecContext *audio_codec = s->streams[1]->codec; int audio_rate = audio_codec->sample_rate; - int frame_rate = ((video_codec->time_base.den) * (0x10000)) / (video_codec->time_base.num); + // TODO: should be avg_frame_rate + int frame_rate = ((video_st->time_base.den) * (0x10000)) / (video_st->time_base.num); int audio_kbitrate = audio_codec->bit_rate / 1000; int video_kbitrate = FFMIN(video_codec->bit_rate / 1000, 800 - audio_kbitrate); @@ -4028,7 +4030,7 @@ static int mov_write_header(AVFormatContext *s) if (mov->video_track_timescale) { track->timescale = mov->video_track_timescale; } else { - track->timescale = st->codec->time_base.den; + track->timescale = st->time_base.den; while(track->timescale < 10000) track->timescale *= 2; } @@ -4068,9 +4070,9 @@ static int mov_write_header(AVFormatContext *s) goto error; } } else if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { - track->timescale = st->codec->time_base.den; + track->timescale = st->time_base.den; } else if (st->codec->codec_type == AVMEDIA_TYPE_DATA) { - track->timescale = st->codec->time_base.den; + track->timescale = st->time_base.den; } else { track->timescale = MOV_TIMESCALE; } diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index f0d9cd2780..a4a32e0e16 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -201,6 +201,7 @@ typedef struct MpegTSWriteStream { int payload_flags; uint8_t *payload; AVFormatContext *amux; + AVRational user_tb; } MpegTSWriteStream; static void mpegts_write_pat(AVFormatContext *s) @@ -602,13 +603,17 @@ static int mpegts_write_header(AVFormatContext *s) /* assign pids to each stream */ for(i = 0;i < s->nb_streams; i++) { st = s->streams[i]; - avpriv_set_pts_info(st, 33, 1, 90000); + ts_st = av_mallocz(sizeof(MpegTSWriteStream)); if (!ts_st) { ret = AVERROR(ENOMEM); goto fail; } st->priv_data = ts_st; + + ts_st->user_tb = st->time_base; + avpriv_set_pts_info(st, 33, 1, 90000); + ts_st->payload = av_mallocz(ts->pes_payload_size); if (!ts_st->payload) { ret = AVERROR(ENOMEM); @@ -683,7 +688,8 @@ static int mpegts_write_header(AVFormatContext *s) pcr_st = s->streams[0]; ts_st = pcr_st->priv_data; service->pcr_pid = ts_st->pid; - } + } else + ts_st = pcr_st->priv_data; if (ts->mux_rate > 1) { service->pcr_packet_period = (ts->mux_rate * ts->pcr_period) / @@ -710,8 +716,9 @@ static int mpegts_write_header(AVFormatContext *s) } } else { // max delta PCR 0.1s + // TODO: should be avg_frame_rate service->pcr_packet_period = - pcr_st->codec->time_base.den/(10*pcr_st->codec->time_base.num); + ts_st->user_tb.den / (10 * ts_st->user_tb.num); } if(!service->pcr_packet_period) service->pcr_packet_period = 1; diff --git a/libavformat/mux.c b/libavformat/mux.c index 57044f3ab2..f542c9e686 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -252,6 +252,25 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) st = s->streams[i]; codec = st->codec; +#if FF_API_LAVF_CODEC_TB +FF_DISABLE_DEPRECATION_WARNINGS + if (!st->time_base.num && codec->time_base.num) { + av_log(s, AV_LOG_WARNING, "Using AVStream.codec.time_base as a " + "timebase hint to the muxer is deprecated. Set " + "AVStream.time_base instead.\n"); + avpriv_set_pts_info(st, 64, codec->time_base.num, codec->time_base.den); + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (!st->time_base.num) { + /* fall back on the default timebase values */ + if (codec->codec_type == AVMEDIA_TYPE_AUDIO && codec->sample_rate) + avpriv_set_pts_info(st, 64, 1, codec->sample_rate); + else + avpriv_set_pts_info(st, 33, 1, 90000); + } + switch (codec->codec_type) { case AVMEDIA_TYPE_AUDIO: if (codec->sample_rate <= 0) { @@ -264,13 +283,6 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) av_get_bits_per_sample(codec->codec_id) >> 3; break; case AVMEDIA_TYPE_VIDEO: - if (codec->time_base.num <= 0 || - codec->time_base.den <= 0) { //FIXME audio too? - av_log(s, AV_LOG_ERROR, "time base not set\n"); - ret = AVERROR(EINVAL); - goto fail; - } - if ((codec->width <= 0 || codec->height <= 0) && !(of->flags & AVFMT_NODIMENSIONS)) { av_log(s, AV_LOG_ERROR, "dimensions not set\n"); diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 6f3226b968..95726232cf 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -1689,7 +1689,8 @@ static int mxf_write_header(AVFormatContext *s) } if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - AVRational rate, tbc = st->codec->time_base; + // TODO: should be avg_frame_rate + AVRational rate, tbc = st->time_base; // Default component depth to 8 sc->component_depth = 8; mxf->timecode_base = (tbc.den + tbc.num/2) / tbc.num; diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c index 6c50fc3521..f6a6d7d96d 100644 --- a/libavformat/oggenc.c +++ b/libavformat/oggenc.c @@ -432,8 +432,8 @@ static int ogg_write_header(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, 48000); else avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); - } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) - avpriv_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den); + } + if (st->codec->codec_id != AV_CODEC_ID_VORBIS && st->codec->codec_id != AV_CODEC_ID_THEORA && st->codec->codec_id != AV_CODEC_ID_SPEEX && diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c index edb8b4ce44..ef4d399030 100644 --- a/libavformat/riffenc.c +++ b/libavformat/riffenc.c @@ -255,8 +255,8 @@ void ff_parse_specific_params(AVStream *st, int *au_rate, } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO || codec->codec_type == AVMEDIA_TYPE_DATA || codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { - *au_scale = codec->time_base.num; - *au_rate = codec->time_base.den; + *au_scale = st->time_base.num; + *au_rate = st->time_base.den; } else { *au_scale = codec->block_align ? codec->block_align * 8 : 8; *au_rate = codec->bit_rate ? codec->bit_rate : diff --git a/libavformat/rmenc.c b/libavformat/rmenc.c index 17192ff275..2e50ed338c 100644 --- a/libavformat/rmenc.c +++ b/libavformat/rmenc.c @@ -315,6 +315,8 @@ static int rm_write_header(AVFormatContext *s) } for(n=0;nnb_streams;n++) { + AVStream *st = s->streams[n]; + s->streams[n]->id = n; codec = s->streams[n]->codec; stream = &rm->streams[n]; @@ -334,7 +336,8 @@ static int rm_write_header(AVFormatContext *s) break; case AVMEDIA_TYPE_VIDEO: rm->video_stream = stream; - stream->frame_rate = (float)codec->time_base.den / (float)codec->time_base.num; + // TODO: should be avg_frame_rate + stream->frame_rate = (float)st->time_base.den / (float)st->time_base.num; /* XXX: dummy values */ stream->packet_max_size = 4096; stream->nb_packets = 0; diff --git a/libavformat/swf.h b/libavformat/swf.h index c1667b3c24..93a094c26d 100644 --- a/libavformat/swf.h +++ b/libavformat/swf.h @@ -132,6 +132,7 @@ typedef struct SWFContext { int tag; AVFifoBuffer *audio_fifo; AVCodecContext *audio_enc, *video_enc; + AVStream *video_st; #if CONFIG_ZLIB AVIOContext *zpb; #define ZBUF_SIZE 4096 diff --git a/libavformat/swfenc.c b/libavformat/swfenc.c index 402f21ef40..3b6f9b3f83 100644 --- a/libavformat/swfenc.c +++ b/libavformat/swfenc.c @@ -212,6 +212,7 @@ static int swf_write_header(AVFormatContext *s) if (enc->codec_id == AV_CODEC_ID_VP6F || enc->codec_id == AV_CODEC_ID_FLV1 || enc->codec_id == AV_CODEC_ID_MJPEG) { + swf->video_st = s->streams[i]; swf->video_enc = enc; } else { av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n"); @@ -229,8 +230,9 @@ static int swf_write_header(AVFormatContext *s) } else { width = swf->video_enc->width; height = swf->video_enc->height; - rate = swf->video_enc->time_base.den; - rate_base = swf->video_enc->time_base.num; + // TODO: should be avg_frame_rate + rate = swf->video_st->time_base.den; + rate_base = swf->video_st->time_base.num; } if (!swf->audio_enc) diff --git a/libavformat/utils.c b/libavformat/utils.c index 723eff6bd8..517d919e1d 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -3738,9 +3738,14 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) st->info->last_dts = AV_NOPTS_VALUE; st->codec = avcodec_alloc_context3(c); - if (s->iformat) + if (s->iformat) { /* no default bitrate if decoding */ st->codec->bit_rate = 0; + + /* default pts setting is MPEG-like */ + avpriv_set_pts_info(st, 33, 1, 90000); + } + st->index = s->nb_streams; st->start_time = AV_NOPTS_VALUE; st->duration = AV_NOPTS_VALUE; @@ -3754,8 +3759,6 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) st->pts_wrap_reference = AV_NOPTS_VALUE; st->pts_wrap_behavior = AV_PTS_WRAP_IGNORE; - /* default pts setting is MPEG-like */ - avpriv_set_pts_info(st, 33, 1, 90000); st->last_IP_pts = AV_NOPTS_VALUE; st->last_dts_for_order_check = AV_NOPTS_VALUE; for (i = 0; i < MAX_REORDER_DELAY + 1; i++) diff --git a/libavformat/version.h b/libavformat/version.h index e9cc16de47..67393e051e 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFORMAT_VERSION_MAJOR 55 -#define LIBAVFORMAT_VERSION_MINOR 43 +#define LIBAVFORMAT_VERSION_MINOR 44 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ @@ -57,6 +57,9 @@ #ifndef FF_API_LAVF_FRAC #define FF_API_LAVF_FRAC (LIBAVFORMAT_VERSION_MAJOR < 57) #endif +#ifndef FF_API_LAVF_CODEC_TB +#define FF_API_LAVF_CODEC_TB (LIBAVFORMAT_VERSION_MAJOR < 57) +#endif #ifndef FF_API_ALLOC_OUTPUT_CONTEXT #define FF_API_ALLOC_OUTPUT_CONTEXT (LIBAVFORMAT_VERSION_MAJOR < 56) diff --git a/libavformat/yuv4mpegenc.c b/libavformat/yuv4mpegenc.c index 3836a95402..beae8bba65 100644 --- a/libavformat/yuv4mpegenc.c +++ b/libavformat/yuv4mpegenc.c @@ -38,8 +38,9 @@ static int yuv4_generate_header(AVFormatContext *s, char* buf) width = st->codec->width; height = st->codec->height; - av_reduce(&raten, &rated, st->codec->time_base.den, - st->codec->time_base.num, (1UL << 31) - 1); + // TODO: should be avg_frame_rate + av_reduce(&raten, &rated, st->time_base.den, + st->time_base.num, (1UL << 31) - 1); aspectn = st->sample_aspect_ratio.num; aspectd = st->sample_aspect_ratio.den; diff --git a/tests/ref/lavf/mxf b/tests/ref/lavf/mxf index 1390612b75..27991ffbb6 100644 --- a/tests/ref/lavf/mxf +++ b/tests/ref/lavf/mxf @@ -3,7 +3,7 @@ ./tests/data/lavf/lavf.mxf CRC=0xdbfff6f1 f61e4c8481610f30b2f5e2279e254f6b *./tests/data/lavf/lavf.mxf 560697 ./tests/data/lavf/lavf.mxf -./tests/data/lavf/lavf.mxf CRC=0x3ff4178e +./tests/data/lavf/lavf.mxf CRC=0x11a6178e a586dad4ff94136be460afb02ff6101e *./tests/data/lavf/lavf.mxf 525369 ./tests/data/lavf/lavf.mxf ./tests/data/lavf/lavf.mxf CRC=0xdbfff6f1