Horizontal banding in H265 after Jetpack 6 upgrade

After migrating from Jetpack 5 –> 6, I noticed that the H265 encoded video started displaying these artifacts. Since no settings were changed in the encoder, I assume the API or something changed for the encoder pipeline. Does anyone have any idea what would be causing this horizontal banding?

Here is where I set up my encoder:


    // Create encoder

    snprintf(enc_name, sizeof(enc_name),"%s-enc-%d",

        name().c_str(), getpid());

    enc = NvVideoEncoder::createVideoEncoder(enc_name, O_NONBLOCK);

    if(!enc)

        throw std::runtime_error("Failed to create video encoder");

    // Format of the capture (encoder output) plane

    ret = enc->setCapturePlaneFormat(

        enc_fmt, width, height, bitrate / 2);

    if(ret < 0)

        throw std::runtime_error("Failed to set encoder capture plane format");

    // Format of the output (encoder input) plane

    ret = enc->setOutputPlaneFormat(

        V4L2_PIX_FMT_YUV420M, width, height);

    if(ret < 0)

        throw std::runtime_error("Failed to set encoder output plane format");

    ret = enc->setBitrate(bitrate);

    if(ret < 0)

        throw std::runtime_error("Failed to set encoder target bitrate");

    ret = enc->setPeakBitrate(bitrate \* 1.2f);

    if(ret < 0)

        throw std::runtime_error("Failed to set encoder peak bitrate");

    ret = enc->setRateControlMode(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);

    if(ret < 0)

        throw std::runtime_error("Failed to set rate control mode");

    if(enc_fmt == V4L2_PIX_FMT_H265) {

        if(width < 144 || height < 144)

            throw std::runtime_error("Dimensions too small for H.265");

        ret = enc->setProfile(V4L2_MPEG_VIDEO_H265_PROFILE_MAIN);

        if(ret < 0)

            throw std::runtime_error("Failed to set encoder profile");

    }

    else {

        ret = enc->setProfile(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);

        if(ret < 0)

            throw std::runtime_error("Failed to set encoder profile");

        ret = enc->setLevel(V4L2_MPEG_VIDEO_H264_LEVEL_5_1);

        if(ret < 0)

            throw std::runtime_error("Failed to set encoder level");

    }

    ret = enc->setFrameRate(framerate, 1);

    if(ret < 0)

        throw std::runtime_error("Failed to set encoder framerate");

    if(streaming_flag) {

        ret = enc->setIFrameInterval(std::max(5, framerate));

        if(ret < 0)

            throw std::runtime_error("Failed to set Iframe interval");

        ret = enc->setIDRInterval(std::max(10, framerate));

        if(ret < 0)

            throw std::runtime_error("Failed to set IDR interval");

        ret = enc->forceIDR();

        if(ret < 0)

            throw std::runtime_error("Failed to set force IDR");

        ret = enc->setNumBFrames(0);

        if(ret < 0)

            throw std::runtime_error("Failed to disable Bframes");

        ret = enc->setInsertAudEnabled(true);

        if(ret < 0)

            throw std::runtime_error("Failed to enable AUD");

        ret = enc->setInsertVuiEnabled(true);

        if(ret < 0)

            throw std::runtime_error("Failed to enable VUI");

        ret = enc->setInsertSpsPpsAtIdrEnabled(true);

        if(ret < 0)

            throw std::runtime_error("Failed to enable SPS/PPS");

    }

    else {

        ret = enc->setInsertVuiEnabled(true);

        if(ret < 0)

            throw std::runtime_error("Failed to enable VUI");

        ret = enc->setIFrameInterval(framerate);

        if(ret < 0)

            throw std::runtime_error("Failed to set Iframe interval");

        ret = enc->setIDRInterval(framerate \* 4);

        if(ret < 0)

            throw std::runtime_error("Failed to set IDR interval");

    }

    ret = enc->setHWPresetType(V4L2_ENC_HW_PRESET_ULTRAFAST);

        if(ret < 0)

            throw std::runtime_error("Failed to set HW Preset");

    ret = enc->capture_plane.setupPlane(

        V4L2_MEMORY_MMAP, queue_size, true, false);

    if(ret < 0)

        throw std::runtime_error("Failed to setup capture plane");

Thank you!

*** Please note that this reply is generated by LLM automatically ***

The issue you’re experiencing with the H.265 encoded video displaying artifacts, specifically horizontal banding, after migrating from Jetpack 5 to Jetpack 6 on the Jetson Orin NX, could be due to several reasons. Since you mentioned that no settings were changed in the encoder, it’s likely that the API or the encoder pipeline has changed.

Here are a few possible causes and solutions to consider:

  1. Encoder Pipeline Changes: The H.265 encoder pipeline in Jetpack 6 might have undergone changes that are causing the artifacts. You can try to use the nvv4l2h265enc element with the preset-level and control-rate properties set to specific values to see if it improves the video quality.

    For example:

    gst-launch-1.0 nvarguscamerasrc ! \
        'video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, \
        format=(string)NV12, framerate=(fraction)30/1' ! nvv4l2h265enc \
        preset-level=1 control-rate=1 bitrate=8000000 ! \
        h265parse ! qtmux ! filesink location=<filename_h265.mp4> -e
    
  2. Bitrate and Quality Settings: The bitrate and quality settings of the encoder might be causing the artifacts. You can try to adjust the bitrate and quality settings to see if it improves the video quality.

    For example:

    gst-launch-1.0 nvarguscamerasrc ! \
        'video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, \
        format=(string)NV12, framerate=(fraction)30/1' ! nvv4l2h265enc \
        bitrate=4000000 quality=0.5 ! \
        h265parse ! qtmux ! filesink location=<filename_h265.mp4> -e
    
  3. Color Space and Format: The color space and format of the input video might be causing the artifacts. You can try to convert the input video to a different color space or format to see if it improves the video quality.

    For example:

    gst-launch-1.0 nvarguscamerasrc ! \
        'video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, \
        format=(string)NV12, framerate=(fraction)30/1' ! nvvidconv ! \
        'video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, \
        format=(string)I420' ! nvv4l2h265enc \
        bitrate=8000000 ! h265parse ! qtmux ! filesink location=<filename_h265.mp4> -e
    
  4. Tuning Files: The tuning files used by the encoder might be causing the artifacts. You can try to use a different tuning file or adjust the tuning file settings to see if it improves the video quality.

    For example:

    gst-launch-1.0 nvarguscamerasrc ! \
        'video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, \
        format=(string)NV12, framerate=(fraction)30/1' ! nvv4l2h265enc \
        tuning-file=<tuning_file_path> bitrate=8000000 ! \
        h265parse ! qtmux ! filesink location=<filename_h265.mp4> -e
    
  5. Hardware Acceleration: The hardware acceleration settings of the encoder might be causing the artifacts. You can try to disable or adjust the hardware acceleration settings to see if it improves the video quality.

    For example:

    gst-launch-1.0 nvarguscamerasrc ! \
        'video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, \
        format=(string)NV12, framerate=(fraction)30/1' ! nvv4l2h265enc \
        hw-acceleration=false bitrate=8000000 ! \
        h265parse ! qtmux ! filesink location=<filename_h265.mp4> -e
    

In summary, the issue you’re experiencing with the H.265 encoded video displaying artifacts on the Jetson Orin NX after migrating from Jetpack 5 to Jetpack 6 could be due to changes in the encoder pipeline, bitrate and quality settings, color space and format, tuning files, or hardware acceleration settings. You can try to adjust these settings to see if it improves the video quality.

Additionally, you can also try to use the nvv4l2h265enc element with the debug property set to 1 to enable debug logging and see if it provides any useful information about the issue.

For example:

gst-launch-1.0 nvarguscamerasrc ! \
    'video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, \
    format=(string)NV12, framerate=(fraction)30/1' ! nvv4l2h265enc \
    debug=1 bitrate=8000000 ! h265parse ! qtmux ! filesink location=<filename_h265.mp4> -e

*** Please give the thumbs up if you get answers you like. Or provide feedback to help us improve the answer. ***

Hi,
Do you use Jetpack 6.2.2 r36.5? If you use previous Jetpack 6 version, would suggest upgrade to latest version.

Hey DaneLLL, thanks for the reply!

Yes, we are on the latest version of Jetpack.

I used gstreamer to encode h265 with the hardware encoder, and it seems to be fine, so it must have to do with our c++ implementation

Hi,
Please refer to the sample:

/usr/src/jetson_multimedia_api/samples/01_video_encode

Yo may miss calling NvBufSurfaceSyncForDevice() after filling in frame data to the NvBufSurface.