Previously, AVStream.codec.time_base was used for that purpose, which was quite confusing for the callers. This change also opens the path for removing AVStream.codec. The change in the lavf-mkv test is due to the native timebase (1/1000) being used instead of the default one (1/90000), so the packets are now sent to the crc muxer in the same order in which they are demuxed (previously some of them got reordered because of inexact timestamp conversion).tags/n2.3
| @@ -13,6 +13,11 @@ libavutil: 2013-12-xx | |||
| 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-04-xx - xxxxxxx - lavc 55.54.0 - avcodec.h | |||
| Add AVCodecContext.side_data_only_packets to allow encoders to output packets | |||
| with only side data. This option may become mandatory in the future, so all | |||
| @@ -710,9 +710,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; | |||
| @@ -144,6 +144,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; | |||
| @@ -172,15 +173,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 */ | |||
| @@ -337,7 +341,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); | |||
| @@ -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, 1/av_q2d(st->codec->time_base)); | |||
| // TODO: should be avg_frame_rate | |||
| avio_wb16(pb, 1/av_q2d(st->time_base)); | |||
| for (i = 0; i < 16; i++) | |||
| avio_w8(pb, 0x00); // reserved | |||
| @@ -25,7 +25,6 @@ int ff_framehash_write_header(AVFormatContext *s) | |||
| int i; | |||
| 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); | |||
| } | |||
| @@ -814,10 +814,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"); | |||
| @@ -2656,10 +2656,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); | |||
| @@ -3400,7 +3402,7 @@ static int mov_write_header(AVFormatContext *s) | |||
| } | |||
| track->height = track->tag >> 24 == 'n' ? 486 : 576; | |||
| } | |||
| track->timescale = st->codec->time_base.den; | |||
| track->timescale = st->time_base.den; | |||
| if (track->mode == MODE_MOV && track->timescale > 100000) | |||
| av_log(s, AV_LOG_WARNING, | |||
| "WARNING codec timebase is very high. If duration is too long,\n" | |||
| @@ -3428,9 +3430,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; | |||
| } | |||
| if (!track->height) | |||
| track->height = st->codec->height; | |||
| @@ -194,6 +194,7 @@ typedef struct MpegTSWriteStream { | |||
| int payload_flags; | |||
| uint8_t *payload; | |||
| AVFormatContext *amux; | |||
| AVRational user_tb; | |||
| } MpegTSWriteStream; | |||
| static void mpegts_write_pat(AVFormatContext *s) | |||
| @@ -480,13 +481,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); | |||
| @@ -557,7 +562,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) / | |||
| @@ -583,8 +589,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); | |||
| } | |||
| } | |||
| @@ -115,6 +115,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) { | |||
| @@ -127,13 +146,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"); | |||
| @@ -1433,11 +1433,12 @@ static int mxf_write_header(AVFormatContext *s) | |||
| av_log(s, AV_LOG_ERROR, "video stream must be first track\n"); | |||
| return -1; | |||
| } | |||
| if (fabs(av_q2d(st->codec->time_base) - 1/25.0) < 0.0001) { | |||
| // TODO: should be avg_frame_rate | |||
| if (fabs(av_q2d(st->time_base) - 1/25.0) < 0.0001) { | |||
| samples_per_frame = PAL_samples_per_frame; | |||
| mxf->time_base = (AVRational){ 1, 25 }; | |||
| mxf->timecode_base = 25; | |||
| } else if (fabs(av_q2d(st->codec->time_base) - 1001/30000.0) < 0.0001) { | |||
| } else if (fabs(av_q2d(st->time_base) - 1001/30000.0) < 0.0001) { | |||
| samples_per_frame = NTSC_samples_per_frame; | |||
| mxf->time_base = (AVRational){ 1001, 30000 }; | |||
| mxf->timecode_base = 30; | |||
| @@ -428,8 +428,7 @@ 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 && | |||
| @@ -230,8 +230,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 : | |||
| @@ -310,6 +310,8 @@ static int rm_write_header(AVFormatContext *s) | |||
| AVCodecContext *codec; | |||
| for(n=0;n<s->nb_streams;n++) { | |||
| AVStream *st = s->streams[n]; | |||
| s->streams[n]->id = n; | |||
| codec = s->streams[n]->codec; | |||
| stream = &rm->streams[n]; | |||
| @@ -329,7 +331,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; | |||
| @@ -76,6 +76,7 @@ typedef struct SWFContext { | |||
| int tag; | |||
| AVFifoBuffer *audio_fifo; | |||
| AVCodecContext *audio_enc, *video_enc; | |||
| AVStream *video_st; | |||
| } SWFContext; | |||
| extern const AVCodecTag ff_swf_codec_tags[]; | |||
| @@ -207,6 +207,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"); | |||
| @@ -224,8 +225,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) | |||
| @@ -2663,9 +2663,14 @@ AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c) | |||
| } | |||
| 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; | |||
| @@ -2677,8 +2682,6 @@ AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c) | |||
| st->first_dts = AV_NOPTS_VALUE; | |||
| st->probe_packets = MAX_PROBE_PACKETS; | |||
| /* default pts setting is MPEG-like */ | |||
| avpriv_set_pts_info(st, 33, 1, 90000); | |||
| st->last_IP_pts = AV_NOPTS_VALUE; | |||
| for (i = 0; i < MAX_REORDER_DELAY + 1; i++) | |||
| st->pts_buffer[i] = AV_NOPTS_VALUE; | |||
| @@ -30,8 +30,8 @@ | |||
| #include "libavutil/version.h" | |||
| #define LIBAVFORMAT_VERSION_MAJOR 55 | |||
| #define LIBAVFORMAT_VERSION_MINOR 19 | |||
| #define LIBAVFORMAT_VERSION_MICRO 1 | |||
| #define LIBAVFORMAT_VERSION_MINOR 20 | |||
| #define LIBAVFORMAT_VERSION_MICRO 0 | |||
| #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | |||
| LIBAVFORMAT_VERSION_MINOR, \ | |||
| @@ -57,5 +57,8 @@ | |||
| #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 | |||
| #endif /* AVFORMAT_VERSION_H */ | |||
| @@ -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; | |||
| @@ -1,3 +1,3 @@ | |||
| 268fb8f9278b0df2f87a6a9455f3cd56 *./tests/data/lavf/lavf.mkv | |||
| 320380 ./tests/data/lavf/lavf.mkv | |||
| ./tests/data/lavf/lavf.mkv CRC=0xbe7d3cda | |||
| ./tests/data/lavf/lavf.mkv CRC=0x36193cda | |||