diff options
author | wm4 <wm4@nowhere> | 2016-08-19 14:19:46 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2016-08-19 14:59:30 +0200 |
commit | 05e4df3f0c7679e8ac3b32a1a414be751b6b6b37 (patch) | |
tree | 82341aaaf7d4e82800d0555b3e39dfd2ddb6a77f /common/av_common.c | |
parent | 4aaa83339ca9515113e936af79bc3d860d67cb4b (diff) | |
download | mpv-05e4df3f0c7679e8ac3b32a1a414be751b6b6b37.tar.bz2 mpv-05e4df3f0c7679e8ac3b32a1a414be751b6b6b37.tar.xz |
video/audio: always provide "proper" timestamps to libavcodec
Instead of passing through double float timestamps opaquely, pass real
timestamps. Do so by always setting a valid timebase on the
AVCodecContext for audio and video decoding.
Specifically try not to round timestamps to a too coarse timebase, which
could round off small adjustments to timestamps (such as for start time
rebasing or demux_timeline). If the timebase is considered too coarse,
make it finer.
This gets rid of the need to do this specifically for some hardware
decoding wrapper. The old method of passing through double timestamps
was also a bit questionable. While libavcodec is not supposed to
interpret timestamps at all if no timebase is provided, it was
needlessly tricky. Also, it actually does compare them with
AV_NOPTS_VALUE. This change will probably also reduce confusion in the
future.
Diffstat (limited to 'common/av_common.c')
-rw-r--r-- | common/av_common.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/common/av_common.c b/common/av_common.c index 6856a27d93..3a424b0c62 100644 --- a/common/av_common.c +++ b/common/av_common.c @@ -16,6 +16,7 @@ */ #include <assert.h> +#include <math.h> #include <libavutil/common.h> #include <libavutil/log.h> @@ -84,6 +85,30 @@ void mp_set_lav_codec_headers(AVCodecContext *avctx, struct mp_codec_params *c) #endif } +// Pick a "good" timebase, which will be used to convert double timestamps +// back to fractions for passing them through libavcodec. +AVRational mp_get_codec_timebase(struct mp_codec_params *c) +{ + AVRational tb = {c->native_tb_num, c->native_tb_den}; + if (tb.num < 1 || tb.den < 1) { + if (c->reliable_fps) + tb = av_inv_q(av_d2q(c->fps, 1000000)); + if (tb.num < 1 || tb.den < 1) + tb = AV_TIME_BASE_Q; + } + + // If the timebase is too coarse, raise its precision, or small adjustments + // to timestamps done between decoder and demuxer could be lost. + if (av_q2d(tb) > 0.001) { + AVRational r = av_div_q(tb, (AVRational){1, 1000}); + tb.den *= (r.num + r.den - 1) / r.den; + } + + av_reduce(&tb.num, &tb.den, tb.num, tb.den, 1000000); + + return tb; +} + // We merely pass-through our PTS/DTS as an int64_t; libavcodec won't use it. union pts { int64_t i; double d; }; |