summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/av_common.c25
-rw-r--r--common/av_common.h1
2 files changed, 26 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; };
diff --git a/common/av_common.h b/common/av_common.h
index e2b86bfe40..4b13dcdd0c 100644
--- a/common/av_common.h
+++ b/common/av_common.h
@@ -33,6 +33,7 @@ struct mp_log;
int mp_lavc_set_extradata(AVCodecContext *avctx, void *ptr, int size);
void mp_copy_lav_codec_headers(AVCodecContext *avctx, AVCodecContext *st);
void mp_set_lav_codec_headers(AVCodecContext *avctx, struct mp_codec_params *c);
+AVRational mp_get_codec_timebase(struct mp_codec_params *c);
void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt, AVRational *tb);
int64_t mp_pts_to_av(double mp_pts, AVRational *tb);
double mp_pts_from_av(int64_t av_pts, AVRational *tb);