Repository navigation
Conversation
…frames Adds Dolby Vision and object-audio detection to the demuxer, colour metadata on the pixel buffers the CPU path produces, a host-stated audio output width, and once-per-stream diagnostics. - TrackInfo.Video.dolbyVision is read from AV_PKT_DATA_DOVI_CONF; TrackInfo.Audio gains profile / isObjectAudio / channelLayoutName. The Atmos profile comparison is gated on codec id: the constant is 30 for both E-AC-3 and TrueHD, so an ungated check false-positives on any codec whose profile happens to be 30. - PixelBufferFactory now attaches colour primaries, transfer function and YCbCr matrix (plus mastering display colour volume and content light level when the frame carries them). AVCOL_*_UNSPECIFIED maps to no attachment at all rather than a guessed default — SD/IPTV streams emit UNSPECIFIED constantly and a wrong tag would regress ordinary channels. This matters most for interlaced HDR broadcast: the deinterlacer is on by default and downloads hardware frames to the CPU, so those frames lost their colour tags even on a hardware decode. - The VideoToolbox zero-copy path is handed on untouched. Measured on an Apple TV 4K against a DV P8.1 title, it already carries all three keys correctly and the picture is clean, so re-stamping could only make a working path worse. - PlayerConfiguration.maxOutputChannels lets the host state the *negotiated* output width at both AudioDecoder construction sites; nil keeps the previous behaviour of reading the audio session directly. - Once-per-stream readouts on engine.lume/diagnostics: stream-open, video-format (naming the delivery path that produced the buffer) and audio-width. Never emitted per frame or per tick. Dolby Vision profile 5 and compressed-audio passthrough remain out of scope and are documented as limitations in PLAN.md §7. Refs bilipp/Lume#207
…ion-atmos # Conflicts: # Tests/LumeEngineCoreTests/Fixtures/generate-fixtures.sh
…the GPU Profiles with no backward-compatible base layer (5, 20, 10.0) carry IPT, not YCbCr. Displayed as BT.2020 they render pink/green on every path — Apple's own decoder included — so the RPU has to be applied by us. - DolbyVisionReshaper: Metal compute kernel applying the per-frame RPU (polynomial/MMR curves, nonlinear matrix, PQ, crosstalk-corrected LMS->RGB, libplacebo's algorithm) and writing a pooled x420 buffer tagged BT.2020/PQ/BT.2020. Reads VideoToolbox surfaces in place. - VideoDecoder routes AVCOL_SPC_IPT_C2 frames through it; frames without an RPU reuse the last one; no Metal or a GPU error delivers the frame untouched and logs dv-reshape once. - Tests: kernel vs CPU reference, HDR10 tags, and hardware/software parity on the local DVprofile20.mp4 sample (skipped when absent). - PLAN.md §7: P5/P20/P10.0 moves from limitation to implemented.
This was referenced Sep 25, 2026
feat(player): negotiate LumeEngine's audio width up front and export its diagnostics
bilipp/Lume#220
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Correct picture and sound for Dolby Vision / HDR / object-audio content. Engine side of bilipp/Lume#207; pairs with bilipp/Lume#220.
What a user saw, and what fixes it:
bl_signal_compatibility_id == 0); every path displayed it as BT.2020PixelBufferFactorybufferPlayerConfiguration.maxOutputChannelsDolby Vision IPT reshaping (P5 / P20 / P10.0)
Apple does not do this for us.
AVAssetImageGeneratorrendersDVprofile20.mp4exactly as tinted on macOS, so forwardingdvh1signalling to VideoToolbox would not fix it either.DolbyVisionReshaperis a Metal compute kernel. It readsAV_FRAME_DATA_DOVI_METADATAand applies libplacebo's algorithm in order:ycc_to_rgbmatrix and offsetrgb_to_lmscrosstalk × BT.2020 HPE LMS→RGBThe output is a pooled
x420buffer tagged BT.2020 / PQ / BT.2020, so it's ordinary HDR10 from there on.Scope: runs only for frames whose colour space is
AVCOL_SPC_IPT_C2. P8.1 (HDR10 base layer) and all other content never touch Metal.Both decode paths: reads VideoToolbox surfaces in place through a Metal texture cache, and handles software /
PixelBufferFactorybuffers the same way. The kernel is compiled from source on the first IPT frame, because SwiftPM compiles.metalresources only under Xcode.Degrades, never dies:
engine.lume/diagnosticsasdv-reshape applied|skipped|failedNot covered:
Colour metadata on CPU-produced buffers
PixelBufferFactoryattaches primaries, transfer function and YCbCr matrix, plus MDCV and CLL when the frame carries them.AVCOL_*_UNSPECIFIEDmaps to no attachment at all, never a guessed default: SD/IPTV emits UNSPECIFIED constantly, and a wrong tag would regress ordinary channels. Every key is set or removed, never left alone, because pool buffers are recycled.Detection, audio width, diagnostics
TrackInfo.Video.dolbyVisionis read fromAV_PKT_DATA_DOVI_CONF.TrackInfo.Audiogainsprofile,isObjectAudioandchannelLayoutName. The Atmos check is gated on codec id: the constant is30for both E-AC-3 and TrueHD, so an ungated check false-positives on any codec whose profile happens to be 30. Detection only; Atmos is still decoded to its channel bed.PlayerConfiguration.maxOutputChannelslets the host state the negotiated width.nilkeeps the old behaviour (read the session directly).stream-open,video-format(names the delivery path),audio-width,dv-reshape. Never per frame.Compressed-audio passthrough stays out of scope, documented in PLAN.md §7. That row for DV P5 now reads implemented.
Type of change
feat— new capabilityInvariants
Channel. Reshaping runs synchronously on the video decode thread, which is the data plane.PlayerConfiguration; reshaper state is perVideoDecoder.TimestampUnwrapper.AVSampleBufferRenderSynchronizer.as!,fatalErrororassertionFailurein new engine code; failures are typedEngineErrors, and the caller degrades.av_logstrings. DV is read from packet/frame side data.Verification
swift buildis warning-free for the new code.swift testis green:DolbyVisionReshapeTests:TestStreams/DolbyVision/DVprofile20.mp4is absent.ColorTaggingTests: the AVCOL→CoreVideo table, exhaustively.TrackDolbyDetectionTests: includes the profile-30 negative case.StreamOpenDiagnosticsTests.DVprofile20.mp4: a plain decode and Apple's decoder both show a purple hippo in green water. The engine output shows a grey hippo in blue-teal sea, matching an independent numpy implementation of the same RPU math.Platforms verified
Reshaping has been verified on macOS only. It still needs a run on Apple TV / iPhone hardware: look for
dv-reshape applied input='xf20' output='x420'. visionOS is not verified; no simulator runtime is installed here.Real-world content
DVprofile20.mp4— HEVC 3840×2160 @ 24 fps, 10-bit, full range, DV profile 20 level 6 (bl_signal_compatibility_id=0, RPU present, polynomial curves).No URLs or credentials.