PR #25356 opened by sepro URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25356 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25356.patch
# Summary of changes The timeline started at the PTS of the first video keyframe, and every packet presented before it was discarded. A GOP can begin with B-frames that are presented before its I-frame, for example a closed GOP coded as I2 B0 B1. On some discs, these frames and the audio presented with them were lost at the start of titles and menus. When the first keyframe is presented within the first VOBU, start the timeline at that VOBU's vobu_s_ptm instead. Here is an example output from master showing the issue: ``` $ ffprobe -v trace -f dvdvideo -title 7 -i DVD03.iso 2>&1 | grep -E "NAV packet|first_pts=|Discarding frame @ st=0" [dvdvideo @ 0x5631aecbccc0] NAV packet: s_ptm=126889200 e_ptm=126932400 scr=126861174 lbn=601474 vobu_duration=43200 nav_pts=0 [dvdvideo @ 0x5631aecbccc0] st=0 pts=0 dts=-10800 pts_offset=0 first_pts=126896400 [dvdvideo @ 0x5631aecbccc0] Discarding frame @ st=0 pts=-7200 dts=-7200 is_key=0 st_mapped=1 [dvdvideo @ 0x5631aecbccc0] Discarding frame @ st=0 pts=-3600 dts=-3600 is_key=0 st_mapped=1 [dvdvideo @ 0x5631aecbccc0] st=0 pts=10800 dts=0 pts_offset=0 first_pts=126896400 [dvdvideo @ 0x5631aecbccc0] st=0 pts=3600 dts=3600 pts_offset=0 first_pts=126896400 [dvdvideo @ 0x5631aecbccc0] st=0 pts=7200 dts=7200 pts_offset=0 first_pts=126896400 ... ``` The two B-frames presented before the I-frame are discarded because first_pts is the PTS of the I-frame rather than the start PTM of the VOBU. After applying the patch, the output is: ``` [dvdvideo @ 0x15faa900] NAV packet: s_ptm=126889200 e_ptm=126932400 scr=126861174 lbn=601474 vobu_duration=43200 nav_pts=0 [dvdvideo @ 0x15faa900] st=0 pts=7200 dts=-3600 pts_offset=0 first_pts=126889200 [dvdvideo @ 0x15faa900] st=0 pts=0 dts=0 pts_offset=0 first_pts=126889200 [dvdvideo @ 0x15faa900] st=0 pts=3600 dts=3600 pts_offset=0 first_pts=126889200 [dvdvideo @ 0x15faa900] st=0 pts=18000 dts=7200 pts_offset=0 first_pts=126889200 [dvdvideo @ 0x15faa900] st=0 pts=10800 dts=10800 pts_offset=0 first_pts=126889200 [dvdvideo @ 0x15faa900] st=0 pts=14400 dts=14400 pts_offset=0 first_pts=126889200 ... ``` I did not upload any samples, as the affected discs are commercial DVDs. If this is required, I can privately share them. >From 04017f9d2efcb83aab554dbdb043c852050981c7 Mon Sep 17 00:00:00 2001 From: sepro <[email protected]> Date: Tue, 20 Oct 2026 17:58:50 +0200 Subject: [PATCH] avformat/dvdvideodec: start the timeline at the first VOBU's start PTM The timeline started at the PTS of the first video keyframe, and every packet presented before it was discarded. A GOP can begin with B-frames that are presented before its I-frame, for example a closed GOP coded as I2 B0 B1. On some discs, these frames and the audio presented with them were lost at the start of titles and menus. When the first keyframe is presented within the first VOBU, start the timeline at that VOBU's vobu_s_ptm instead. Signed-off-by: sepro <[email protected]> --- libavformat/dvdvideodec.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/libavformat/dvdvideodec.c b/libavformat/dvdvideodec.c index cf4c7962df7..d07f5bb756f 100644 --- a/libavformat/dvdvideodec.c +++ b/libavformat/dvdvideodec.c @@ -121,6 +121,8 @@ typedef struct DVDVideoPlaybackState { int ptt; /* ID of the chapter we are in now */ uint32_t vobu_duration; /* duration of the current VOBU */ uint32_t vobu_e_ptm; /* end PTM of the current VOBU */ + uint32_t ps_start_s_ptm; /* start PTM of the first VOBU */ + uint32_t ps_start_e_ptm; /* end PTM of the first VOBU */ int vtsn; /* ID of the active VTS (video title set) */ uint64_t *pgc_pg_times_est; /* PG start times as reported by IFO */ pgc_t *pgc; /* handle to the active PGC */ @@ -164,7 +166,7 @@ typedef struct DVDVideoDemuxContext { ifo_handle_t *vts_ifo; /* handle to the active VTS (VTS_nn_n.IFO) */ /* playback control */ - int64_t first_pts; /* the PTS of the first video keyframe */ + int64_t first_pts; /* PTS of the timeline origin */ int nb_angles; /* number of angles in the current title */ int play_started; /* signal that playback has started */ DVDVideoPlaybackState play_state; /* the active playback state */ @@ -482,8 +484,10 @@ static int dvdvideo_menu_next_ps_block(AVFormatContext *s, DVDVideoPlaybackState state->ptm_offset += state->vobu_e_ptm - pci.pci_gi.vobu_s_ptm; } } else { - state->in_pgc = 1; - state->in_ps = 1; + state->in_pgc = 1; + state->in_ps = 1; + state->ps_start_s_ptm = pci.pci_gi.vobu_s_ptm; + state->ps_start_e_ptm = pci.pci_gi.vobu_e_ptm; } state->vobu_e_ptm = pci.pci_gi.vobu_e_ptm; @@ -799,7 +803,9 @@ static int dvdvideo_play_next_ps_block(AVFormatContext *s, DVDVideoPlaybackState av_log(s, AV_LOG_DEBUG, "navigation: locked to program stream\n"); - state->in_ps = 1; + state->in_ps = 1; + state->ps_start_s_ptm = e_pci->pci_gi.vobu_s_ptm; + state->ps_start_e_ptm = e_pci->pci_gi.vobu_e_ptm; } else { if (state->vobu_e_ptm != e_pci->pci_gi.vobu_s_ptm) { state->ptm_discont = 1; @@ -1682,7 +1688,14 @@ static int dvdvideo_read_packet(AVFormatContext *s, AVPacket *pkt) if (st_subdemux->codecpar->codec_type != AVMEDIA_TYPE_VIDEO || !is_key) goto discard; - c->first_pts = pkt->pts; + /* the GOP may begin with B-frames that are presented before the keyframe + * (e.g. I2 B0 B1), so begin at the start PTM of the VOBU if the keyframe + * is presented within it, and at the keyframe otherwise */ + if (c->play_state.ps_start_s_ptm <= pkt->pts && pkt->pts < c->play_state.ps_start_e_ptm) + c->first_pts = c->play_state.ps_start_s_ptm; + else + c->first_pts = pkt->pts; + c->play_started = 1; } -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
