demux_mkv: don't apply AVI b-frame delay compensation to VfW tracks

crazy_video_pts_stuff() shifts video PTS back by the codec delay to undo
libavcodec returning frames paired with a later packet's DTS. This is
only correct for genuine AVI, where DTS are decode-order frame indices.

VfW-muxed Matroska looks similar but its block timestamps are real DTS,
already offset by the reorder delay, so the libavcodec shift cancels the
offset and no compensation is needed. Applying it anyway pushed video
one frame ahead of audio (e.g. VC-1, whose Advanced Profile always
reports has_b_frames=1).

Split the `avi_dts` flag. Deep DTS routing for VfW mkv via a new
`block_dts`, and reserve avi_dts for genuine AVI only.

Note that demux_lavf for Matroska was already not affected, because
`avi_dts` wouldn't be set for those.

Fixes #18089
This commit is contained in:
Kacper Michajłow committed 2026-06-17 23:55:51 +02:00
1 parent 02491a3949
commit f8150c78d5
2 files changed
+6 -3

No files matched your search

+1 -1
View File
@@ -775,7 +775,7 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
sh->codec->dv_level = cfg->dv_level;
}
// This also applies to vfw-muxed mkv, but we can't detect these easily.
// AVI uses decode-order indices as DTS and needs the compensation.
sh->codec->avi_dts = matches_avinputformat_name(priv, "avi");
break;
+5 -2
View File
@@ -145,6 +145,9 @@ typedef struct mkv_track {
bool require_keyframes;
// VfW mode: block timestamps are real DTS, route them to the packet DTS.
bool block_dts;
/* stuff for realaudio braincancer */
double ra_pts; /* previous audio timestamp */
uint32_t sub_packet_size; ///< sub packet size, per stream
@@ -1647,7 +1650,7 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
extradata = track->private_data + 40;
extradata_size = track->private_size - 40;
mp_set_codec_from_tag(sh_v);
sh_v->avi_dts = true;
track->block_dts = true;
} else if (track->private_size >= RVPROPERTIES_SIZE
&& (!strcmp(track->codec_id, "V_REAL/RV10")
|| !strcmp(track->codec_id, "V_REAL/RV20")
@@ -3108,7 +3111,7 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
dp->pts = current_pts + i * track->default_duration;
dp->keyframe = keyframe;
}
if (stream->codec->avi_dts)
if (track->block_dts)
MPSWAP(double, dp->pts, dp->dts);
if (i == 0 && block_info->duration_known)
dp->duration = block_duration / 1e9;