mirror of
https://github.com/mpv-player/mpv
synced 2024-12-22 06:42:03 +00:00
demux: export dts from demux_lavf, use it for avi
Having the DTS directly can be useful for restoring PTS values. The avi file format doesn't actually store PTS values, just DTS. An older hack explicitly exported the DTS as PTS (ignoring the [I assume] genpts generated non-sense PTS), which is not necessary anymore due to this change.
This commit is contained in:
parent
d8b59aa17f
commit
9f72a9753e
@ -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),
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user