Commit Graph
55444 Commits
Author SHA1 Message Date
Kacper Michajłow abbbffe0dd demux_disc: hold BD jump boundaries for the player's resync seek
The resync seek that follows a disc-initiated jump must not reposition
the VM. On BD the jump is handled out-of-band by reopening the slave
demuxer on the packet-read path, and the VM already sits at the jump
destination. Repositioning it with the (stale) seek target time would
hop to the wrong place. Adopting the discontinuity counter here would
leave the old slave demuxer parsing the new playlist's data with the
wrong codec context. Flush our side only, and keep the counter stale so
the read path still performs the reopen.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 4a110f39cf demux_disc: map timestamps with per-stream timeline generations
Discs restart the in-stream timestamps at cell/segment boundaries. The
single global base_dts/last_dts pair rebased on any |diff| >= 5s between
consecutive packets of any stream, which broke down in several ways:

- Backward resets smaller than the threshold (e.g. a 1.5s menu
  transition cell followed by the looping button cell) were not detected
  at all, producing non-monotonic playback timestamps.
- The global last_dts ping-ponged between streams that cross a boundary
  at different packet positions (interleave skew), rebasing on nearly
  every packet and spamming the log.
- Menu subpictures timestamped for the next cell were mapped with the
  previous cell's offset and displayed at the wrong time.

Map each segment as a timeline "generation" with its own raw->playback
offset instead. Boundaries are detected per stream, as a backward step
beyond muxing jitter or a forward gap that would stall playback (sparse
still-image streams exempt). The previous generation stays valid until
every stream has moved past the boundary, and the new generation is
placed so the triggering stream continues seamlessly.

DVD subpictures are muxed around cell boundaries and their raw
timestamps alone cannot tell whether they continue the current segment
or belong to the next one. Defer each by one a/v packet (or EOF) and
let the packet that follows settle which generation it belongs to.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 02ec593037 stream: auto-detect .iso DVD-Video, DVD-Audio and Blu-ray images
Passing a disc image directly (e.g. `mpv disc.iso`) previously fell
through to FFmpeg. Route it to the matching disc backend instead,
like the VIDEO_TS.IFO/AUDIO_TS.IFO/BDMV redirectors already do.
2026-08-26 01:47:41 +02:00
Kacper Michajłow fee9b14d46 demux_disc: handle slideshow DVD titles
Audio DVDs commonly author each song as a chapter whose video is a
single (or more) still frame, with only the audio really interleaved.
Detect this at runtime and mark the video still_image. The player then
treats it as sparse, and the starved stream stops forcing eager reads
that would scan through the source hunting for the next still.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 4109805d0c demux_disc: follow the disc's initial audio stream selection
The player's default track selection picks the first probed audio
track, but the substream the disc's current PGC actually plays is
decided by the DVD VM and may be a different one. On discs whose menu
domain plays LPCM while the mux also carries an (unreferenced) AC3
substream, mpv selected the AC3 track, which has no data. We have to
keep track of what VM wants to output and what LAVF expects.
2026-08-26 01:47:41 +02:00
Kacper Michajłow c855d13170 stream_dvdnav: resync disc-initiated jumps through the seek path
When the disc VM jumps (menu activation, end of title), the demuxer
and player have to flush and reinitialize exactly at the boundary.

Hold an EOF at the boundary until the demuxer acks it, and resync
the player with a regular seek, which already orders flush, decoder
reset and restart. d_seek recognizes the held boundary and releases
it instead of repositioning the VM.

Also log the VM domain in nav event messages.
2026-08-26 01:47:41 +02:00
Kacper Michajłow daaab42166 player: rejoin the restart for a video frame after a transient EOF
A sparse video stream can report a transient EOF during a restart. The
DVD-Audio still track is read lazily and its first frame may arrive a
moment after the video chain already drained. Treat a frame arriving
while the restart is in progress as the restart's first frame.
2026-08-26 01:47:41 +02:00
Kacper Michajłow b3e3d1774e player: fix timing of sparse still-image video streams
Sparse video with continuous audio broke playback timing in several
ways:

- The first frame after a seek/restart was always shown immediately.
  With sparse video the frame at the seek target may not exist, and the
  next still can lie minutes ahead. Showing it early displays the wrong
  image.
- hr-seeks dropped frames with PTS below the target. For sparse video
  the nearest preceding still is the correct frame to show.
- Frame scheduling used the incremental A/V delay accounting, which is
  unusable across the video-EOF gaps between stills. Schedule sparse
  frames directly against the audio clock instead.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 34c649b864 demux: allow demuxers to update still_image during demuxing
Whether a DVD title's video track consists of sparse still images (a
slideshow) is only observable from the packet timestamps after
streaming started, and demux_disc wants to flip sh->still_image
accordingly, so that the stream stops being read eagerly.
2026-08-26 01:47:41 +02:00
Kacper Michajłow a2448f3b81 stream_dvda: expose DVD-Audio still images as a cover-art video track
DVD-Audio discs carry an Audio Still Video Set (ASVS). An MPEG-2 still
images (cover art, booklet/lyric pages) that the disc associates with
tracks.

A new STREAM_CTRL_GET_STILL returns the still for a given playback time.
demux_disc exposes it as a selectable mpeg2video track and injects the
still as a keyframe at the track's playback time. It changes as playback
crosses track boundaries (and follows onset times when a disc encodes
them).

--dvda-page (with the new STREAM_CTRL_SET_STILL_PAGE) forces a specific
still page instead of the scheduled one. The still state is guarded by
a mutex, runtime page changes arrive from the player thread while the
demuxer thread extracts stills.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 263bea5261 demux: read sparse still-image streams lazily
still_image streams (AV_DISPOSITION_STILL_IMAGE) consist of sparse
frames that can be minutes apart. When such a stream was selected
alongside an eager audio/video stream, its empty packet queue forced
the demuxer to keep reading ahead, buffering the whole file trying to
chase min_secs of "video". Read them lazily when other eager streams
exist, so playback drives read-ahead instead.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 8c6680a868 osdep/w32_register: add a DVD-Audio AutoPlay handler
Register mpv for the PlayDVDAudioOnArrival event, like the existing
CD-Audio/DVD/Blu-ray handlers.
2026-08-26 01:47:41 +02:00
Kacper Michajłow be04215d3f stream_dvda: add DVD-Audio playback support
Add a dvda:// protocol backed by libdvdread. Audio title sets are
enumerated from the ATS IFOs. Each ATS title is exposed as an mpv
title/edition and its tracks as chapters.

Menus are not supported, they would need full VM implementation, and
libdvdnav currently doesn't support DVD-Audio.

Still images (ASVS) may be supported in the future.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 76c0c5de03 stream_dvdnav: lock event processing
The menu/highlight state is filled by event processing on the demuxer
thread and read by nav commands and controls on the player thread. Add
a mutex around it.
2026-08-26 01:47:41 +02:00
Kacper Michajłow bb19b0fc36 stream_bluray: remove BD_EVENT_POPUP and menu-event tracking
BD_EVENT_POPUP was tracked into has_popup, which never grew a
consumer. BD_EVENT_MENU's menu_event_active only fed the menu_active
condition, where it was subsumed by the visible-overlay check. Remove
all three.
2026-08-26 01:47:41 +02:00
Kacper Michajłow c9422ff88f stream: turn the highlight fields into mp_dvdnav_highlight
The highlight rectangle and palette were passed around as loose fields
in three places. Bundle them into a struct, pass the whole nav state to
the sd_lavc control.
2026-08-26 01:47:41 +02:00
Kacper Michajłow c7859fe5b6 sub/osd_state: rename external2 to image_overlay 2026-08-26 01:47:41 +02:00
Kacper Michajłow b17b4371f8 stream_bluray: route logs through mp_log
This is awkward, because libbluray has a single global log callback.
libmpv can spawn multiple players in a single process, and the
instance created last takes over the callback (the previous instance's
log stays alive until its stream closes, so a racing callback never
sees a dangling pointer). This mirrors how ffmpeg logging works.

The callback delivers only a string without severity, so everything is
printed as MSGL_DEBUG, with the libbluray debug mask derived from our
log level.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 15f8a74aa4 stream_dvdnav: route logs from libdvdnav through mp_log
Use dvdnav_open2() with a logger callback instead of letting libdvdnav
print to stderr. This bumps the libdvdnav requirement to 6.1.0. 6.1.0 is
from 2019, it's resonable to request it by now.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 7c13c58ffa stream_dvdnav: keep cached duration in native time base
Store the duration in 90 kHz ticks instead of converting back and
forth. This also fixes STREAM_CTRL_GET_CURRENT_TIME's failure check,
which previously compared the already-converted value against -1 and
could never trigger.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 61416bd8b5 stream_bluray: rename BD_TIME_TO_MP to BD_TIME_TO_S 2026-08-26 01:47:41 +02:00
Kacper Michajłow b48fb6c86c demux_lavf: seek avfc only on seekable streams in drop_buffers
Disc streams are only seekable through the higher-level stream
controls, a byte seek on the slave can only fail and log errors.
avformat_flush() below already resets the demuxer state.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 2c8d954d21 demux_disc: only add the menu edition for streams with menu support 2026-08-26 01:47:41 +02:00
Kacper Michajłow 8356c7f674 demux_disc: keep one-shot DVD menu subpictures deliverable
Keep DVD SPU streams always enabled at the slave level and retain the
last subpicture per substream. Re-deliver the retained copy when a sub
track is (re)selected and when the player resets playback state.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 47a53910a5 demux: parent chapter metadata to the chapter list
demux_disc replaces the chapter list at runtime. Parent each chapter's
tags to the list that contains them, so a replaced list keeps owning
its metadata instead of accumulating it on the demuxer.
2026-08-26 01:47:41 +02:00
Kacper Michajłow b0c4e8cab6 demux_disc: soft-reload the slave demuxer on DVD discontinuities
A full slave reopen makes libavformat re-probe the stream, which eats
packets around the jump (losing the one-shot menu SPU) and re-bases the
timestamps. DVD cannot change codecs across a jump, so flushing the
slave and refreshing duration/chapters/edition is enough. BD keeps the
full reopen because codecs can change across titles.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 582810ac1d 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.
2026-08-26 01:47:41 +02:00
Kacper Michajłow dbe496e6be demux_lavf: clear sticky avio EOF in drop_buffers
A stream can report a one-shot EOF and then continue producing data
(disc-nav jump boundaries). Also clear a sticky read error, the
underlying source is being reused.
2026-08-26 01:47:41 +02:00
Kacper Michajłow af53a9dc4b stream_bluray: rework fill_buffer around bd_read_ext
Menu support added bd_read_ext for events but kept the old bd_read
path, leaving two read loops. Use bd_read_ext everywhere and handle
all events in one place.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 4084e7609f stream_bluray: add support for still frames
Track BD_EVENT_STILL/STILL_TIME. Hold playback on indefinite stills and
skip timed stills only. Activations on a held still bump the
discontinuity counter, the disc VM will jump.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 3897b3a579 stream_dvdnav: add support for still frames
DVDNAV_STILL_FRAME means the VM is holding a frame indefinitely (menu
pages, some logos) or for a timed duration. Report the indefinite case
via nav state so the player holds playback at EOF instead of ending
the file, and skip timed stills, which would otherwise stall playback.
2026-08-26 01:47:41 +02:00
Kacper Michajłow fbcced5bf0 stream_bluray: lock all controls that read cached disc state
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.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 5f19209953 stream_bluray: use 1-based angle, same as in DVD
Internally the angle stays 0-based (matching the libbluray API), only
the user-visible option/property values are 1-based. BD_EVENT_ANGLE
delivers a 1-based value and is converted on arrival.
2026-08-26 01:47:41 +02:00
Kacper Michajłow f0bc30aaf1 demux: adapt caching to interactive disc navigation
The disc VM advances when the stream is read, so in nav mode the cache
must not run ahead of what the user is seeing. Never read ahead (a
looping menu is endless). Never satisfy seeks from the cache either.

This applies to the whole disc session, not only while a menu is on
screen. The VM can jump at any time (BD-J timers, end of title), so
the cache must never run ahead of playback.

Activations still must be able to drive the VM while nothing is
consumed. demux_drive_nav() forces a single read for them.
2026-08-26 01:47:41 +02:00
Kacper Michajłow c625405ddc stream_bluray: add BD-J menu support
Adds support for the ARGB overlay callback from libbluray. libbluray
does not convert between its overlay formats, BD-J planes arrive as
ARGB while HDMV planes arrive RLE-encoded, so both callbacks have to
be supported.

When the Java VM is not available, fall back to non-menu playback.

Also bump libbluray requirement to 1.0.2, it was released in 2017.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 70174945a4 discnav: sync track selection state with VM
The disc VM selects audio and subpicture streams itself (menu SPU
highlights, title-authored stream changes on jumps). Follow the VM's
selection on every hop, and turn subtitles on/off with the disc's
sub_visible flag.

The sync only applies while the corresponding track selection is on
auto. An explicitly chosen track (--aid/--sid or runtime cycling) is
never overridden.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 4725c2e492 demux_disc: set partially_seekable to true
This suppresses refresh seeks (e.g. on track switches). A refresh seek
would reposition the disc VM, which breaks menus and can hop to a
different position entirely. Track switching relies on the always-on
readahead of the disc demuxer instead.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 216e26c871 player/command: add discnav command and bind default keys
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 allows binding controls that are only
active while a disc menu is on screen.

Setting the edition property on a disc jumps to the title through the
stream directly, so selecting the currently-playing edition can still
return to it from a menu.
2026-08-26 01:47:41 +02:00
Kacper Michajłow a5682eb2ad player/command: add disc-menu-active property 2026-08-26 01:47:41 +02:00
Kacper Michajłow 5713c30160 player/loadfile: react to runtime chapter/edition list updates
On DEMUX_EVENT_LISTS, re-copy the chapter list and notify the
chapter/edition properties, so a disc title change is reflected in
observed properties and the OSC.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 816eca1fef player/loadfile: auto-select default tracks added after initial open
play_current_file picks default tracks once, then leaves them alone.
That leaves later-surfacing streams without a default selection. This
applies to all demuxers with late-added streams, not only discs.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 652ca81af9 player: add disc-menu state holder and overlay support
The new player/discnav.c owns the player-side state for the in-disc
menu UI, shared between stream_bluray and stream_dvdnav. Once per
playloop iteration it pulls the stream's nav state and

- pushes the BD menu plane to the OSD (OSDTYPE_DISC_MENU) and the DVD
  highlight state to the dvd_subtitle decoders,
- resyncs playback when the disc VM jumped on its own, detected
  through the stream's discontinuity counter,
- mirrors the disc's current title into demuxer->edition,
- force-selects a dvd_subtitle track while a DVD menu is up, so the
  menu graphics decoded by sd_lavc reach the OSD, and
- enables the {discnav} input section while a menu is interactive.

The per-file state is reset on every new playlist entry.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 8d36904e05 sub/osd: add OSDTYPE_DISC_MENU
A dedicated OSD object for the disc menu overlay. It renders above the
subtitle tracks and below mpv's own OSD.
2026-08-26 01:47:41 +02:00
Kacper Michajłow e204c1cfd9 demux_disc: add a synthetic "Disc Menu" edition
Expose the disc menu in the edition list, after the titles, so it can
be reached like any title.
2026-08-26 01:47:41 +02:00
Kacper Michajłow af9a11a8e5 demux_disc: reopen slave demuxer on disc-nav hops
Playing a disc through the menu means crossing playlist boundaries at
runtime: menu -> title (and back), sub-menu -> sub-menu, title -> title.
Each new playlist can have a different stream count and/or a different
codec mix. 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.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 3a8b6995e9 stream_bluray: implement HDMV menu navigation
Add HDMV menu support to stream_bluray, activated by opening with
"bd://menu/..." or the global --disc-menu option.

The IG overlay plane arrives through the libbluray YUV overlay
callback. Decode the palettized RLE into a BGRA plane (premultiplied
alpha) and hand it to the player via STREAM_CTRL_GET_NAV_OVERLAY.
STREAM_CTRL_NAV_CMD maps arrow/select/menu/popup/mouse actions onto
bd_user_input() and bd_mouse_select(). Events relevant to the menu
state (title, playlist, menu on/off) are tracked so
STREAM_CTRL_GET_NAV_STATE can report an active menu, and playlist
changes bump discontinuity_id so the player flushes stale packets.
2026-08-26 01:47:41 +02:00
Kacper Michajłow b17feb1f79 stream_dvdnav: implement DVD menu navigation
Drive libdvdnav's menu state through the new disc-nav protocol so the
player can show and interact with VMGM and VTSM menus.

STREAM_CTRL_NAV_CMD maps the nav actions onto libdvdnav.

STREAM_CTRL_GET_NAV_STATE reports whether a menu with buttons is on
screen, the highlight rectangle and palette of the focused button, and
the ids of the disc-selected audio/SPU streams.

Menu mode is entered by opening with dvd://menu or --disc-menu, which
starts at the disc's root menu instead of a title.
2026-08-26 01:47:41 +02:00
Kacper Michajłow fbd0e047b1 options: add disc-menu option 2026-08-26 01:47:41 +02:00
Kacper Michajłow e2b7a983fa stream: add disc-nav actions and states
Define three new stream controls so disc backends (libdvdnav, libbluray)
can expose their in-disc menu/highlight state to the player.

Not used yet, the next commits add the backends and the player side.
2026-08-26 01:47:41 +02:00
Kacper Michajłow 5db1db2852 demux: allow updating duration, chapters and editions during playback
Disc demuxers switch titles and playlists at runtime, which changes the
duration and replaces the chapter/edition lists. Add
demux_set_duration() and demux_lists_changed() for demuxers to publish
such updates, and DEMUX_EVENT_LISTS for the player to react.
2026-08-26 01:47:41 +02:00