How to Use FFmpeg tonemap_opencl for HDR to SDR
This guide explains how to leverage the tonemap_opencl
filter in FFmpeg to perform fast, hardware-accelerated HDR-to-SDR tone
mapping using OpenCL. Tone mapping converts High Dynamic Range (HDR)
content with wide color gamuts (like BT.2020) down to Standard Dynamic
Range (SDR) with Rec.709 color profiles. Using OpenCL offloads the
computationally heavy color transformation to your GPU, resulting in
significantly faster encoding times compared to software-based filters
like zscale.
Prerequisites
Before using the filter, ensure your environment meets the following requirements:
- FFmpeg Compilation: FFmpeg must be compiled with
--enable-opencl. You can check this by runningffmpeg -versionand looking for--enable-openclin the configuration output. - GPU Drivers: Proper OpenCL runtime drivers must be installed for your hardware (Intel Neo/Compute Runtime, NVIDIA CUDA/OpenCL, or AMD ROCm/AMDGPU-PRO).
- OpenCL Device: Identify your available OpenCL
devices with
clinfoor by using FFmpeg's device detection.
The OpenCL Processing Pipeline
The tonemap_opencl filter operates in GPU memory. When
reading an input stream decoded on the CPU, you must transfer frames to
the GPU, process them, and download them back unless you pass them
directly to an OpenCL-compatible hardware encoder.
The filtergraph sequence follows this general structure:
- Initialize the OpenCL hardware device
(
-init_hw_device). - Format the CPU frames into an OpenCL-compatible pixel format
(typically 10-bit
p010lefor HDR10). - Upload frames to the GPU (
hwupload). - Apply the
tonemap_openclfilter to convert luminance and color primaries. - Download frames back to CPU memory (
hwdownload) and reformat them (usually to 8-bitnv12oryuv420pfor standard SDR encoding).
Basic Command Example
The following command converts an HDR10 video to SDR using the Mobius
tone mapping algorithm and encodes it using libx264:
ffmpeg -init_hw_device opencl=gpu:0.0 -filter_hw_device gpu \
-i input_hdr.mkv \
-filter_complex \
"[0:v]format=p010,hwupload,tonemap_opencl=tonemap=mobius:format=nv12:desat=0.5,hwdownload,format=nv12[v]" \
-map "[v]" -map 0:a? \
-c:v libx264 -crf 20 -preset medium \
-c:a copy output_sdr.mp4Explanation of Key Flags
-init_hw_device opencl=gpu:0.0 -filter_hw_device gpu: Initializes the OpenCL context using the first platform and first device (0.0), assigning it the labelgpuand binding it to the filter graph.format=p010,hwupload: Ensures the decoded input is in 10-bit format before transferring it to the GPU viahwupload.tonemap_opencl: The core filter.tonemap=mobius: The tone-mapping curve. Alternatives includereinhard,hable, andclip.mobiustypically preserves highlights while maintaining contrast.format=nv12: Specifies the output pixel format in OpenCL memory. Setting this tonv12reduces the frame depth to 8-bit, appropriate for SDR.desat=0.5: Adjusts desaturation for bright pixels to prevent blown-out colors.
hwdownload,format=nv12: Pulls the processed frames from GPU memory back to host RAM and normalizes the format for standard CPU encoders.
Common
tonemap_opencl Parameters
You can fine-tune the output by adjusting the following options
inside the tonemap_opencl filter:
tonemap: Specifies the tone-mapping algorithm:mobius: Smooth roll-off of highlights; best balance between details and contrast.hable: Filmic tone mapping; prevents oversaturated highlights at the expense of dark detail.reinhard: Simple non-linear curve; bright scenes can appear washed out if not tuned.clip: Hard clips out-of-range luminance; fastest, but loses highlight details.
param: Modifies algorithm-specific behavior (e.g., transition threshold formobius). Default is typically tuned for general use.desat: Controls desaturation strength for out-of-gamut luminance (range0.0to1.0). Higher values prevent color clipping in high-brightness areas.peak: Overrides signal peak luminance in nits. If the source metadata is absent or inaccurate, you can define it explicitly (e.g.,peak=1000).
Advanced: Integrating with Hardware Encoders
If you use a hardware encoder like VAAPI or NVENC, you can reduce
host memory roundtrips by deriving the hardware device context directly,
avoiding hwdownload where supported by your driver stack.
For general compatibility across diverse GPU vendors, the standard
pipeline using hwupload and hwdownload paired
with standard encoders provides the most consistent tone-mapping
results.