Skip to content

Instantly share code, notes, and snippets.

@LukeNewNew
Created May 29, 2025 06:31
Show Gist options
  • Save LukeNewNew/558a2e715664fe2a3e6be1df3129bab7 to your computer and use it in GitHub Desktop.
Save LukeNewNew/558a2e715664fe2a3e6be1df3129bab7 to your computer and use it in GitHub Desktop.

How to transcode Dolby Vision with correct color on non-Dolby device?

Below is a step‑by‑step workflow to “flatten” Dolby Vision into a single‑layer HDR10 (or SDR) encode that preserves the correct color on devices without Dolby Vision support.

At a high level, Dolby Vision streams consist of a backward‑compatible HDR10 base layer plus one or two enhancement layers (dynamic metadata) that non‑Dolby decoders ignore; our goal is to merge and tone‑map these into a single output the target device can render accurately.

1. Understand Dolby Vision’s Dual‑Layer Architecture

Dolby Vision encodes a mandatory HDR10 base layer plus one (Profile 8.1) or two (Profile 7.6) enhancement layers (RPU and optional MEL/FEL) carrying dynamic metadata.

Non‑Dolby decoders will play only the base layer, often resulting in green‑tinted or washed‑out color because they ignore the enhancement layers’ tone‑mapping metadata.

2. Extract the HEVC Elementary Stream

First, demux and convert the video into raw Annex‑B HEVC:

ffmpeg -i input.mkv -map 0:v:0 -c:v copy -vbsf hevc_mp4toannexb -f hevc input.hevc

This preserves both base and enhancement layers intact for processing.

3. Extract Dolby Vision Metadata

Use the open‑source dovi_tool to parse out RPU metadata into JSON:

dovi_tool parse-rpu input.hevc rpu.json

Likewise, for HDR10+ static metadata you can use hdr10plus_tool if desired.

4. Tone‑Map or Merge Enhancement Layers

You have two main approaches:

A. FFmpeg + libplacebo Tone‑Mapping

On Linux, FFmpeg with vf_libplacebo can apply dynamic metadata tone‑mapping in real time (Vulkan required):

ffmpeg -i input.hevc -vf format=rgb0,libplacebo=tone_mapping=1 \
  -c:v libx265 -x265-params crf=18:profile=main10 \
  output_hdr10.mkv

This fuses the dynamic metadata into the pixel data.

B. DaVinci Resolve ACES (GUI‑Based)

Import your flattened HEVC and RPU JSON into DaVinci Resolve 18’s ACES pipeline, grade/flatten on V1, then export as a single HDR10 master.

5. Re‑encode with Correct Color Metadata

Whether using FFmpeg or Resolve, explicitly set the color parameters to ensure accurate playback:

ffmpeg -i tone_mapped.hevc \
  -c:v libx265 \
  -pix_fmt yuv420p10le \
  -color_primaries bt2020 \
  -color_trc smpte2084 \
  -colorspace bt2020_ncl \
  -crf 18 \
  output_hdr10.mp4

This tags your file as HDR10 (PQ transfer) with BT.2020 primaries.

6. Mux and Verify

Finally, mux into MP4 or MKV:

ffmpeg -i output_hdr10.mp4 -i input.audio -c copy final_output.mp4

Test on your target device: you should see “4K HDR10” (or SDR) with correct color, no green tint.


Quick Troubleshooting Tips

  • HandBrake users: HandBrake passes Dolby Vision only via x265 10‑bit profiles, but metadata often drops; prefer the above FFmpeg workflow.

  • Container support: MKV may drop DV metadata; MP4 is more reliable for Dolby Vision signaling.

  • Library versions: Ensure you’re using a recent FFmpeg build compiled with libplacebo support, or use the official Docker + Vulkan packages.

By extracting the dual layers, tone‑mapping with libplacebo or ACES, and re‑encoding with explicit color tags, you can reliably deliver high quality color on any HDR10/SDR device.

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