Skip to content

Skip HDR10+ metadata processing when Dolby Vision Profile 8 is detected#3085

Open
cgarst wants to merge 3 commits intoandroidx:releasefrom
cgarst:dvfix
Open

Skip HDR10+ metadata processing when Dolby Vision Profile 8 is detected#3085
cgarst wants to merge 3 commits intoandroidx:releasefrom
cgarst:dvfix

Conversation

@cgarst
Copy link

@cgarst cgarst commented Feb 22, 2026

Strip in-band HDR10+ SEI from HEVC bitstream during Dolby Vision Profile 8 playback

Summary

Fixes freezes, black screens, and purple screens when playing DV Profile 8 MKV files that contain both Dolby Vision RPU and HDR10+ dynamic metadata on devices with buggy chipsets.

Related Issues

Fixes #1895

Problem

MKV files containing Dolby Vision Profile 8.1 (dvhe.08) combined with HDR10+ metadata cause playback failures on many Android TV devices:

  • Fire TV Stick 4K Max (Gen 1 and Gen 2)
  • Google TV Streamer (MediaTek MT8696)
  • TCL C825 and MQLED80
  • Other Android TV devices with similar chipsets

The HEVC base layer bitstream contains HDR10+ dynamic metadata as in-band SEI NAL units (ITU-T T.35 / ST 2094-40). When a native Dolby Vision codec processes this stream, it also handles DV RPU for dynamic HDR. The conflicting dynamic metadata crashes the chipset.

Solution

Strip HDR10+ SEI NAL units from buffer.data in onQueueInputBuffer() before the buffer is submitted to the native DV codec. This is the same approach used by Kodi.

The stripping only activates when both conditions are met:

  1. The format is Dolby Vision Profile 8
  2. A native DV codec was selected (codecMimeType == VIDEO_DOLBY_VISION)

When the TV doesn't support Dolby Vision, doesDisplaySupportDolbyVision() returns false, getDecoderInfos() falls back to HEVC, codecMimeType is VIDEO_H265, and stripping is not applied — HDR10+ metadata is preserved for the HEVC decoder.

What if the device supports DV and HDR10+, but the TV only supports HDR10+?

In this case doesDisplaySupportDolbyVision() returns false → HEVC fallback is selected → stripHdr10PlusSeiNalUnits stays false → HDR10+ SEI is preserved → no regression. This scenario is covered by the dvProfile8_hevcFallback_preservesHdr10PlusSeiInBuffer integration test.

Changes

MediaCodecVideoRenderer.java

  • Added stripHdr10PlusSeiNalUnits boolean field, set in onCodecInitialized()
  • Added stripping call at the top of onQueueInputBuffer()
  • Added stripHdr10PlusSeiFromBuffer(): scans AnnexB buffer for start codes, identifies HEVC PREFIX_SEI/SUFFIX_SEI NAL units (types 39/40), parses SEI payloads to detect HDR10+ (ITU-T T.35 with country code 0xB5, provider 0x003C, oriented 0x0001, app_id 4, version 0 or 1), removes matching NAL units by compacting the buffer in-place

MediaCodecInfo.java

  • Reverted isHdr10PlusOutOfBandMetadataSupported() to VP9-only — the HEVC extension was unreachable for this bug

MediaCodecVideoRendererTest.java

  • Removed prior tests that targeted the unreachable out-of-band path
  • Added unit tests for stripHdr10PlusSeiFromBuffer() and integration tests for the fix

Test plan

Bug fix validation

These tests confirm that HDR10+ SEI NAL units are correctly stripped from the HEVC bitstream before it reaches a native Dolby Vision codec. They fail on unpatched code and pass with the fix.

Test Purpose Before fix After fix
stripHdr10PlusSei_removesHdr10PlusSeiNalUnit Unit test: given AnnexB buffer [VCL][HDR10+ SEI][VCL], verifies the HDR10+ SEI NAL is removed, VCL NALs are preserved, and the buffer limit is reduced FAIL — buffer unchanged PASS
dvProfile8_nativeDvCodec_stripsHdr10PlusSeiFromBuffer Integration test: full render pipeline with a native DV codec selected for DV Profile 8 content. Captures actual buffer data submitted to the codec and asserts no HDR10+ SEI NAL units remain FAIL — HDR10+ SEI still present PASS

Regression protection

These tests confirm that stripping does not activate when it shouldn't — non-HDR10+ SEI is never touched, buffers without SEI are left alone, and HEVC fallback playback preserves HDR10+ metadata for devices/TVs that need it.

Test Purpose Before fix After fix
stripHdr10PlusSei_preservesNonHdr10PlusSei Unit test: given AnnexB buffer [VCL][non-HDR10+ SEI][VCL], verifies all NAL units are preserved unchanged. Guards against accidentally stripping unrelated SEI messages (e.g. CEA-608 captions) PASS PASS
stripHdr10PlusSei_noOpWhenNoSeiPresent Unit test: given AnnexB buffer with only VCL NAL units, verifies the buffer is completely unchanged. Guards against corruption of normal video frames PASS PASS
dvProfile8_hevcFallback_preservesHdr10PlusSeiInBuffer Integration test: device has DV + HEVC codecs but TV only supports HDR10+ (no DV), so HEVC fallback is selected. Captures codec input buffers and asserts HDR10+ SEI NAL units are still present. PASS PASS

@markwiese
Copy link

OMG, @cgarst you are an absolute legend!

@nift4
Copy link
Contributor

nift4 commented Feb 25, 2026

Wouldn't this cause a regression if playback device doesn't support Dolby Vision, but does support HDR10+, and the file has both?
Currently it would play the DV file in backward compatible HDR10 mode and could use HDR10+ dynamic metadata, but with this patch it seems impossible.

@cgarst
Copy link
Author

cgarst commented Feb 26, 2026

@nift4 good call - this should be fixed now.

@nift4
Copy link
Contributor

nift4 commented Feb 27, 2026

Just to start with an disclaimer, I'm not sure about this as I don't have a test setup and my understanding is limited.

That said, I wonder if this could still cause a regression in the following case:

  1. Playback device is not affected by the linked bug
  2. Playback device supports DV and HDR10+
  3. TV supports HDR10+ only
  4. File has both DV and HDR10+

Edit: I was a bit mistaken in an initial analysis in this comment, sorry. (I edited it out now as it is not relevant, to prevent confusion.) Your prior fix seems to have already considered that scenario, and the change seems fine now.

…ta/setParameters, but that path is unreachable for MKV DV Profile 8 — the HDR10+ is in-band as SEI NAL units in buffer.data, not out-of-band supplemental data. Now strips HDR10+ SEI directly from the AnnexB buffer in onQueueInputBuffer before it reaches the native DV codec. Tests were added to validate the fix and guard from regressions.
@cgarst
Copy link
Author

cgarst commented Feb 27, 2026

@nift4 Thanks again for the feedback. The fix has been redone to handle this at a different level after digging deeper into how the HDR10+ metadata flows.

The HDR10+ in these MKV files is in-band as SEI NAL units in buffer.data, not out-of-band supplemental data, so the new approach strips HDR10+ SEI directly from the AnnexB buffer in onQueueInputBuffer(). It only kicks in when a native DV codec is actually active. It gates on codecMimeType == VIDEO_DOLBY_VISION, not just the format.

I've added the scenario you mentioned as an integration test (dvProfile8_hevcFallback_preservesHdr10PlusSeiInBuffer) to validate that HDR10+ SEI is preserved when HEVC fallback is selected.

I work on some additional testing with this change.

@nift4
Copy link
Contributor

nift4 commented Feb 27, 2026

You're right, that should just work with your new commit, because ExoPlayer already correctly falls back to HEVC codec, even if DV codec is present in STB but TV does not have DV. (I was mistaken about that not happening in my prior comment.) So everything should be good now!

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.

Firestick 4k max (files with hdr10+ and dolby vision profile 8.1)

3 participants