diff options
-rw-r--r-- | demux/demux.c | 7 | ||||
-rw-r--r-- | demux/demux.h | 7 | ||||
-rw-r--r-- | demux/demux_lavf.c | 21 | ||||
-rw-r--r-- | demux/packet.h | 1 | ||||
-rw-r--r-- | mpvcore/av_common.c | 25 | ||||
-rw-r--r-- | mpvcore/av_common.h | 1 | ||||
-rw-r--r-- | mpvcore/player/video.c | 3 | ||||
-rw-r--r-- | video/decode/vd_lavc.c | 5 |
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); |