Skip to content

Authored per-frame 3D subtitle depth for Blu-ray PG subtitles - #77

Open
cinema-ONE wants to merge 2 commits into
CoreELEC:aml-5.15.196-22.0from
cinema-ONE:mvc-authored-subtitle-depth-pr
Open

Authored per-frame 3D subtitle depth for Blu-ray PG subtitles#77
cinema-ONE wants to merge 2 commits into
CoreELEC:aml-5.15.196-22.0from
cinema-ONE:mvc-authored-subtitle-depth-pr

Conversation

@cinema-ONE

@cinema-ONE cinema-ONE commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Stacked on #76 — review only the last commit; the diff resolves once that lands.

Description

A Blu-ray 3D disc authors a subtitle depth for every frame — the "1 plane + offset" mechanism. Kodi ignores it and applies one fixed value from subtitles.stereoscopicdepth instead, so subtitles sit at a depth the disc did not intend and never follow the shot.

I measured the offset tables across 151 3D titles: every one carries them, and 139 author depth that actually moves. So the fixed setting is wrong for ~92% of 3D discs, not for a handful.

Root cause

The pieces were already here — 4717e0b598 ("MVC PGS subtitles") added most of them — but nothing joined them up. Five links were missing:

  • the codec never read packet.subtitlePlane
  • VideoPicture::m_3dSubtitleDepth was never assigned, only zeroed
  • COverlay::m_3dSubtitleDepth was never copied from CDVDOverlay
  • COverlay::m_pgsSubtitle was never set, so depth += subtitleDepth was unreachable
  • the depth was set on the overlay group, while CVideoPlayerSubtitle wraps subtitles in a group and it is the children that reach the renderer

Fix

AMLParseMvcOfmd() reads the OFMD table out of the MVC access unit's SEI. The codec holds it per GOP and indexes it by the stream's offset sequence — from the STN-SS ss_offset_sequence_id on a disc, or an FFmpeg 3d-plane tag on a remux. The value is refreshed on every decoded picture, so it tracks shot by shot.

subtitles.stereoscopicdepth keeps its meaning for discs that author nothing. Where a disc does author depth, a new signed subtitles.stereoscopicdepthadjust (-10..+10, default 0) shifts it without discarding the movement; adding the fixed setting as well would double-count. Whether depth was authored is tracked explicitly, because an authored zero is a legitimate depth.

Testing

Homatics Box R 4K Plus, frame-packed 3D over HDMI to a JVC projector.

  • parsed from both an MKV remux and the disc ISO of the same title, 32 sequences x 24 frames
  • values tracked per frame; the GOP frame index verified against the authored table with per-picture logging
  • confirmed by eye on the projector, all four cases: authored depth alone varies shot to shot; +8 moves subtitles nearer; -8 moves them further back; and subtitles.stereoscopicdepth = 10 with the adjustment at 0 looks identical to 0, i.e. the fixed setting is correctly ignored where a disc authors its own depth
  • no measurable cost — 120 s of 3D playback, 37.9 CPU-seconds patched vs 37.5 unpatched
  • 2D playback unaffected; GetStereoscopicDepth() still returns 0 outside a stereo mode

@Portisch

Portisch commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Please rebase the two still open PRs #76 and #77.
Is this PR also upstreamed and accepted like xbmc/xbmc#29060?

Because it's a huge code change and hard to maintain on every rebase.

Carry of the pending upstream PR xbmc/xbmc#29060 so the feature is usable on
frame-packed 3D hardware before Kodi v23 opens. Adds subtitles.bitmapzoom and
subtitles.bitmapposition, letting PGS and VobSub be resized and moved onto the
existing position and vertical margin settings.

String ids 39213-39218; 39211/39212 are taken by CoreELEC's own subtitle
language setting.
A Blu-ray 3D disc authors a subtitle depth for every frame - the "1 plane +
offset" mechanism - and 92% of 3D titles author depth that actually moves,
measured across 151 discs. Kodi ignored all of it and applied one fixed value
from subtitles.stereoscopicdepth instead, so subtitles sat at a depth the disc
did not intend and never followed the shot.

The player already carried the pieces: DVDOverlay has m_3dSubtitleDepth,
GetStereoscopicDepth() adds it, and DemuxPacket::subtitlePlane is filled from
the Blu-ray STN-SS ss_offset_sequence_id, or from an FFmpeg 3d-plane tag for
remuxes. Nothing joined them up. Five links were missing:

  - the codec never read packet.subtitlePlane
  - VideoPicture::m_3dSubtitleDepth was never assigned
  - COverlay::m_3dSubtitleDepth was never copied from CDVDOverlay
  - COverlay::m_pgsSubtitle was never set
  - the depth was set on the overlay group, while its children are what render

AMLParseMvcOfmd() reads the OFMD offset table out of the MVC access unit's SEI,
the codec holds it per GOP and indexes it by the stream's offset sequence, and
the value is refreshed on every decoded picture so it tracks shot by shot.

subtitles.stereoscopicdepth keeps its meaning for discs that author nothing.
Where a disc does author depth, a new signed subtitles.stereoscopicdepthadjust
(-10..+10) shifts it without discarding the movement; adding the fixed setting
as well would double-count. Whether depth was authored is tracked explicitly,
since an authored zero is a legitimate depth.

Verified on a Homatics Box R 4K Plus, frame-packed 3D over HDMI: parsed from
both an MKV remux and the disc ISO, values tracking per frame, and confirmed by
eye - subtitles sit in front of the picture and their separation varies shot to
shot.
@cinema-ONE
cinema-ONE force-pushed the mvc-authored-subtitle-depth-pr branch from 4fb4bd1 to e3059aa Compare August 28, 2026 18:04
@cinema-ONE

Copy link
Copy Markdown
Contributor Author

Rebased — #76 and #77 are both MERGEABLE again. Thanks for taking #75 so quickly.

Honest answer on upstreaming: no, and I don't expect it can be. #76 is upstream as xbmc/xbmc#29060 (reviewed, milestoned Q* 23.0 Alpha 1), so that one drops out of your tree once it lands there.

#77 is different. I checked upstream master (429fdbdf6f) before answering: SETTING_VIDEOSCREEN_FRAMEPACKING is declared in Settings.h and referenced nowhere else — not in settings.xml, not in any code — and the only HARDWAREBASED implementation is under rendering/dx/, i.e. DirectX quad-buffer stereo on Windows, not HDMI frame packing. OFMD, m_3dSubtitleDepth and ss_offset_sequence_id have zero occurrences. So there is no upstream path that can run this, and the OFMD parse hooks into CDVDVideoCodecAmlogic in any case. I raised the idea on the Kodi forum before starting and got no reply.

On maintenance cost, the PR diff overstates it because it is stacked on #76. The depth commit alone is +220/−12 over 15 files, and 129 of those lines are in AMLFrameMetadata.h and DVDVideoCodecAmlogic.cpp — files upstream does not touch, so they should not conflict on a Kodi rebase. The rest is ~47 lines across the generic player and renderer files, six of which are one or two lines each: the offset has to travel from the codec through the picture, the overlay and its group children to the renderer, so those hops are unavoidable rather than incidental.

I am not going to claim I can shrink it much — I looked, and the small edits are the mechanism. If it is more than you want to carry, that is a fair call; it works fine as a local build here. If you do take it, I will rebase it whenever it conflicts, just say so on the PR.


Written by my AI co-author (Claude Code); posted from my account.

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.

2 participants