summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2014-05-18 12:12:59 +0200
committerAnton Khirnov <anton@khirnov.net>2014-06-18 15:12:34 +0200
commit194be1f43ea391eb986732707435176e579265aa (patch)
tree2045d50660f7e045fde6cda7a2ed8213c24f5aab /libavformat
parentd754ed41727b1fcbab335b510248a9758a73320c (diff)
lavf: switch to AVStream.time_base as the hint for the muxer timebase
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).
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/avformat.h9
-rw-r--r--libavformat/avienc.c15
-rw-r--r--libavformat/filmstripenc.c3
-rw-r--r--libavformat/framehash.c1
-rw-r--r--libavformat/movenc.c14
-rw-r--r--libavformat/mpegtsenc.c13
-rw-r--r--libavformat/mux.c26
-rw-r--r--libavformat/mxfenc.c5
-rw-r--r--libavformat/oggenc.c3
-rw-r--r--libavformat/riffenc.c4
-rw-r--r--libavformat/rmenc.c5
-rw-r--r--libavformat/swf.h1
-rw-r--r--libavformat/swfenc.c6
-rw-r--r--libavformat/utils.c9
-rw-r--r--libavformat/version.h7
-rw-r--r--libavformat/yuv4mpegenc.c5
16 files changed, 84 insertions, 42 deletions
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index b17c791eac..473b8daedf 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 87075d4b93..417a8e99d2 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 90d9a7685c..8d1d2d8365 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 28e9e8407d..6a6da98ae4 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 dcd3294e01..f5c36fcec1 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 04cabe5f8d..838702e8fa 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -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);
}
}
diff --git a/libavformat/mux.c b/libavformat/mux.c
index e024a7eaea..9c2144acc1 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -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");
diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
index 66beec2940..841e727791 100644
--- a/libavformat/mxfenc.c
+++ b/libavformat/mxfenc.c
@@ -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;
diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c
index d148f5b7da..19c77595f4 100644
--- a/libavformat/oggenc.c
+++ b/libavformat/oggenc.c
@@ -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 &&
diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c
index 8f0279628e..b83533a250 100644
--- a/libavformat/riffenc.c
+++ b/libavformat/riffenc.c
@@ -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 :
diff --git a/libavformat/rmenc.c b/libavformat/rmenc.c
index fba8feb802..9ff9f318a5 100644
--- a/libavformat/rmenc.c
+++ b/libavformat/rmenc.c
@@ -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;
diff --git a/libavformat/swf.h b/libavformat/swf.h
index 79c3c1d033..8eb3f70541 100644
--- a/libavformat/swf.h
+++ b/libavformat/swf.h
@@ -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[];
diff --git a/libavformat/swfenc.c b/libavformat/swfenc.c
index be2e5cd7d3..a1fc7b337c 100644
--- a/libavformat/swfenc.c
+++ b/libavformat/swfenc.c
@@ -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)
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 50661ea17c..ab6c6bf0c9 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -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;
diff --git a/libavformat/version.h b/libavformat/version.h
index 57970cd250..1a017ce362 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -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 */
diff --git a/libavformat/yuv4mpegenc.c b/libavformat/yuv4mpegenc.c
index ed1ffea87d..abe967f177 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;