mirror of
https://github.com/mpv-player/mpv.git
synced 2026-10-23 19:38:51 +08:00
video: pass PTS as part of demux_packet/AVPacket and mp_image/AVFrame
Instead of passing the PTS as separate field, pass it as part of the usual data structures. Basically, this removes strange artifacts from the API. (It's not finished, though: the final decoded PTS goes through strange paths, and filter_video() finally overwrites the decoded mp_image's pts field with it.) We also stop using libavcodec's reordered_opaque fields, and use AVPacket.pts and AVFrame.pkt_pts. This is slightly unorthodox, because these pts fields are not "really" opaque anymore, yet we treat them as such. But the end result should be the same, and reordered_opaque is marked as partially deprecated (it's not clear whether it's really deprecated).
This commit is contained in:
+8
-13
@@ -323,8 +323,8 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx)
|
||||
update_fps(mpctx);
|
||||
int framedrop_type = check_framedrop(mpctx, frame_time);
|
||||
|
||||
void *decoded_frame = video_decode(d_video, pkt, framedrop_type,
|
||||
d_video->pts);
|
||||
pkt->pts = d_video->pts;
|
||||
void *decoded_frame = video_decode(d_video, pkt, framedrop_type);
|
||||
talloc_free(pkt);
|
||||
if (decoded_frame) {
|
||||
filter_video(mpctx, decoded_frame);
|
||||
@@ -343,7 +343,7 @@ static double update_video_attached_pic(struct MPContext *mpctx)
|
||||
return -1;
|
||||
|
||||
struct mp_image *decoded_frame =
|
||||
video_decode(d_video, d_video->header->attached_picture, 0, 0);
|
||||
video_decode(d_video, d_video->header->attached_picture, 0);
|
||||
if (decoded_frame)
|
||||
filter_video(mpctx, decoded_frame);
|
||||
load_next_vo_frame(mpctx, true);
|
||||
@@ -393,12 +393,9 @@ double update_video(struct MPContext *mpctx, double endpts)
|
||||
if (d_video->header->attached_picture)
|
||||
return update_video_attached_pic(mpctx);
|
||||
|
||||
double pts;
|
||||
|
||||
while (1) {
|
||||
if (load_next_vo_frame(mpctx, false))
|
||||
break;
|
||||
pts = MP_NOPTS_VALUE;
|
||||
struct demux_packet *pkt = NULL;
|
||||
while (1) {
|
||||
pkt = demux_read_packet(d_video->header);
|
||||
@@ -409,16 +406,14 @@ double update_video(struct MPContext *mpctx, double endpts)
|
||||
* that must have packets at fixed timecode intervals. */
|
||||
talloc_free(pkt);
|
||||
}
|
||||
if (pkt)
|
||||
pts = pkt->pts;
|
||||
if (pts != MP_NOPTS_VALUE)
|
||||
pts += mpctx->video_offset;
|
||||
if (pts >= mpctx->hrseek_pts - .005)
|
||||
if (pkt && pkt->pts != MP_NOPTS_VALUE)
|
||||
pkt->pts += mpctx->video_offset;
|
||||
if (pkt && pkt->pts >= mpctx->hrseek_pts - .005)
|
||||
mpctx->hrseek_framedrop = false;
|
||||
int framedrop_type = mpctx->hrseek_active && mpctx->hrseek_framedrop ?
|
||||
1 : check_framedrop(mpctx, -1);
|
||||
struct mp_image *decoded_frame =
|
||||
video_decode(d_video, pkt, framedrop_type, pts);
|
||||
video_decode(d_video, pkt, framedrop_type);
|
||||
talloc_free(pkt);
|
||||
if (decoded_frame) {
|
||||
determine_frame_pts(mpctx);
|
||||
@@ -433,7 +428,7 @@ double update_video(struct MPContext *mpctx, double endpts)
|
||||
if (!video_out->frame_loaded)
|
||||
return 0;
|
||||
|
||||
pts = video_out->next_pts;
|
||||
double pts = video_out->next_pts;
|
||||
if (pts == MP_NOPTS_VALUE) {
|
||||
MP_ERR(mpctx, "Video pts after filters MISSING\n");
|
||||
// Try to use decoder pts from before filters
|
||||
|
||||
@@ -206,10 +206,11 @@ bool video_init_best_codec(struct dec_video *d_video, char* video_decoders)
|
||||
}
|
||||
|
||||
void *video_decode(struct dec_video *d_video, struct demux_packet *packet,
|
||||
int drop_frame, double pts)
|
||||
int drop_frame)
|
||||
{
|
||||
mp_image_t *mpi = NULL;
|
||||
struct MPOpts *opts = d_video->opts;
|
||||
double pts = packet ? packet->pts : MP_NOPTS_VALUE;
|
||||
|
||||
if (opts->correct_pts && pts != MP_NOPTS_VALUE) {
|
||||
int delay = -1;
|
||||
@@ -242,7 +243,7 @@ void *video_decode(struct dec_video *d_video, struct demux_packet *packet,
|
||||
}
|
||||
}
|
||||
|
||||
mpi = d_video->vd_driver->decode(d_video, packet, drop_frame, &pts);
|
||||
mpi = d_video->vd_driver->decode(d_video, packet, drop_frame);
|
||||
|
||||
//------------------------ frame decoded. --------------------
|
||||
|
||||
@@ -256,6 +257,8 @@ void *video_decode(struct dec_video *d_video, struct demux_packet *packet,
|
||||
else if (opts->field_dominance == 1)
|
||||
mpi->fields &= ~MP_IMGFIELD_TOP_FIRST;
|
||||
|
||||
pts = mpi->pts;
|
||||
|
||||
double prevpts = d_video->codec_reordered_pts;
|
||||
d_video->prev_codec_reordered_pts = prevpts;
|
||||
d_video->codec_reordered_pts = pts;
|
||||
|
||||
@@ -42,8 +42,6 @@ struct dec_video {
|
||||
|
||||
void *priv;
|
||||
|
||||
float next_frame_time;
|
||||
double last_pts;
|
||||
double buffered_pts[32];
|
||||
int num_buffered_pts;
|
||||
double codec_reordered_pts;
|
||||
@@ -59,6 +57,10 @@ struct dec_video {
|
||||
int i_bps; // == bitrate (compressed bytes/sec)
|
||||
float fps; // FPS from demuxer or from user override
|
||||
float initial_decoder_aspect;
|
||||
|
||||
// State used only by player/video.c
|
||||
float next_frame_time;
|
||||
double last_pts;
|
||||
};
|
||||
|
||||
struct mp_decoder_list *video_decoder_list(void);
|
||||
@@ -68,7 +70,7 @@ void video_uninit(struct dec_video *d_video);
|
||||
|
||||
struct demux_packet;
|
||||
void *video_decode(struct dec_video *d_video, struct demux_packet *packet,
|
||||
int drop_frame, double pts);
|
||||
int drop_frame);
|
||||
|
||||
int video_get_colors(struct dec_video *d_video, const char *item, int *value);
|
||||
int video_set_colors(struct dec_video *d_video, const char *item, int value);
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ typedef struct vd_functions
|
||||
void (*uninit)(struct dec_video *vd);
|
||||
int (*control)(struct dec_video *vd, int cmd, void *arg);
|
||||
struct mp_image *(*decode)(struct dec_video *vd, struct demux_packet *pkt,
|
||||
int flags, double *reordered_pts);
|
||||
int flags);
|
||||
} vd_functions_t;
|
||||
|
||||
// NULL terminated array of all drivers
|
||||
|
||||
+11
-11
@@ -729,12 +729,11 @@ static struct mp_image *image_from_decoder(struct dec_video *vd)
|
||||
#endif /* HAVE_AVUTIL_REFCOUNTING */
|
||||
|
||||
static int decode(struct dec_video *vd, struct demux_packet *packet,
|
||||
int flags, double *reordered_pts, struct mp_image **out_image)
|
||||
int flags, struct mp_image **out_image)
|
||||
{
|
||||
int got_picture = 0;
|
||||
int ret;
|
||||
vd_ffmpeg_ctx *ctx = vd->priv;
|
||||
AVFrame *pic = ctx->pic;
|
||||
AVCodecContext *avctx = ctx->avctx;
|
||||
AVPacket pkt;
|
||||
|
||||
@@ -747,22 +746,23 @@ static int decode(struct dec_video *vd, struct demux_packet *packet,
|
||||
|
||||
mp_set_av_packet(&pkt, packet);
|
||||
|
||||
// The avcodec opaque field stupidly supports only int64_t type
|
||||
// We merely pass-through our PTS as an int64_t; libavcodec won't use it.
|
||||
union pts { int64_t i; double d; };
|
||||
avctx->reordered_opaque = (union pts){.d = *reordered_pts}.i;
|
||||
ret = avcodec_decode_video2(avctx, pic, &got_picture, &pkt);
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
*reordered_pts = (union pts){.i = pic->reordered_opaque}.d;
|
||||
|
||||
// Skipped frame, or delayed output due to multithreaded decoding.
|
||||
if (!got_picture)
|
||||
return 0;
|
||||
|
||||
update_image_params(vd, pic);
|
||||
update_image_params(vd, ctx->pic);
|
||||
double out_pts = (union pts){.i = ctx->pic->pkt_pts}.d;
|
||||
|
||||
// Note: potentially resets ctx->pic as it is transferred to mpi
|
||||
struct mp_image *mpi = image_from_decoder(vd);
|
||||
assert(mpi->planes[0]);
|
||||
mp_image_set_params(mpi, &ctx->image_params);
|
||||
@@ -772,6 +772,7 @@ static int decode(struct dec_video *vd, struct demux_packet *packet,
|
||||
|
||||
struct mp_image_params vo_params;
|
||||
mp_image_params_from_image(&vo_params, mpi);
|
||||
mpi->pts = out_pts;
|
||||
|
||||
if (!mp_image_params_equals(&vo_params, &ctx->vo_image_params)) {
|
||||
mp_image_pool_clear(ctx->non_dr1_pool);
|
||||
@@ -787,15 +788,14 @@ static int decode(struct dec_video *vd, struct demux_packet *packet,
|
||||
}
|
||||
|
||||
static struct mp_image *decode_with_fallback(struct dec_video *vd,
|
||||
struct demux_packet *packet,
|
||||
int flags, double *reordered_pts)
|
||||
struct demux_packet *packet, int flags)
|
||||
{
|
||||
vd_ffmpeg_ctx *ctx = vd->priv;
|
||||
if (!ctx->avctx)
|
||||
return NULL;
|
||||
|
||||
struct mp_image *mpi = NULL;
|
||||
int res = decode(vd, packet, flags, reordered_pts, &mpi);
|
||||
int res = decode(vd, packet, flags, &mpi);
|
||||
if (res >= 0)
|
||||
return mpi;
|
||||
|
||||
@@ -811,7 +811,7 @@ static struct mp_image *decode_with_fallback(struct dec_video *vd,
|
||||
mpi = NULL;
|
||||
if (vd->vf_initialized < 0)
|
||||
vd->vf_initialized = 0;
|
||||
decode(vd, packet, flags, reordered_pts, &mpi);
|
||||
decode(vd, packet, flags, &mpi);
|
||||
return mpi;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user