summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demux/demux.c7
-rw-r--r--demux/demux.h7
-rw-r--r--demux/demux_lavf.c21
-rw-r--r--demux/packet.h1
-rw-r--r--mpvcore/av_common.c25
-rw-r--r--mpvcore/av_common.h1
-rw-r--r--mpvcore/player/video.c3
-rw-r--r--video/decode/vd_lavc.c5
8 files changed, 45 insertions, 25 deletions
diff --git a/demux/demux.c b/demux/demux.c
index 00d59af09d..467b016699 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -131,6 +131,7 @@ static struct demux_packet *create_packet(size_t len)
*dp = (struct demux_packet) {
.len = len,
.pts = MP_NOPTS_VALUE,
+ .dts = MP_NOPTS_VALUE,
.duration = -1,
.stream_pts = MP_NOPTS_VALUE,
.pos = -1,
@@ -217,6 +218,7 @@ struct demux_packet *demux_copy_packet(struct demux_packet *dp)
memcpy(new->buffer, dp->buffer, new->len);
}
new->pts = dp->pts;
+ new->dts = dp->dts;
new->duration = dp->duration;
new->stream_pts = dp->stream_pts;
return new;
@@ -340,6 +342,11 @@ int demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream,
if (dp->pos >= 0)
demuxer->filepos = dp->pos;
+ // For video, PTS determination is not trivial, but for other media types
+ // distinguishing PTS and DTS is not useful.
+ if (stream->type != STREAM_VIDEO && dp->pts == MP_NOPTS_VALUE)
+ dp->pts = dp->dts;
+
mp_dbg(MSGT_DEMUXER, MSGL_DBG2,
"DEMUX: Append packet to %s, len=%d pts=%5.3f pos=%"PRIu64" "
"[packs: A=%d V=%d S=%d]\n", stream_type_name(stream->type),
diff --git a/demux/demux.h b/demux/demux.h
index e025862bb2..6b08b84e4c 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -43,12 +43,6 @@ enum demuxer_type {
DEMUXER_TYPE_CUE,
};
-enum timestamp_type {
- TIMESTAMP_TYPE_PTS,
- TIMESTAMP_TYPE_SORT,
-};
-
-
// DEMUXER control commands/answers
#define DEMUXER_CTRL_NOTIMPL -1
#define DEMUXER_CTRL_DONTKNOW 0
@@ -174,7 +168,6 @@ typedef struct demuxer {
bool accurate_seek;
// File format allows PTS resets (even if the current file is without)
bool ts_resets_possible;
- enum timestamp_type timestamp_type;
bool warned_queue_overflow;
struct sh_stream **streams;
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index fe0b3efdd2..98efbc32f3 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -82,7 +82,6 @@ typedef struct lavf_priv {
struct sh_stream **streams; // NULL for unknown streams
int num_streams;
int cur_program;
- bool use_dts;
char *mime_type;
bool genpts_hack;
AVPacket *packets[MAX_PKT_QUEUE];
@@ -541,8 +540,6 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
if (matches_avinputformat_name(priv, "avi")) {
/* for avi libavformat returns the avi timestamps in .dts,
* some made-up stuff that's not really pts in .pts */
- priv->use_dts = true;
- demuxer->timestamp_type = TIMESTAMP_TYPE_SORT;
} else {
int mode = lavfdopts->genptsmode;
if (mode == 0 && opts->correct_pts)
@@ -785,14 +782,18 @@ static int demux_lavf_fill_buffer(demuxer_t *demux)
dp = new_demux_packet_fromdata(pkt->data, pkt->size);
dp->avpacket = talloc_steal(dp, pkt);
- int64_t ts = priv->use_dts ? pkt->dts : pkt->pts;
- if (ts != AV_NOPTS_VALUE) {
- dp->pts = ts * av_q2d(st->time_base);
- priv->last_pts = dp->pts * AV_TIME_BASE;
- dp->duration = pkt->duration * av_q2d(st->time_base);
- if (pkt->convergence_duration > 0)
- dp->duration = pkt->convergence_duration * av_q2d(st->time_base);
+ if (pkt->pts != AV_NOPTS_VALUE) {
+ dp->pts = pkt->pts * av_q2d(st->time_base);
+ priv->last_pts = dp->pts;
}
+ if (pkt->dts != AV_NOPTS_VALUE) {
+ dp->dts = pkt->dts * av_q2d(st->time_base);
+ if (priv->last_pts == AV_NOPTS_VALUE)
+ priv->last_pts = pkt->dts;
+ }
+ dp->duration = pkt->duration * av_q2d(st->time_base);
+ if (pkt->convergence_duration > 0)
+ dp->duration = pkt->convergence_duration * av_q2d(st->time_base);
dp->pos = pkt->pos;
dp->keyframe = pkt->flags & AV_PKT_FLAG_KEY;
// Use only one stream for stream_pts, otherwise PTS might be jumpy.
diff --git a/demux/packet.h b/demux/packet.h
index 96e3885761..ca57179acb 100644
--- a/demux/packet.h
+++ b/demux/packet.h
@@ -26,6 +26,7 @@
typedef struct demux_packet {
int len;
double pts;
+ double dts;
double duration;
double stream_pts;
int64_t pos; // position in source file byte stream
diff --git a/mpvcore/av_common.c b/mpvcore/av_common.c
index 11d1090146..d4fa6d426f 100644
--- a/mpvcore/av_common.c
+++ b/mpvcore/av_common.c
@@ -20,7 +20,7 @@
#include <libavutil/common.h>
#include <libavcodec/avcodec.h>
-#include "mpvcore/mp_talloc.h"
+#include "mpvcore/mp_common.h"
#include "demux/packet.h"
#include "av_common.h"
#include "codecs.h"
@@ -60,11 +60,19 @@ void mp_copy_lav_codec_headers(AVCodecContext *avctx, AVCodecContext *st)
avctx->bits_per_coded_sample = st->bits_per_coded_sample;
}
+// 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).
-// Does not set pts or duration fields.
+// Sets pts/dts to reinterpret-casted mpv values - these are useful for
+// reading back via mp_get_av_frame_okt_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)
{
+ assert(sizeof(int64_t) >= sizeof(double));
+
av_init_packet(dst);
dst->data = mpkt ? mpkt->buffer : NULL;
dst->size = mpkt ? mpkt->len : 0;
@@ -76,6 +84,19 @@ 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.
+// Normally, this returns the pts. If the pts is unknown, return dts instead.
+double mp_get_av_frame_pkt_pdts(AVFrame *frame)
+{
+ double pts = (union pts){.i = frame->pkt_pts}.d;
+ double dts = (union pts){.i = frame->pkt_dts}.d;
+ return pts == MP_NOPTS_VALUE ? dts : pts;
}
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 2fa8f127b0..683570971d 100644
--- a/mpvcore/av_common.h
+++ b/mpvcore/av_common.h
@@ -26,6 +26,7 @@ struct demux_packet;
void mp_copy_lav_codec_headers(AVCodecContext *avctx, AVCodecContext *st);
void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt);
+double mp_get_av_frame_pkt_pdts(AVFrame *frame);
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/mpvcore/player/video.c b/mpvcore/player/video.c
index c162cfa51a..a1585e560d 100644
--- a/mpvcore/player/video.c
+++ b/mpvcore/player/video.c
@@ -302,8 +302,7 @@ static void determine_frame_pts(struct MPContext *mpctx)
if (opts->user_pts_assoc_mode)
d_video->pts_assoc_mode = opts->user_pts_assoc_mode;
else if (d_video->pts_assoc_mode == 0) {
- if (d_video->header->demuxer->timestamp_type == TIMESTAMP_TYPE_PTS
- && d_video->codec_reordered_pts != MP_NOPTS_VALUE)
+ if (d_video->codec_reordered_pts != MP_NOPTS_VALUE)
d_video->pts_assoc_mode = 1;
else
d_video->pts_assoc_mode = 2;
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 03d77e1c2b..c13ef68aad 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -746,9 +746,6 @@ static int decode(struct dec_video *vd, struct demux_packet *packet,
mp_set_av_packet(&pkt, packet);
- // We merely pass-through our PTS as an int64_t; libavcodec won't use it.
- union pts { int64_t i; double d; };
- pkt.pts = (union pts){.d = packet ? packet->pts : MP_NOPTS_VALUE}.i;
ret = avcodec_decode_video2(avctx, ctx->pic, &got_picture, &pkt);
if (ret < 0) {
mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Error while decoding frame!\n");
@@ -760,7 +757,7 @@ static int decode(struct dec_video *vd, struct demux_packet *packet,
return 0;
update_image_params(vd, ctx->pic);
- double out_pts = (union pts){.i = ctx->pic->pkt_pts}.d;
+ double out_pts = mp_get_av_frame_pkt_pdts(ctx->pic);
// Note: potentially resets ctx->pic as it is transferred to mpi
struct mp_image *mpi = image_from_decoder(vd);