From 582810ac1df4aa4e94e5d0fb164773f7d5602ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sat, 4 Jul 2026 15:33:43 +0200 Subject: [PATCH] stream_dvdnav: emit a one-shot EOF at source jump boundaries Menu activations, HOP_CHANNEL and VTS changes jump the source position. On this strictly forward stream the demuxer cannot tell where the old content ends, so buffered pre-jump data would mix with post-jump data. Return a single EOF at the boundary so the demuxer drains and resets before any new content flows. --- stream/stream_dvdnav.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/stream/stream_dvdnav.c b/stream/stream_dvdnav.c index 74586d25c4..61e17b7f3a 100644 --- a/stream/stream_dvdnav.c +++ b/stream/stream_dvdnav.c @@ -79,6 +79,7 @@ struct priv { uint32_t hl_palette[4]; // 0xAARRGGBB for SPU pixel values 0..3 uint32_t nav_change_id; uint32_t discontinuity_id; // bumped on actions that may jump + bool pending_drain; // emit one EOF at the next jump boundary int src_w, src_h; // video resolution in pixels int auto_actioned_button; // last auto-activated button; 0 if none @@ -468,6 +469,13 @@ static void do_nav_cmd(stream_t *stream, struct stream_nav_cmd *cmd) update_highlight(priv); } +// Mark a source-position jump. +static void bump_discontinuity(struct priv *priv) +{ + priv->discontinuity_id++; + priv->pending_drain = true; +} + static void handle_nav_cmd(stream_t *stream, struct stream_nav_cmd *cmd) { struct priv *priv = stream->priv; @@ -477,7 +485,7 @@ static void handle_nav_cmd(stream_t *stream, struct stream_nav_cmd *cmd) bool activated = stream_nav_action_activates(cmd->action) || priv->auto_actioned_button != prev_auto; if (priv->still_active && activated) - priv->discontinuity_id++; + bump_discontinuity(priv); } /** @@ -559,6 +567,10 @@ static int fill_buffer(stream_t *s, void *buf, int max_len) } while (1) { + if (priv->pending_drain) { + priv->pending_drain = false; + return 0; + } int len = -1; int event = DVDNAV_NOP; if (dvdnav_get_next_block(dvdnav, buf, &event, &len) != DVDNAV_STATUS_OK) @@ -613,7 +625,7 @@ static int fill_buffer(stream_t *s, void *buf, int max_len) break; case DVDNAV_HOP_CHANNEL: // Bump discontinuity_id so the playloop flushes the cache. - priv->discontinuity_id++; + bump_discontinuity(priv); break; case DVDNAV_HIGHLIGHT: update_highlight(priv); @@ -638,8 +650,7 @@ static int fill_buffer(stream_t *s, void *buf, int max_len) MP_WARN(s, "Requested title not found\n"); } // VTS change is a title-set boundary, flush. - refresh_video_resolution(priv); - priv->discontinuity_id++; + bump_discontinuity(priv); break; } case DVDNAV_CELL_CHANGE: { @@ -780,13 +791,13 @@ static int control(stream_t *stream, int cmd, void *arg) if (dvdnav_menu_call(priv->dvdnav, DVD_MENU_Root) != DVDNAV_STATUS_OK) break; - priv->discontinuity_id++; + bump_discontinuity(priv); stream_drop_buffers(stream); return STREAM_OK; } if (dvdnav_title_play(priv->dvdnav, title + 1) != DVDNAV_STATUS_OK) break; - priv->discontinuity_id++; + bump_discontinuity(priv); stream_drop_buffers(stream); return STREAM_OK; }