Skip to content

Add DVD / Blu-Ray menu support#18080

Open
kasper93 wants to merge 21 commits into
mpv-player:masterfrom
kasper93:bd-dvd
Open

Add DVD / Blu-Ray menu support#18080
kasper93 wants to merge 21 commits into
mpv-player:masterfrom
kasper93:bd-dvd

Conversation

@kasper93

@kasper93 kasper93 commented Jun 6, 2026

Copy link
Copy Markdown
Member

No description provided.

@kasper93 kasper93 force-pushed the bd-dvd branch 3 times, most recently from 072b324 to 499ba28 Compare June 6, 2026 02:33
@kasper93 kasper93 force-pushed the bd-dvd branch 4 times, most recently from d698b40 to ddfc443 Compare June 7, 2026 21:12
Comment thread player/discnav.c
@@ -0,0 +1,449 @@
/*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole file could be a builtin client.

As long as mpv provides the overlay images, the clients have all the necessary parts to display and control menu with discnav and overlay-add commands.

There are code later using osd_set_external2 which overwrite user added overlay-add overlays. This does not belong to the core.

Comment thread stream/stream_bluray.c Outdated
@qyot27

qyot27 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Just to mention it in case it might need some adjustment with all these changes before they finalize, but how easily would potential future DVD-Audio support slot in amongst this? I'm not sure if it employs any visual menuing, since most DVD players would pick up the VIDEO_TS part of the disc instead.

libdvd{css,read} can properly handle DVD-Audio now, and VLC has it enabled in the nightlies, but I don't know if it can easily be bolted onto mpv's existing DVD-Video parsing or if it would require much deeper changes (or at worst, just get siloed off into its own component if it's too different and accessed via dvda://whatever).

@kasper93 kasper93 added this to the Release v0.42.0 milestone Jun 27, 2026
kasper93 added 18 commits July 1, 2026 04:47
DVDNAV_VTS_CHANGE casts the just-written event payload to
dvdnav_vts_change_event_t. The cast was reading from s->buffer (the
stream's ring buffer, untouched by this read), not buf (the demuxer's
destination that dvdnav_get_next_block actually wrote into).

While here, drop the message to MP_VERBOSE and fix its wording.
"switched to title" is misleading because this is a VTS-change event.
not a title change.
This is connected to standard DVD subs renderer, with additional state
passed for highlight color.
They are expected in normal operation of libdvdread, where changing
titles, causes natural jump in PTS.
Define three new stream controls so disc backends (libdvdnav, libbluray)
can expose their in-disc menu/highlight state to the player.

STREAM_CTRL_NAV_CMD - send a navigation action
STREAM_CTRL_GET_NAV_STATE - get current menu state
STREAM_CTRL_GET_NAV_OVERLAY - get BGRA overlay that should be drawn (BD)

Not used yet, will get use in next commits.
Drive libdvdnav's menu state through the new disc-nav protocol so the
player can show / interact with VMGM and VTSM menus:
Add HDMV menu support to stream_bluray. Activated by opening with
"bd://menu/..." or by the global --disc-menu option

Lots of plumbing the libbluary event loop. Menus are read though
different function even.

STREAM_CTRL_NAV_CMD maps arrow/select/menu/popup/mouse onto
bd_user_input and bd_mouse_select. SELECT and MOUSE_CLICK queue an
HDMV VM command (often PlayPlaylist) that won't execute until the
next demuxer read, so we bump discontinuity_id pre-emptively; the
player's post-action check then sees the change and flushes cached
audio/video that would otherwise keep playing for seconds while the
new playlist is already arriving.
Playing a disc through the menu means crossing playlist boundaries at
runtime: menu -> title (and back), sub-menu -> sub-menu, title -> title
on a "Play next" button. Each new playlist can have a different stream
count and/or a different codec mix (a MPEG-2 menu into an H.264 main
feature is common on BD-Video). The previous slave demuxer was probed
once at open and never refreshed, so after a hop the player either kept
decoding stale streams or saw nothing at all.

Tear down and re-open the slave on every nav discontinuity.

add_stream_editions() now appends a synthetic "Disc Menu" entry at
index num_titles.
New player/discnav.c owns the state for the in-disc menu UI. Used to
display menu and control the DVD / BD playback. This is common part
between stream_bluray.c and stream_dvdnav.c.
play_current_file picks default tracks once, then leaves them alone.
That leaves later-surfacing streams without a default selection.
User-facing entry point for in-disc menu navigation. The command
forwards an action (up/down/left/right/select/menu/title-menu/popup/
prev/mouse-move/mouse-click) to the current disc stream handler

The new `discnav` input section is defined to allow binding specific
controls only for disc menu.
Fixes track switching on some discs.
Adds support for ARGB callback from libbluray. For some reason they
don't have unified support, and sometimes it uses ARGB (for BD-J) and
RLE (for HDMV), while they could convery RLE encoded menus into ARGB
bitmaps, if only one is supproted. We have to support both.

When Java VM is not available, fallbacks to non-menu playback.
kasper93 added 3 commits July 1, 2026 04:47
VM events are processed in fill_buffer callback, which are called by the
demuxer thread. The should be processed close to what user is seeing on
screen, else VM will think that we are at different point and may
trigger action before user sees whole cache.
We cache some state like title properties, in some cases during deinit
player thread may actually try to read it during demuxer thead read.
Just add a lock, it shouldn't be called frequently to cause too much
synchronization.
Comment thread stream/stream_bluray.c
Comment on lines +202 to +219
static enum pl_color_system bd_overlay_csp(struct bluray_priv_s *priv)
{
const BLURAY_TITLE_INFO *ti = priv->title_info;
if (!ti || !ti->clip_count || !ti->clips[0].video_stream_count)
return PL_COLOR_SYSTEM_BT_709;
const BLURAY_STREAM_INFO *vs = &ti->clips[0].video_streams[0];
switch (vs->format) {
case BLURAY_VIDEO_FORMAT_2160P: // UHD: always BT.2020
return PL_COLOR_SYSTEM_BT_2020_NC;
case BLURAY_VIDEO_FORMAT_480I: // ITU-R BT.601
case BLURAY_VIDEO_FORMAT_576I:
case BLURAY_VIDEO_FORMAT_480P:
case BLURAY_VIDEO_FORMAT_576P:
return PL_COLOR_SYSTEM_BT_601;
default:
return PL_COLOR_SYSTEM_BT_709;
}
}

@cubicibo cubicibo Jul 1, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static enum pl_color_system bd_overlay_csp(struct bluray_priv_s *priv)
{
    const BLURAY_TITLE_INFO *ti = priv->title_info;
    if (!ti || !ti->clip_count || !ti->clips[0].video_stream_count)
        return PL_COLOR_SYSTEM_BT_709;
    const BLURAY_STREAM_INFO *vs = &ti->clips[0].video_streams[0];

    // HEVC on UHD BD (2160p or 1080p) can be either 2020 or 709
    if (vs->coding_type == BLURAY_STREAM_TYPE_VIDEO_HEVC || vs->format == BLURAY_VIDEO_FORMAT_2160P)
        return vs->color_space == BLURAY_COLOR_SPACE_BT2020 ? PL_COLOR_SYSTEM_BT_2020_NC : PL_COLOR_SYSTEM_BT_709;

    switch (vs->format) {
    case BLURAY_VIDEO_FORMAT_480I:  // ITU-R BT.601
    case BLURAY_VIDEO_FORMAT_576I:
    case BLURAY_VIDEO_FORMAT_480P:
    case BLURAY_VIDEO_FORMAT_576P:
        return PL_COLOR_SYSTEM_BT_601;
    default:
        return PL_COLOR_SYSTEM_BT_709;
    }
}

Not relying on color_space of libbluray alone because it seems to be specified only for UHD BD format as it does not specify BT.601.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants