Jetson Orin AGX: tegrav4l2 encoder missing V4L2 colorimetry support for BT.2020 / full range

Hi NVIDIA team,

We have been investigating colorimetry metadata propagation when encoding video on a Jetson AGX Orin DevKit using the V4L2 encoder C++ API.

Our current platform is:

L4T | R36.4.7

Kernel | 5.15.148-tegra arm64

Device | Jetson AGX Orin DevKit

We are trying to correctly signal colorimetry metadata for encoded video streams.

From our testing, `V4L2_COLORSPACE_SMPTE170M` and `V4L2_COLORSPACE_REC709` appear to be propagated correctly to the encoded output metadata. However, `V4L2_COLORSPACE_BT2020` appears to be silently ignored or replaced by `V4L2_COLORSPACE_SMPTE170M`, which seems to be the default. Similarly, attempts to use full range appear to fall back to limited range.

For example, this works for SMPTE170M and REC709, but not for BT.2020:

encoderTry(m_encoder->setOutputPlaneFormat(V4L2_PIX_FMT_NV12M, inputWidth, inputHeight, V4L2_COLORSPACE_BT2020));

We also tried setting the detailed V4L2 colorimetry fields directly:

struct v4l2_format fmt = {};
if (m_encoder->output_plane.getFormat(fmt) == 0) {
   fmt.fmt.pix_mp.ycbcr_enc    = V4L2_YCBCR_ENC_BT2020;
   fmt.fmt.pix_mp.quantization = V4L2_QUANTIZATION_FULL_RANGE;
   fmt.fmt.pix_mp.xfer_func    = V4L2_XFER_FUNC_709;
   fmt.fmt.pix_mp.flags       |= V4L2_PIX_FMT_FLAG_SET_CSC;
   m_encoder->output_plane.setFormat(fmt);
}

This `VIDIOC_S_FMT` call returns `EINVAL` for all colorimetry configurations we tried, not only BT.2020. A subsequent `VIDIOC_G_FMT` readback shows `colorspace = 0`, which suggests that the driver does not retain the sub-fields.

In a previous discussion with NVIDIA, it was confirmed that full colorimetry support is currently missing in the `tegrav4l2` encoder layer. The configurations mentioned as needing V4L2 support were:

- BT.601 and BT.709, limited and full range, for H.264, H.265, and AV1

- BT.2020 for 10-bit H.265 and 10-bit AV1

Other Color Spaces (sRGB, OptRGB, DCI_P3) haven’t been discussed. My understanding from that discussion is that the Orin encoder hardware supports these configurations, but the V4L2 layer currently does not propagate all of them correctly. It would be interesting to know if supporting a wider set of color spaces and full range would be possible?

Additional question regarding the current behaviour:

In our current pipeline, we feed the encoder with already-converted YCbCr/NV12 data. If the input content is, for example, BT.2020 full-range but the encoder incorrectly signals it as SMPTE170M limited-range, are the input sample values still encoded unchanged, with only the VUI/container metadata being wrong? Or does the encoder/driver perform any conversion, clamping, or range remapping based on these colorimetry fields?

This distinction is important for us because if the issue is metadata-only, we can work around it for now by injecting the correct color fields at the bitstream or muxer level. If the encoded pixel data itself can be affected, then the workaround would not be sufficient.

Many thanks for your help.

Hi,
Encoding BT.601 full range, BT.601 limited range, BT.709 full range, BT.709 limited range are supported. Please check setup_output_dmabuf() in 01_video_encode sample. It configures format of NvBufSurface per enable_extended_colorformat

There is no softwa stack for encoding BT.2020 on Orin. Do you need to encode BT.2020 YUV420 8-bit or 10-bit, to H264 or H265? Would need to check if the use-case is supported on Orin. On AGX Thor, encoding BT.2020 is supported.

We would suggest upgrade to Jetpack 6.2.2 r36.5, or 7.2 r39.2. If you must stay on r36.4.7, please apply the PSIRT fix:

Making sure you're not a bot!

Hi,

Thank you for your answer.
We are using MMAP instad of DMABUF for practical reasons at the moment, and the enable_extended_colorformat as well as *_ER colorimetry enum do not seem to have any effect on the output range in the VUI SPS. Is the usage of DMABUF strictly required? If not, would you have a sample example setting Full Colorimetry Range for BT601 or BT709 with MMAP?

Regarding BT2020, yes we might need to encode BT.2020 YUV420 8-bit & 10-bit, to H264 or H265.

We are planning to upgrade to Jetpack 7+ soon.

Hi,
Please run the command:

01_video_encode$ ./video_encode 720.yuv 1280 720 H264 bt601_er.h264 --insert-vui --enable-extcolorfmt
01_video_encode$ ./video_encode 720.yuv 1280 720 H264 bt709_er.h264 --insert-vui --color-space 2 --enable-extcolorfmt
01_video_encode$ ./video_encode 720.yuv 1280 720 H264 bt709.h264 --insert-vui --color-space 2

And check the colorspace through ffprobe command:

$ ffprobe -i bt709_er.h264
ffprobe version 4.4.2-0ubuntu0.22.04.1 Copyright (c) 2007-2021 the FFmpeg developers
(...skip...)
Input #0, h264, from 'bt709_er.h264':
  Duration: N/A, bitrate: N/A
  Stream #0:0: Video: h264 (Constrained Baseline), yuvj420p(pc, bt709, progressive), 1280x720, 30 fps, 30 tbr, 1200k tbn, 60 tbc

Due to constraint of Orin, we can enable only BT2020 YUV420 10-bit in H265 encoding. Our team is checking on this.