From: Marth64 <marth64@proxyid.net> To: ffmpeg-devel@ffmpeg.org Cc: Marth64 <marth64@proxyid.net>, Kacper Michajlow <kasper93@gmail.com> Subject: [FFmpeg-devel] [PATCH] avformat/dvdvideodec: fix seeking on multi-angle discs Date: Tue, 4 Feb 2025 10:55:19 -0600 Message-ID: <20250204165524.2716-2-marth64@proxyid.net> (raw) When seeking on multi-angle titles, libdvdnav does not lock on to the correct sectors initially as it seeks to find the right NAV packet. This manifests itself as two bugs: (1) When seeking on the first angle in a multi-angle segment, frames from another angle will appear (for example in intro or credits scenes). This issue is present in VLC also. (2) When seeking during a segment on angle n+1, the demuxer cannot deduce the right position from dvdnav and does not allow seeking within the segment (due to it maintaining a strict state). Correct the issue by switching to angle 1 before doing the seek operation, and skipping 3 VOBUs (NAV packet led segments) ahead where dvdnav will have positioned itself correctly. Reported-by: Kacper Michajlow <kasper93@gmail.com> Signed-off-by: Marth64 <marth64@proxyid.net> --- libavformat/dvdvideodec.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/libavformat/dvdvideodec.c b/libavformat/dvdvideodec.c index 5b9abebbf2..9596468ce2 100644 --- a/libavformat/dvdvideodec.c +++ b/libavformat/dvdvideodec.c @@ -111,6 +111,7 @@ typedef struct DVDVideoPlaybackState { int in_vts; /* if our navigator is in the VTS */ int is_seeking; /* relax navigation path while seeking */ int64_t nav_pts; /* PTS according to IFO, not frame-accurate */ + int nb_vobu_skip; /* number of VOBUs we should skip */ uint64_t pgc_duration_est; /* estimated duration as reported by IFO */ uint64_t pgc_elapsed; /* the elapsed time of the PGC, cell-relative */ int pgc_nb_pg_est; /* number of PGs as reported by IFOs */ @@ -165,6 +166,7 @@ typedef struct DVDVideoDemuxContext { /* playback control */ int64_t first_pts; /* the PTS of the first video keyframe */ + 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 */ int64_t *prev_pts; /* track the previous PTS emitted per stream */ @@ -298,6 +300,8 @@ static int dvdvideo_ifo_open(AVFormatContext *s) return AVERROR_INVALIDDATA; } + c->nb_angles = title_info.nr_of_angles; + return 0; } @@ -759,6 +763,13 @@ static int dvdvideo_play_next_ps_block(AVFormatContext *s, DVDVideoPlaybackState return AVERROR_INVALIDDATA; } + if (state->nb_vobu_skip > 0) { + av_log(s, AV_LOG_VERBOSE, "Skipping VOBU at SCR %d\n", + e_dsi->dsi_gi.nv_pck_scr); + state->nb_vobu_skip -= 1; + continue; + } + state->vobu_duration = e_pci->pci_gi.vobu_e_ptm - e_pci->pci_gi.vobu_s_ptm; state->pgc_elapsed += state->vobu_duration; state->nav_pts = dvdnav_get_current_time(state->dvdnav); @@ -1736,6 +1747,7 @@ static int dvdvideo_read_seek(AVFormatContext *s, int stream_index, int64_t time int64_t new_nav_pts; pci_t* new_nav_pci; dsi_t* new_nav_dsi; + int seek_failed = 0; if (c->opt_menu || c->opt_chapter_start > 1) { av_log(s, AV_LOG_ERROR, "Seeking is not compatible with menus or chapter extraction\n"); @@ -1755,9 +1767,30 @@ static int dvdvideo_read_seek(AVFormatContext *s, int stream_index, int64_t time c->seek_warned = 1; } + /* dvdnav loses NAV packets when seeking on multi-angle discs, so enforce angle 1 then revert */ + if (c->nb_angles > 1) { + if (dvdnav_angle_change(c->play_state.dvdnav, 1) != DVDNAV_STATUS_OK) { + av_log(s, AV_LOG_ERROR, "Unable to open angle 1 for seeking\n"); + + return AVERROR_EXTERNAL; + } + } + /* XXX(PATCHWELCOME): use dvdnav_jump_to_sector_by_time(c->play_state.dvdnav, timestamp, 0) * when it is available in a released version of libdvdnav; it is more accurate */ if (dvdnav_time_search(c->play_state.dvdnav, timestamp) != DVDNAV_STATUS_OK) { + seek_failed = 1; + } + + if (c->nb_angles > 1) { + if (dvdnav_angle_change(c->play_state.dvdnav, c->opt_angle) != DVDNAV_STATUS_OK) { + av_log(s, AV_LOG_ERROR, "Unable to revert to angle %d after seeking\n", c->opt_angle); + + return AVERROR_EXTERNAL; + } + } + + if (seek_failed) { av_log(s, AV_LOG_ERROR, "libdvdnav: seeking to %" PRId64 " failed\n", timestamp); return AVERROR_EXTERNAL; @@ -1781,6 +1814,9 @@ static int dvdvideo_read_seek(AVFormatContext *s, int stream_index, int64_t time c->play_state.ptm_discont = 0; c->play_state.vobu_e_ptm = new_nav_pci->pci_gi.vobu_s_ptm; + /* if there are multiple angles, skip the next 3 VOBUs as dvdnav will be at the wrong angle */ + c->play_state.nb_vobu_skip = c->nb_angles > 1 ? 3 : 0; + c->first_pts = 0; c->play_started = 0; c->pts_offset = timestamp; -- 2.34.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
reply other threads:[~2025-02-04 17:00 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20250204165524.2716-2-marth64@proxyid.net \ --to=marth64@proxyid.net \ --cc=ffmpeg-devel@ffmpeg.org \ --cc=kasper93@gmail.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git