HEVC HDR10 encoding looks simple on paper — Main 10 profile, BT.2020 color, PQ transfer, 10-bit pixel format, mastering metadata. In practice, getting all the parameters right so the output triggers HDR mode on consumer TVs is non-trivial. Get one piece wrong (incorrect SEI metadata, wrong transfer signaling, mismatched master-display values) and HDR-capable displays show the content as miscolored SDR. This page is the engineering reference for HEVC HDR10 encoding configuration that actually produces conformant output.
What HDR10 encoding requires
HDR10 conformant output has three categories of signaling, all of which must be correct:
- Color metadata in VUI (Video Usability Information) — color primaries, transfer characteristics, matrix coefficients.
- Static HDR metadata in SEI (Supplemental Enhancement Information) messages — mastering display description and content light level.
- Codec profile — Main 10 (10-bit) is required; 8-bit HDR exists in spec but produces banding and isn't standard.
Plus correctly signaled in the container (MP4 colr/mdcv/clli boxes; MPEG-TS PSI signaling).
VUI color metadata
The VUI fields that signal HDR10:
| Field | Value | Meaning |
|---|---|---|
| color_primaries | 9 | BT.2020 |
| transfer_characteristics | 16 | SMPTE ST 2084 (PQ) |
| matrix_coefficients | 9 | BT.2020 non-constant luminance |
| chroma_sample_loc_type_top_field | 2 | Co-sited (HEVC standard) |
| video_full_range_flag | 0 | Limited range (TV range) |
| color_description_present_flag | 1 | (signals all the above are valid) |
In x265 parameters:
colorprim=bt2020:transfer=smpte2084:colormatrix=bt2020nc:range=limited
If any of these are wrong, the receiving display can't engage HDR mode correctly. Common mistakes:
- Setting transfer=bt709 (SDR transfer) on actually-HDR content.
- Setting matrix=bt709 on BT.2020 content.
- Setting full range flag when source is limited range.
Mastering display SEI message
The master-display parameter encodes the SMPTE ST 2086 SEI message describing the display the content was mastered on:
master-display=G(GREEN)B(BLUE)R(RED)WP(WHITE)L(MAX_LUM,MIN_LUM)
Values are in chromaticity coordinates × 50,000 (the integer encoding the spec uses). For BT.2020 with D65 white point:
- G(13250,34500) — green chromaticity (0.265, 0.690) × 50,000
- B(7500,3000) — blue chromaticity (0.150, 0.060) × 50,000
- R(34000,16000) — red chromaticity (0.680, 0.320) × 50,000
- WP(15635,16450) — D65 white point (0.3127, 0.3290) × 50,000
- L(MAX,MIN) — peak and minimum luminance × 10,000
For a 1000-nit mastering display: L(10000000,1) means peak 1000 nits, min 0.0001 nits.
For a 4000-nit mastering display: L(40000000,50) — peak 4000 nits, min 0.005 nits.
The values must match the actual mastering setup. If you mastered on a 1000-nit display, declare 1000 nits; if 4000-nit, declare 4000 nits. Mis-declared mastering display causes incorrect tone-mapping on consumer TVs.
Content Light Level SEI message
The max-cll parameter encodes content light level metadata:
max-cll=MaxCLL,MaxFALL
- MaxCLL (Maximum Content Light Level) — the maximum pixel luminance across the content. In nits.
- MaxFALL (Maximum Frame Average Light Level) — the maximum frame-average luminance across the content. In nits.
For a typical movie with peak luminance of 1000 nits and average peak frame luminance of 400 nits: max-cll=1000,400.
Values should match actual content. Some encoders compute these automatically; for manual control, measure the actual content and supply correct values.
Full x265 HDR10 CLI
The complete ffmpeg + x265 invocation for HDR10:
ffmpeg -i hdr_master.mov \
-c:v libx265 -profile:v main10 -pix_fmt yuv420p10le \
-preset slow -crf 22 \
-x265-params "colorprim=bt2020:transfer=smpte2084:colormatrix=bt2020nc:\
range=limited:hrd=1:repeat-headers=1:\
master-display=G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1):\
max-cll=1000,400" \
-c:a copy hdr10_output.hevc
Each piece:
-profile:v main10— Main 10 profile (10-bit).-pix_fmt yuv420p10le— 10-bit YUV 4:2:0 (the streaming standard).-preset slow— production preset for premium HDR (quality matters).-crf 22— quality target. HDR content typically uses CRF 22-24 (slightly lower than SDR CRF 23) to handle the extended dynamic range.colorprim=bt2020— BT.2020 color primaries.transfer=smpte2084— PQ transfer function (HDR10 standard).colormatrix=bt2020nc— BT.2020 non-constant luminance matrix.range=limited— limited (TV) range. Almost always correct for streaming.hrd=1— generates Hypothetical Reference Decoder buffer info.repeat-headers=1— repeats VPS/SPS/PPS at IDR frames for streaming compatibility.master-display=...— mastering display SEI.max-cll=...— content light level SEI.
Verify the output has correct signaling:
ffprobe -v error -select_streams v:0 -show_entries stream=color_primaries,color_transfer,color_space,bits_per_raw_sample hdr10_output.hevc
Expected output:
[STREAM]
color_space=bt2020nc
color_primaries=bt2020
color_transfer=smpte2084
bits_per_raw_sample=10
[/STREAM]
If any field is missing or wrong, the encoding configuration has issues.
Container signaling
HEVC HDR10 output then needs container-level signaling. For MP4/CMAF:
ffmpeg -i hdr10.hevc -i audio.aac -c copy -movflags +faststart \
-metadata:s:v:0 mediadata=master_display=... \
hdr10.mp4
ffmpeg should preserve the codec-level signaling automatically when copying. The MP4-level boxes (colr, mdcv, clli) get populated from the HEVC VUI/SEI metadata.
Verify MP4 has correct boxes:
mediainfo --Inform="Video;%colour_primaries%,%transfer_characteristics%,%matrix_coefficients%,%MasteringDisplay_Luminance%" hdr10.mp4
For HLS/DASH packaging, the packager preserves these boxes through segment generation. Verify segment-level signaling is correct via ffprobe.
Common HDR10 encoding mistakes
Mistakes that cause HDR-capable TVs to display content as miscolored SDR or refuse HDR mode:
Mistake 1: Wrong transfer characteristic — Setting transfer=bt709 produces SDR signaling. The TV sees an SDR signal and applies SDR tone mapping; the content looks washed out.
Mistake 2: Mis-declared master-display — Declaring a 4000-nit master when content was mastered on 1000-nit causes consumer TVs to under-tone-map; output looks too dark on consumer displays.
Mistake 3: Missing max-cll — Some TVs require both master-display AND max-cll SEI to engage HDR mode. Without max-cll, behavior is platform-specific; some TVs work, others fail.
Mistake 4: Range flag mismatch — Setting range=full on limited-range source produces compressed output that displays with crushed shadows.
Mistake 5: Inconsistent VUI/SEI between segments — for HLS/DASH, all segments should have the same VUI/SEI. Mismatches between segments cause player confusion.
Mistake 6: Wrong bit depth — encoding 8-bit yuv420p instead of 10-bit yuv420p10le produces visible banding on HDR content.
Mistake 7: Encoder version regression — x265 has evolved; older versions had subtle HDR bugs. Pin to recent stable x265 versions for HDR work.
Validation procedure
A practical validation procedure for HDR10 encoding:
- Verify codec signaling — ffprobe color fields match expected (bt2020/smpte2084/bt2020nc/10-bit).
- Verify mastering display SEI — extract via
mediainfoormp4parseand check values match actual mastering setup. - Verify MaxCLL/MaxFALL — sane values that aren't zero.
- Test on actual HDR display — play on a Samsung/LG/Sony HDR TV; confirm HDR mode engages and output looks correct.
- Test SDR fallback — play on an SDR-only display; confirm output is acceptable (or that pipeline produces a separate SDR variant).
- Cross-platform testing — test on iOS, Android, Apple TV, Roku, PS5/Xbox where relevant.
For automated testing, the Apple Media Stream Validator (mediastreamvalidator command) checks HDR signaling for HLS streams. For DASH, the DASH-IF Conformance Tool does similar checks.
HDR10 vs Dolby Vision encoding
HDR10 encoding produces a baseline; Dolby Vision encoding requires additional steps:
- Dolby Vision Profile 8.1 produces an HDR10-compatible base stream PLUS Dolby Vision metadata.
- The encoding requires a Dolby-licensed encoder with metadata XML input.
- The output is HEVC Main 10 (same as HDR10) with additional SEI messages carrying Dolby Vision metadata.
For pipelines producing both HDR10 and Dolby Vision from the same master, the HDR10 portion is essentially the same as standalone HDR10 encoding; Dolby Vision adds metadata embedding.
Operational considerations
Things that matter for HDR10 encoding in production:
- Master fidelity — HDR10 encoding can't add information that wasn't in the source. Verify master is genuinely HDR-graded with correct metadata before encoding.
- Per-asset master-display values — different content may be mastered on different displays. Don't hardcode master-display globally; configure per asset.
- Color management throughout pipeline — every pipeline stage that touches the content (filters, scaling, transcoding) must preserve color metadata. Loss anywhere produces HDR-mode failures downstream.
- Encoder version pinning — x265 HDR handling has improved across versions; pin to known-good version after validation.
- Cross-codec consistency — when shipping HEVC HDR10 + AV1 HDR10 + (eventually) VVC HDR10, all variants should produce equivalent visual output. Verify cross-codec.
- Bitrate budget for HDR — HDR10 typically needs 10-20% more bitrate than equivalent-quality SDR. Plan ladder bitrates accordingly.
What MpegFlow does with HEVC HDR10 encoding
MpegFlow's FfmpegExecutor worker image runs x265 Main 10 with HDR10 configuration through workflow YAML. The DAG runtime expresses per-rung HDR10 encoding as parallel rendition stages on job_stages with explicit dependency tracking; per-stage retry handles transient failures; sibling cancellation propagates fatal failures across rendition stages.
For customers ingesting HDR-graded source content, an FfprobeExecutor stage characterizes HDR signaling upstream of encode; cross-stage data flow wires the probe output (master-display, max-cll, color primaries, transfer characteristics) into the downstream FfmpegExecutor rendition stages so the encoder receives accurate per-asset values rather than fixed defaults. Master-display values can be derived from source metadata or overridden per asset in workflow YAML.
Timestamp-preservation discipline at every stage boundary keeps HDR metadata aligned end-to-end. The CMAF muxer at the packaging stage preserves the colr/mdcv/clli boxes the encoder populated.
For multi-format HDR delivery (HDR10 + Dolby Vision + HDR10+ + SDR), HDR10 is the baseline that's straightforwardly handled by the FFmpeg/x265 path. Dolby Vision Profile 5/8 and HDR10+ dynamic-metadata workflows requiring metadata signaling beyond what x265 emits natively are operator-side work today — Dolby Vision metadata muxing, HDR10+ dynamic-metadata authoring — rather than pipeline-native encoder configuration.
The strict-broker security model handles HDR10 work like any pipeline payload — workers carry no ambient credentials; content access flows through short-lived presigned URLs scoped per stage; access is disposed on completion.
For customers shipping HDR for the first time, the most common issue is master metadata accuracy. Bad master-display or max-cll values produce HDR output that displays incorrectly. We help customers verify their mastering pipeline's output signaling during onboarding.
The general guidance: HEVC HDR10 encoding is precise but mechanical. Get the parameters right (correct VUI, correct SEI, correct bit depth, correct color matrix) and the output works universally on HDR-capable displays. The complexity is in the metadata accuracy, not the encoder configuration.