summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/decode/ad_lavc.c2
-rw-r--r--common/av_common.c25
-rw-r--r--common/av_common.h1
-rw-r--r--demux/demux_lavf.c2
-rw-r--r--demux/demux_mf.c1
-rw-r--r--demux/demux_raw.c4
-rw-r--r--demux/stheader.h4
-rw-r--r--video/decode/vd_lavc.c5
8 files changed, 39 insertions, 5 deletions
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c
index c785c62c90..26e67fe1b9 100644
--- a/audio/decode/ad_lavc.c
+++ b/audio/decode/ad_lavc.c
@@ -86,7 +86,7 @@ static int init(struct dec_audio *da, const char *decoder)
struct priv *ctx = talloc_zero(NULL, struct priv);
da->priv = ctx;
- ctx->codec_timebase = (AVRational){0};
+ ctx->codec_timebase = mp_get_codec_timebase(da->codec);
ctx->force_channel_map = c->force_channels;
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);
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index ef0a8583d5..4b236ee2be 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -670,6 +670,8 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
if (sh->codec->lav_headers)
mp_copy_lav_codec_headers(sh->codec->lav_headers, codec);
#endif
+ sh->codec->native_tb_num = st->time_base.num;
+ sh->codec->native_tb_den = st->time_base.den;
if (st->disposition & AV_DISPOSITION_DEFAULT)
sh->default_track = true;
diff --git a/demux/demux_mf.c b/demux/demux_mf.c
index c0b159e4ea..20b948630c 100644
--- a/demux/demux_mf.c
+++ b/demux/demux_mf.c
@@ -321,6 +321,7 @@ static int demux_open_mf(demuxer_t *demuxer, enum demux_check check)
c->disp_w = 0;
c->disp_h = 0;
c->fps = demuxer->opts->mf_fps;
+ c->reliable_fps = true;
demux_add_sh_stream(demuxer, sh);
diff --git a/demux/demux_raw.c b/demux/demux_raw.c
index bd8e11306d..51378e7031 100644
--- a/demux/demux_raw.c
+++ b/demux/demux_raw.c
@@ -145,6 +145,9 @@ static int demux_rawaudio_open(demuxer_t *demuxer, enum demux_check check)
c->force_channels = true;
c->samplerate = opts->samplerate;
+ c->native_tb_num = 1;
+ c->native_tb_den = c->samplerate;
+
int f = opts->aformat;
// See PCM(): sign float bits endian
mp_set_pcm_codec(sh->codec, f & 1, f & 2, f >> 3, f & 4);
@@ -233,6 +236,7 @@ static int demux_rawvideo_open(demuxer_t *demuxer, enum demux_check check)
c->codec = decoder;
c->codec_tag = imgfmt;
c->fps = opts->fps;
+ c->reliable_fps = true;
c->disp_w = width;
c->disp_h = height;
demux_add_sh_stream(demuxer, sh);
diff --git a/demux/stheader.h b/demux/stheader.h
index f9d564c230..78e86a47ee 100644
--- a/demux/stheader.h
+++ b/demux/stheader.h
@@ -74,6 +74,9 @@ struct mp_codec_params {
struct AVCodecContext *lav_headers;
struct AVCodecParameters *lav_codecpar;
+ // Timestamp granularity for converting double<->rational timestamps.
+ int native_tb_num, native_tb_den;
+
// STREAM_AUDIO
int samplerate;
struct mp_chmap channels;
@@ -85,6 +88,7 @@ struct mp_codec_params {
// STREAM_VIDEO
bool avi_dts; // use DTS timing; first frame and DTS is 0
float fps; // frames per second (set only if constant fps)
+ bool reliable_fps; // the fps field is definitely not broken
int par_w, par_h; // pixel aspect ratio (0 if unknown/square)
int disp_w, disp_h; // display size
int rotate; // intended display rotation, in degrees, [0, 359]
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index eb63e58e92..804bf1112d 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -449,10 +449,7 @@ static void init_avctx(struct dec_video *vd, const char *decoder,
if (!lavc_codec)
return;
- ctx->codec_timebase = (AVRational){0};
- if (strstr(decoder, "_mmal") || strstr(decoder, "_mediacodec"))
- ctx->codec_timebase = (AVRational){1, 1000000};
-
+ ctx->codec_timebase = mp_get_codec_timebase(vd->codec);
ctx->pix_fmt = AV_PIX_FMT_NONE;
ctx->hwdec = hwdec;
ctx->hwdec_fmt = 0;