Hello,
I am having troubles decoding a bt709 h264 stream and get correct colors. It can be reproduced on Orin AGX running R36 (release), REVISION: 2.0, as well as on Xavier NX running R32 (release), REVISION: 7.3
We encoded a steady colorbar pattern (grabbed from a 1080p HD source) using x264enc:
gst-launch-1.0 multifilesrc location=img.png caps=image/png,framerate=60000/1001 num-buffers=200 ! pngdec ! videoconvert ! x264enc bitrate=10000 ! video/x-h264,profile=high ! mpegtsmux ! tsdemux ! video/x-h264 ! filesink location=test.h264
The h264 stream has VUI flags as follows (matching gstreamer definition of bt709 colorspace): limited value range, bt709 matrix, bt709 transfer and bt709 color primaries. This can be validated by ffmpeg with trace_headers.
[trace_headers @ 0x55e62e646b40] 84 vui_parameters_present_flag 1 = 1
[trace_headers @ 0x55e62e646b40] 95 video_signal_type_present_flag 1 = 1
[trace_headers @ 0x55e62e646b40] 96 video_format 010 = 5
[trace_headers @ 0x55e62e646b40] 99 video_full_range_flag 0 = 0
[trace_headers @ 0x55e62e646b40] 100 colour_description_present_flag 1 = 1
[trace_headers @ 0x55e62e646b40] 101 colour_primaries 00000001 = 1
[trace_headers @ 0x55e62e646b40] 109 transfer_characteristics 00000001 = 1
[trace_headers @ 0x55e62e646b40] 117 matrix_coefficients 00000001 = 1
The encoded video is decoded to an output device that requires UYVY format and bt709 colorimetry:
gst-launch-1.0 filesrc location=test.h264 ! h264parse ! nvv4l2decoder ! nvvidconv ! video/x-raw,colorimetry=bt709 ! v4l2sink
Unfortunately, the color rendering is bad (darker than expected). One way to solve the color issue is to first decode to RGBA, then use sw converter (videoconvert) to UYVY. This is not an ideal solution because of the SW conversion.
To help to reproduce and analyse the issue, one frame of the video output can be decoded in different ways to different files, then files are compared. As a reference I also used libav h264 as a software decoder:
- decoder can be avdec_h264(I420)+videoconvert or nvv4l2decoder(NV12)+nvvidconv
- the first conversion is done to an intermediate format: RGBA or UYVY
- a second conversion is done with videoconvert to UYVY (required by the output device)
- one frame is store to a file for each case (decoder crossed by RGBA/UYVY intermediate format)
The common parts of such a pipeline is as follows:
filesrc location=test.h264 ! h264parse ! <decoder> ! video/x-raw,format=[RGBA,UYVY] ! videoconvert ! video/x-raw,format=UYVY,colorimetry=bt709 ! multifilesink location=<filename> max-files=1
Once having 4 files (avdecRGBA, avdecUYVY, nvdecRGBA, nvdecUYVY), they can be compared using ffmpeg psnr filter as follows:
ffmpeg -pix_fmt uyvy422 -s:v 1920x1080 -i <fileA> -pix_fmt uyvy422 -s:v 1920x1080 -i <fileB> -filter_complex psnr -f null -
Results show that only nvdecUYVY differs significatively from the others: PSNR is under 31dB when nvdecUYVY is compared to another file, while it goes higher than 42dB when comparing other files to each other’s.
The nvconv conversion from NV12 to UYVY looks to be broken. Are there additional tests that can be made ? nvconv parameters to check ?