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).
---
doc/APIchanges | 5 +++++
libavformat/avformat.h | 9 ++++++---
libavformat/avienc.c | 15 ++++++++++-----
libavformat/filmstripenc.c | 3 ++-
libavformat/framehash.c | 1 -
libavformat/movenc.c | 14 ++++++++------
libavformat/mpegtsenc.c | 12 +++++++++---
libavformat/mux.c | 26 +++++++++++++++++++-------
libavformat/mxfenc.c | 5 +++--
libavformat/oggenc.c | 3 +--
libavformat/riffenc.c | 4 ++--
libavformat/rmenc.c | 5 ++++-
libavformat/swf.h | 1 +
libavformat/swfenc.c | 6 ++++--
libavformat/utils.c | 9 ++++++---
libavformat/version.h | 3 +++
libavformat/yuv4mpegenc.c | 5 +++--
tests/ref/lavf/mkv | 2 +-
18 files changed, 87 insertions(+), 41 deletions(-)
diff --git a/doc/APIchanges b/doc/APIchanges
index 952ee51..82774ea 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,11 @@ libavutil: 2013-12-xx
API changes, most recent first:
+2014-xx-xx - xxxxxxx - lavf 55.19.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
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index b17c791..473b8da 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -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;
diff --git a/libavformat/avienc.c b/libavformat/avienc.c
index 87075d4..417a8e9 100644
--- a/libavformat/avienc.c
+++ b/libavformat/avienc.c
@@ -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);
diff --git a/libavformat/filmstripenc.c b/libavformat/filmstripenc.c
index 90d9a76..8d1d2d8 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, 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
diff --git a/libavformat/framehash.c b/libavformat/framehash.c
index 28e9e84..6a6da98 100644
--- a/libavformat/framehash.c
+++ b/libavformat/framehash.c
@@ -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);
}
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index dcd3294..f5c36fc 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -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;
diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index 8efd93e..487de18 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -228,6 +228,7 @@ typedef struct MpegTSWriteStream {
int payload_flags;
uint8_t *payload;
AVFormatContext *amux;
+ AVRational user_tb;
} MpegTSWriteStream;
static void mpegts_write_pat(AVFormatContext *s)
@@ -514,13 +515,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);
@@ -591,7 +596,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 * PCR_RETRANS_TIME) /
@@ -618,7 +624,7 @@ static int mpegts_write_header(AVFormatContext *s)
} else {
// max delta PCR 0.1s
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);
}
}