FFmpeg tonemap_opencl Hardware Accelerated Tone Mapping

This article provides a practical guide on how to use the tonemap_opencl filter in FFmpeg to perform hardware-accelerated High Dynamic Range (HDR) to Standard Dynamic Range (SDR) tone mapping. You will learn the required prerequisites, the core command syntax, and real-world examples to leverage your GPU for fast and efficient video transcoding.

Prerequisites

To use tonemap_opencl, your system and FFmpeg build must meet the following requirements:

  • FFmpeg compiled with OpenCL support: Ensure your FFmpeg binary was configured with the --enable-opencl flag. You can verify this by running ffmpeg -version and looking for enable-opencl in the configuration list.
  • GPU Drivers and OpenCL Runtime: Install the appropriate OpenCL drivers for your graphics card (Intel, AMD, or NVIDIA).
  • OpenCL-compatible GPU: A dedicated or integrated graphics card that supports OpenCL 1.2 or higher.

Core Command Structure

Hardware-accelerated filtering in FFmpeg requires initializing the hardware device, uploading the video frames to the GPU, processing them with the OpenCL filter, and downloading them back to system memory (unless using a full hardware encoder pipeline).

Here is the template for a basic pipeline:

ffmpeg -init_hw_device opencl=gpu -filter_hw_device gpu -i input_hdr.mp4 -vf "hwupload,tonemap_opencl=t=bt709:tonemap=mobius:format=nv12,hwdownload,format=nv12" -c:v libx264 -c:a copy output_sdr.mp4

Parameter Breakdown

  • -init_hw_device opencl=gpu: Initializes the OpenCL hardware device and labels it as gpu.
  • -filter_hw_device gpu: Instructs FFmpeg to use the initialized gpu device for the filtering graph.
  • hwupload: Uploads the decoded video frames from system memory to GPU memory.
  • tonemap_opencl: The core tone mapping filter.
    • t=bt709: Sets the target transfer characteristic to BT.709 (standard SDR color space).
    • tonemap=mobius: Specifies the tone mapping algorithm (options include mobius, reinhard, hable, linear, and clip). mobius or hable are generally recommended for preserving details in highlights.
    • format=nv12: Converts the 10-bit HDR pixel format (typically p010 or yuv420p10le) to 8-bit SDR format (nv12) within the GPU.
  • hwdownload: Downloads the processed frames from GPU memory back to system memory.
  • format=nv12: Sets the software pixel format for the output encoder.

Advanced Usage and Customization

Adjusting Brightness and Contrast

You can fine-tune the output by specifying the peak luminance of the source and target.

ffmpeg -init_hw_device opencl=gpu -filter_hw_device gpu -i input_hdr.mp4 -vf "hwupload,tonemap_opencl=t=bt709:tonemap=reinhard:peak=1000:target_peak=100:format=nv12,hwdownload,format=nv12" -c:v libx264 output_sdr.mp4
  • peak=1000: Overrides the source video's peak luminance (in nits).
  • target_peak=100: Sets the target display peak luminance (100 nits is standard for SDR).

Full Hardware Pipeline (NVENC Example)

If you want to decode, tone-map, and encode entirely on an NVIDIA GPU without transferring frames back and forth to system memory, use the following pipeline:

ffmpeg -init_hw_device opencl=ocl -init_hw_device cuda=cuda -filter_hw_device ocl -c:v hevc_cuvid -i input_hdr.mp4 -vf "hwmap=derive_device=opencl,tonemap_opencl=t=bt709:tonemap=mobius:format=nv12,hwmap=derive_device=cuda" -c:v h264_nvenc output_sdr.mp4
  • hevc_cuvid: Decodes the HDR video using NVIDIA CUDA hardware decoding.
  • hwmap=derive_device=opencl: Maps the CUDA frames to OpenCL frames directly in GPU memory.
  • hwmap=derive_device=cuda: Maps the processed OpenCL frames back to CUDA for the h264_nvenc encoder.