HDR Encoding.

Table of contents
  1. HDR Encoding.
    1. PQ10
      1. Frame prep
      2. PQ 444 FFMPEG encoding
        1. Overall encode params
        2. Encode media definition
        3. X265 parameters
    2. HLG
      1. Frame prep
      2. HLG 444 FFMPEG encoding
        1. Overall encode params
        2. Encode media definition
        3. X265 parameters
      3. HLG 420 FFMPEG encoding
      4. HLG 422 FFMPEG Encoding

This is currently under development, use at your own risk.

There are a lot of competing standards for HDR, we are going to focus only on two due to their relative simplicity (not requiring dynamic metadata), and lack of licensing fees.

  1. HLG encoding, developed by NHK and the BBC.
  2. PQ10 which uses the PQ EOTF.

PQ10

Is the HDR format which is the HDR10 without the metadata. It uses the PQ EOTF aka SMPTE ST 2084 otherwise is somewhat similar to create as HLG, but there may be different reasons for choosing each.

Frame prep

We take advantage of ACES to do the initial conversion to an intermediate format, which we are using png as the container.

Converting to PQ-1000 Nits.

# Assuming we are using OCIO 2.1 or higher
export OCIO=ocio://studio-config-v1.0.0_aces-v1.3_ocio-v2.1
oiiotool -v --framepadding 5 --frames 6700-6899 sparks2/SPARKS_ACES_#.exr --iscolorspace "ACEScg" --resize 1920x1014 \
       --ociodisplay "Rec.2100-PQ - Display" "ACES 1.1 - HDR Video (1000 nits & Rec.2020 lim)" \
       -d uint16 -o sparks2_pq2000/sparks2_pq2000.#.png
–iscolorspace “ACEScg” Set the input colorspace to ACEScg (or whatever your source imagery is using)
–ociodisplay “Rec.2100-PQ - Display” “ACES 1.1 - HDR Video (1000 nits & Rec.2020 lim)” This is the core colorspace conversion, This is using a 2100-PQ display, at 100 nits and rec2020
-d uint16 Output as 16-bit file format

The other option built in for PQ is a config with 2000 nits - ``–ociodisplay “Rec.2100-PQ - Display” “ACES 1.1 - HDR Video (2000 nits & Rec.2020 lim)” | | HLG | |

PQ 444 FFMPEG encoding

ffmpeg  \
    -r 30 -start_number 6700 -i sparks2_pq2000/sparks2_pq2000.%05d.png   \
    -c:v libx265   \
    -vf "scale=in_range=full:in_color_matrix=bt2020:out_range=tv:out_color_matrix=bt2020" \
	-tag:v hvc1  \
    -color_range tv   -color_trc smpte2084   -color_primaries bt2020   -colorspace bt2020nc  \
    -pix_fmt yuv444p10le 
    -x265-params 'colorprim=bt2020:transfer=smpte2084:colormatrix=bt2020nc:range=limited:master-display=G\(13250,34500\)B\(7500,3000\)R\(34000,16000\)WP\(15635,16450\)L\(10000000,1\):max-cll=2000,400'   \
    sparks2_pq2000_444.mov

Overall encode params

-c:v libx265 Use the h265 encoder
-tag:v hvc1 Tag the file for playback on mac
-vf “scale=in_range=full:in_color_matrix=bt2020:out_range=tv:out_color_matrix=bt2020” Make sure we treat the input and output color primaries to be bt2020. Without this, ffmpeg can assume the source is different, and apply a primary that shouldnt be there.

Encode media definition

-color_range tv Set the source range to be tv range.
-color_trc smpte2084 smpte2084 is the PQ reference EOTF
-color_primaries bt2020 Use the bt2020 color primaries
-colorspace bt2020nc Tagging the YcBCr as being encoded using the BT-2020 non-constant luminance.
-pix_fmt yuv444p10le YUV 444 10-bit output

X265 parameters

We explicitly define the X265 parameters (see x265 )

colorprim=bt2020 Set the colorprimaries to bt2020
transfer=smpte2084 Set the ETOF to PQ (aka. smpte2084 )
colormatrix=bt2020nc UTagging the YcBCr as being encoded using the BT-2020 non-constant luminance.
range=limited Set the source range to be tv range.
master-display=G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1) SMPTE ST 2086 mastering display color volume SEI info, specified as a string which is parsed when the stream header Essentially setting the X,Y display primaries for rec2020 along with the Whitepoint, and the Max,min luminance values in units of 0.00001 NITs. See the above docs for more info.
max-cll=2000,400 Set the Maximum content light level (in this case 2000 nits = max content light level and 400 = the MaxFall - the maxiumum frame-average light level)

HLG

HLG encoding, developed by NHK and the BBC. Its designed to be backwards compatible with the EOTF to SDR but with an extension for higher intensities. It has a more limited maximum peak brightness of 5000 nits rather than 10000 nits for PQ.

It is also designed to adapt to the surrounding room light levels, unlike PQ which is fixed. The downside is that this adaption could affect the media in unexpected ways.

Frame prep

We take advantage of ACES to do the initial conversion to an intermediate format, which we are using png as the container.

# Assuming we are using OCIO 2.1 or higher
export OCIO=ocio://studio-config-v1.0.0_aces-v1.3_ocio-v2.1
oiiotool -v --framepadding 5 --frames 6700-6899 sparks2/SPARKS_ACES_#.exr --resize 1920x1014 \
      ---ociodisplay "Rec.2100-HLG - Display" "ACES 1.1 - HDR Video (1000 nits & Rec.2020 lim)" -d uint16 -o sparks2_hlg/sparks2_hlg.#.png
–ociodisplay “Rec.2100-HLG - Display” “ACES 1.1 - HDR Video (1000 nits & Rec.2020 lim)” This is the core colorspace conversion, out_rec2020hlg1000nits is an output colorspace conversion for rec2020 HLG at 1000 nit display
-d uint16 Output as 16-bit file format

HLG 444 FFMPEG encoding

ffmpeg -r 30 -start_number 6700 -i sparks2_hlg/sparks2_hlg.%05d.png   \
    -c:v libx265  -tag:v hvc1  \
    -vf "scale=in_range=full:in_color_matrix=bt2020:out_range=tv:out_color_matrix=bt2020" \
    -color_range tv   -color_trc arib-std-b67   -color_primaries bt2020   -colorspace bt2020nc  \
    -pix_fmt yuv444p10le   \
    -x265-params 'colorprim=bt2020:transfer=arib-std-b67:colormatrix=bt2020nc:range=limited:master-display=G\(13250,34500\)B\(7500,3000\)R\(34000,16000\)WP\(15635,16450\)L\(10000000,1\):max-cll=1000,400'   \
    sparks2_hlg_444.mov

Overall encode params

-c:v libx265 Use the h265 encoder
-tag:v hvc1 Tag the file for playback on mac

Encode media definition

-color_range tv Set the source range to be tv range.
-color_trc arib-std-b67 ARIB STD-B67 is the HLG reference EOTF
-color_primaries bt2020 Use the bt2020 color primaries
-colorspace bt2020nc Tagging the YcBCr as being encoded using the BT-2020 non-constant luminance.
-pix_fmt yuv444p10le YUV 444 10-bit output

X265 parameters

We explicitly define the X265 parameters (see x265 )

colorprim=bt2020 Set the colorprimaries to bt2020
transfer=arib-std-b67 Set the ETOF to HLG (aka. arib-std-bt67 )
colormatrix=bt2020nc UTagging the YcBCr as being encoded using the BT-2020 non-constant luminance.
range=limited Set the source range to be tv range.
master-display=G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1) SMPTE ST 2086 mastering display color volume SEI info, specified as a string which is parsed when the stream header Essentially setting the X,Y display primaries for rec2020 along with the White-point, and the Max,min luminance values in units of 0.00001 NITs. See the above docs for more info.
max-cll=1000,400 Set the Maximum content light level (in this case 2000 nits = max content light level and 400 = the MaxFall - the maximum frame-average light level)

TODO - We do need to understand if the max-cll and master-display parameters are even used for HLG display.

HLG 420 FFMPEG encoding

ffmpeg  -r 30 -start_number 6700 -i sparks2_hlg/sparks2_hlg.%05d.png   \
	-c:v libx265   -tag:v hvc1  \
  -vf "scale=in_range=full:in_color_matrix=bt2020:out_range=tv:out_color_matrix=bt2020" \
	-color_range tv   -color_trc arib-std-b67   -color_primaries bt2020   -colorspace bt2020nc   \
	-pix_fmt yuv420p10le   \
	-x265-params 'colorprim=bt2020:transfer=arib-std-b67:colormatrix=bt2020nc:range=limited:master-display=G\(13250,34500\)B\(7500,3000\)R\(34000,16000\)WP\(15635,16450\)L\(10000000,1\):max-cll=1000,400' \
	   sparks2_hlg_420.mov

HLG 422 FFMPEG Encoding

ffmpeg  -r 30 -start_number 6700 -i sparks2_hlg/sparks2_hlg.%05d.png   \
	-c:v libx265   -color_range tv   -color_trc arib-std-b67   -color_primaries bt2020   -colorspace bt2020nc   \
	-pix_fmt yuv420p10le  -tag:v hvc1  \
    -vf "scale=in_range=full:in_color_matrix=bt2020:out_range=tv:out_color_matrix=bt2020" \
	-x265-params 'colorprim=bt2020:transfer=arib-std-b67:colormatrix=bt2020nc:range=limited:master-display=G\(13250,34500\)B\(7500,3000\)R\(34000,16000\)WP\(15635,16450\)L\(10000000,1\):max-cll=1000,400' \
	   sparks2_hlg_420_v2.mov

Further Reading:


Copyright © 2022 ORI Contributors. Distributed under a CC BY 4.0 license.