summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-12-04 20:12:14 +0100
committerwm4 <wm4@nowhere>2013-12-04 23:12:51 +0100
commit8a84da8102cb9c436627a61cd3b674a8ad3e9708 (patch)
tree9329d8af1d4239b50a5605788286ef43f5ef3871
parente2dfdc0c7ed5542b0211bb405ad3564bb72e3dee (diff)
downloadmpv-8a84da8102cb9c436627a61cd3b674a8ad3e9708.tar.bz2
mpv-8a84da8102cb9c436627a61cd3b674a8ad3e9708.tar.xz
av_common: add timebase parameter to mp_set_av_packet()
If the timebase is set, it's used for converting the packet timestamps. Otherwise, the previous method of reinterpret-casting the mpv style double timestamps to libavcodec style int64_t timestamps is used. Also replace the kind of awkward mp_get_av_frame_pkt_ts() function by mp_pts_from_av(), which simply converts timestamps in a way the old function did. (Plus it takes a timebase parameter, similar to the addition to mp_set_av_packet().) Note that this should not change anything yet. The code in ad_lavc.c and vd_lavc.c passes NULL for the timebase parameters. We could set AVCodecContext.pkt_timebase and use that if we want to give libavcodec "proper" timestamps. This could be important for ad_lavc.c: some codecs (opus, probably mp3 and aac too) have weird requirements about doing decoding preroll on the container level, and thus require adjusting the audio start timestamps in some cases. libavcodec doesn't tell us how much was skipped, so we either get shifted timestamps (by the length of the skipped data), or we give it proper timestamps. (Note: libavcodec interprets or changes timestamps only if pkt_timebase is set, which by default it is not.) This would require selecting a timebase though, so I feel uncomfortable with the idea. At least this change paves the way, and will allow some testing.
-rw-r--r--audio/decode/ad_lavc.c2
-rw-r--r--audio/decode/ad_spdif.c2
-rw-r--r--mpvcore/av_common.c53
-rw-r--r--mpvcore/av_common.h8
-rw-r--r--sub/sd_lavc_conv.c5
-rw-r--r--video/decode/vd_lavc.c5
6 files changed, 47 insertions, 28 deletions
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c
index 4093fa77bd..3b9a48e419 100644
--- a/audio/decode/ad_lavc.c
+++ b/audio/decode/ad_lavc.c
@@ -329,7 +329,7 @@ static int decode_new_packet(struct dec_audio *da)
int in_len = mpkt->len;
AVPacket pkt;
- mp_set_av_packet(&pkt, mpkt);
+ mp_set_av_packet(&pkt, mpkt, NULL);
if (mpkt->pts != MP_NOPTS_VALUE) {
da->pts = mpkt->pts;
diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c
index 059022e5e3..8c3c7c3ea7 100644
--- a/audio/decode/ad_spdif.c
+++ b/audio/decode/ad_spdif.c
@@ -202,7 +202,7 @@ static int decode_audio(struct dec_audio *da, struct mp_audio *buffer, int maxle
return -1;
AVPacket pkt;
- mp_set_av_packet(&pkt, mpkt);
+ mp_set_av_packet(&pkt, mpkt, NULL);
pkt.pts = pkt.dts = 0;
mp_msg(MSGT_DECAUDIO, MSGL_V, "spdif packet, size=%d\n", pkt.size);
if (mpkt->pts != MP_NOPTS_VALUE) {
diff --git a/mpvcore/av_common.c b/mpvcore/av_common.c
index d233071c23..59f6d636c7 100644
--- a/mpvcore/av_common.c
+++ b/mpvcore/av_common.c
@@ -63,16 +63,40 @@ void mp_copy_lav_codec_headers(AVCodecContext *avctx, AVCodecContext *st)
// We merely pass-through our PTS/DTS as an int64_t; libavcodec won't use it.
union pts { int64_t i; double d; };
-// Set dst from mpkt. Note that dst is not refcountable.
-// mpkt can be NULL to generate empty packets (used to flush delayed data).
-// Sets pts/dts to reinterpret-casted mpv values - these are useful for
-// reading back via mp_get_av_frame_pkt_pdts(), but they will be non-sense for
-// libavcodec itself. (And normally, libavcodec won't interpret them.)
-// Does not set duration field.
-void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt)
+// Convert the mpv style timestamp (seconds as double) to a libavcodec style
+// timestamp (integer units in a given timebase).
+//
+// If the given timebase is NULL or invalid, pass through the mpv timestamp by
+// reinterpret casting them to int64_t. In this case, the timestamps will be
+// non-sense for libavcodec, but we expect that it doesn't interpret them,
+// and treats them as opaque.
+int64_t mp_pts_to_av(double mp_pts, AVRational *tb)
{
assert(sizeof(int64_t) >= sizeof(double));
+ if (tb && tb->num > 0 && tb->den > 0)
+ return mp_pts == MP_NOPTS_VALUE ? AV_NOPTS_VALUE : mp_pts / av_q2d(*tb);
+ // The + 0.0 is to squash possible negative zero mp_pts, which would
+ // happen to end up as AV_NOPTS_VALUE.
+ return (union pts){.d = mp_pts + 0.0}.i;
+}
+
+// Inverse of mp_pts_to_av(). (The timebases must be exactly the same.)
+double mp_pts_from_av(int64_t av_pts, AVRational *tb)
+{
+ assert(sizeof(int64_t) >= sizeof(double));
+ if (tb && tb->num > 0 && tb->den > 0)
+ return av_pts == AV_NOPTS_VALUE ? MP_NOPTS_VALUE : av_pts * av_q2d(*tb);
+ // Should libavcodec set the PTS to AV_NOPTS_VALUE, it would end up as
+ // non-sense (usually negative zero) when unwrapped to double.
+ return av_pts == AV_NOPTS_VALUE ? MP_NOPTS_VALUE : (union pts){.i = av_pts}.d;
+}
+// Set dst from mpkt. Note that dst is not refcountable.
+// mpkt can be NULL to generate empty packets (used to flush delayed data).
+// Sets pts/dts using mp_pts_to_av(ts, tb). (Be aware of the implications.)
+// Set duration field only if tb is set.
+void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt, AVRational *tb)
+{
av_init_packet(dst);
dst->data = mpkt ? mpkt->buffer : NULL;
dst->size = mpkt ? mpkt->len : 0;
@@ -84,17 +108,10 @@ void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt)
dst->side_data = mpkt->avpacket->side_data;
dst->side_data_elems = mpkt->avpacket->side_data_elems;
}
- dst->pts = (union pts){.d = mpkt ? mpkt->pts : MP_NOPTS_VALUE}.i;
- dst->dts = (union pts){.d = mpkt ? mpkt->dts : MP_NOPTS_VALUE}.i;
-}
-
-// Return the pts/dts from a frame returned by libavcodec. Note that this
-// assumes libavcodec was fed a packet setup with mp_set_av_packet()! If not,
-// the timestamps might contain garbage.
-void mp_get_av_frame_pkt_ts(AVFrame *frame, double *out_pts, double *out_dts)
-{
- *out_pts = (union pts){.i = frame->pkt_pts}.d;
- *out_dts = (union pts){.i = frame->pkt_dts}.d;
+ if (mpkt && tb && tb->num > 0 && tb->den > 0)
+ dst->duration = mpkt->duration / av_q2d(*tb);
+ dst->pts = mp_pts_to_av(mpkt ? mpkt->pts : MP_NOPTS_VALUE, tb);
+ dst->dts = mp_pts_to_av(mpkt ? mpkt->dts : MP_NOPTS_VALUE, tb);
}
void mp_add_lavc_decoders(struct mp_decoder_list *list, enum AVMediaType type)
diff --git a/mpvcore/av_common.h b/mpvcore/av_common.h
index 103185329c..e457628979 100644
--- a/mpvcore/av_common.h
+++ b/mpvcore/av_common.h
@@ -18,15 +18,19 @@
#ifndef MP_AVCOMMON_H
#define MP_AVCOMMON_H
+#include <inttypes.h>
+
#include <libavutil/avutil.h>
+#include <libavutil/rational.h>
#include <libavcodec/avcodec.h>
struct mp_decoder_list;
struct demux_packet;
void mp_copy_lav_codec_headers(AVCodecContext *avctx, AVCodecContext *st);
-void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt);
-void mp_get_av_frame_pkt_ts(AVFrame *frame, double *out_pts, double *out_dts);
+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);
void mp_add_lavc_decoders(struct mp_decoder_list *list, enum AVMediaType type);
int mp_codec_to_av_codec_id(const char *codec);
const char *mp_codec_from_av_codec_id(int codec_id);
diff --git a/sub/sd_lavc_conv.c b/sub/sd_lavc_conv.c
index 6f72671650..24ea2c10c6 100644
--- a/sub/sd_lavc_conv.c
+++ b/sub/sd_lavc_conv.c
@@ -234,15 +234,12 @@ static void decode(struct sd *sd, struct demux_packet *packet)
{
struct sd_lavc_priv *priv = sd->priv;
AVCodecContext *avctx = priv->avctx;
- double ts = av_q2d(av_inv_q(avctx->time_base));
AVSubtitle sub = {0};
AVPacket pkt;
AVPacket parsed_pkt = {0};
int ret, got_sub;
- mp_set_av_packet(&pkt, packet);
- pkt.pts = packet->pts == MP_NOPTS_VALUE ? AV_NOPTS_VALUE : packet->pts * ts;
- pkt.duration = packet->duration * ts;
+ mp_set_av_packet(&pkt, packet, &avctx->time_base);
if (sd->codec && strcmp(sd->codec, "webvtt-webm") == 0) {
if (parse_webvtt(&pkt, &parsed_pkt) < 0) {
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 868f148d8b..fadd76de0e 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -744,7 +744,7 @@ static int decode(struct dec_video *vd, struct demux_packet *packet,
else
avctx->skip_frame = ctx->skip_frame;
- mp_set_av_packet(&pkt, packet);
+ mp_set_av_packet(&pkt, packet, NULL);
ret = avcodec_decode_video2(avctx, ctx->pic, &got_picture, &pkt);
if (ret < 0) {
@@ -757,7 +757,8 @@ static int decode(struct dec_video *vd, struct demux_packet *packet,
return 0;
update_image_params(vd, ctx->pic);
- mp_get_av_frame_pkt_ts(ctx->pic, &vd->codec_pts, &vd->codec_dts);
+ vd->codec_pts = mp_pts_from_av(ctx->pic->pkt_pts, NULL);
+ vd->codec_dts = mp_pts_from_av(ctx->pic->pkt_dts, NULL);
// Note: potentially resets ctx->pic as it is transferred to mpi
struct mp_image *mpi = image_from_decoder(vd);