Nvh264enc and webrtcsink on jetson

I am unable to find a solution for using nvh264enc together with webrtcsink on a Jetson Orin AGX.
It seems webrtcsink is can not defer the needed encoder for my input caps.

Right now i am running this pipeline, streaming 3 GigE cameras to a Chrome Web UI

With this i am loosing all the good stuff from webrtcsink controlling bitrate etc..
Since for now the sink and UI are on localhost at the same time, this is running ok, but unstable.
I am dropping frames both in pipeline and Browser it seems, i have no good idea how to really profile this.

To make this work i had to add a pad probe to convert force-keyunit events to the custom action signal based NVIDIA encoder API ( i took this from gst-plugins-rs/net/webrtc/src/webrtcsink/imp.rs#L729:

namespace {

GstPadProbeReturn force_keyunit_probe(GstPad* pad, GstPadProbeInfo* info, gpointer user_data) {
    auto* saw_buffer = static_cast<std::atomic<bool>*>(user_data);

    if (info->type & (GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BUFFER_LIST)) {
        saw_buffer->store(true, std::memory_order_seq_cst);
    } else if (info->type & GST_PAD_PROBE_TYPE_EVENT_UPSTREAM) {
        GstEvent* ev = GST_PAD_PROBE_INFO_EVENT(info);
        if (gst_video_event_is_force_key_unit(ev) && saw_buffer->load(std::memory_order_seq_cst)) {
            GstObject* parent = gst_pad_get_parent(pad);  // new ref, NULL if unparented
            if (parent) {
                // dGPU nvv4l2h264enc exposes force-idr as a PROPERTY, not an action signal,
                // FIX from:
                // https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/blob/0.15/net%2Fwebrtc%2Fsrc%2Fwebrtcsink%2Fimp.rs?ref_type=heads&blame=1#L729
                if (g_object_class_find_property(G_OBJECT_GET_CLASS(parent), "force-idr") != nullptr) {
                    g_object_set(G_OBJECT(parent), "force-idr", TRUE, NULL);
                }
                gst_object_unref(parent);
            }
        }
    }

    return GST_PAD_PROBE_OK;
}

}  // namespace

void add_nv4l2enc_force_keyunit_workaround(GstElement* enc) {
    GstPad* srcpad = gst_element_get_static_pad(enc, "src");
    g_assert(srcpad != nullptr);

    auto* saw_buffer = new std::atomic<bool>(false);

    gulong id = gst_pad_add_probe(
        srcpad,
        static_cast<GstPadProbeType>(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BUFFER_LIST |
                                     GST_PAD_PROBE_TYPE_EVENT_UPSTREAM),
        force_keyunit_probe, saw_buffer, [](gpointer data) { delete static_cast<std::atomic<bool>*>(data); });
    g_assert(id != 0);

    gst_object_unref(srcpad);
}

Running the pipeline on a dGPU x86 without the extra encoder, the automatic encoder selection works fine with following warnings:

0:00:06.328453208 23639 0x7976b40031c0 WARN                GST_PADS gstpad.c:4392:gst_pad_peer_query:<capsfilter7:src> could not send sticky events
0:00:06.328617623 23639 0x7973ec038a40 WARN                   nvenc gstnvbaseenc.c:2668:gst_nv_base_enc_set_property:<nvh265enc0> device does not support requested rate control mode 5
0:00:06.328634541 23639 0x7976b40031c0 WARN                   nvenc gstnvbaseenc.c:1745:gst_nv_base_enc_set_format:<nvh264enc0> error: Selected preset not supported
0:00:06.328653345 23639 0x7976b40031c0 WARN            videoencoder gstvideoencoder.c:773:gst_video_encoder_setcaps:<nvh264enc0> rejected caps video/x-raw, width=(int)616, height=(int)514, multiview-mode=(string)mono, multiview-flags=(GstVideoMultiviewFlagsSet)0:ffffffff:/right-view-first/left-flipped/left-flopped/right-flipped/right-flopped/half-aspect/mixed-mono, framerate=(fraction)15/1, batch-size=(uint)1, num-surfaces-per-frame=(int)1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, format=(string)NV12, block-linear=(boolean)false, nvbuf-memory-type=(string)nvbuf-mem-cuda-device, gpu-id=(int)0
0:00:06.328861551 23639 0x7976b4003a40 WARN          nvvideoconvert gstnvvideoconvert.c:1818:gst_nvvideoconvert_set_caps:<nvvideoconvert8> Cannot keep DAR
0:00:06.334418849 23639 0x7976b40031c0 WARN                   nvenc gstnvbaseenc.c:1745:gst_nv_base_enc_set_format:<nvh264enc0> error: Selected preset not supported
0:00:06.334454170 23639 0x7976b40031c0 WARN            videoencoder gstvideoencoder.c:773:gst_video_encoder_setcaps:<nvh264enc0> rejected caps video/x-raw, width=(int)616, height=(int)514, multiview-mode=(string)mono, multiview-flags=(GstVideoMultiviewFlagsSet)0:ffffffff:/right-view-first/left-flipped/left-flopped/right-flipped/right-flopped/half-aspect/mixed-mono, framerate=(fraction)15/1, batch-size=(uint)1, num-surfaces-per-frame=(int)1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, format=(string)NV12, block-linear=(boolean)false, nvbuf-memory-type=(string)nvbuf-mem-cuda-device, gpu-id=(int)0
0:00:06.336743925 23639 0x7973ec038a40 WARN                 default gstdebugutils.c:881:gst_debug_bin_to_dot_file: Failed to open file '/app/data/dot_files/0.00.06.336727458-webrtcsink-discovery-pipeline3-Null-to-Ready.dot' for writing: No such file or directory
0:00:06.337048903 23639 0x7976b4003a40 WARN                  vpxenc gstvpxenc.c:1863:gst_vpx_enc_set_format:<vp9enc0> "Failed to set VP8E_SET_NOISE_SENSITIVITY": incapable (details: (NULL))
0:00:06.337089267 23639 0x7976b4003a40 WARN                  vpxenc gstvpxenc.c:1878:gst_vpx_enc_set_format:<vp9enc0> "Failed to set VP8E_SET_TOKEN_PARTIONS": incapable (details: (NULL))
0:00:06.337201799 23639 0x7976b4004e90 FIXME                default gstutils.c:4088:gst_element_decorate_stream_id_internal:<appsrc3> Creating random stream-id, consider implementing a deterministic way of creating a stream-id
0:00:06.337205644 23639 0x7973ec038a40 WARN                 default gstdebugutils.c:881:gst_debug_bin_to_dot_file: Failed to open file '/app/data/dot_files/0.00.06.337191404-webrtcsink-discovery-pipeline0-done.dot' for writing: No such file or directory
0:00:06.339079480 23639 0x7973ec038a40 WARN              webrtcsink net/webrtc/src/webrtcsink/imp.rs:4425:gstrswebrtc::webrtcsink::imp::BaseWebRTCSink::run_discovery_pipeline::{{closure}}:<webrtcsink> Error in discovery pipeline: Error {
    structure: Some(
        GstMessageError {
            gerror: (GError) ((GError*) 0x797310007030),
            debug: (gchararray) "../sys/nvcodec/gstnvbaseenc.c(1745): gst_nv_base_enc_set_format (): /GstPipeline:pipeline1/GstNvH264Enc:nvh264enc0:\nSelected preset not supported",
        },
    ),
    source: Some(
        (
            Object {
                inner: TypedObjectRef {
                    inner: 0x00007973ec7a0ad0,
                    type: GstNvH264Enc,
                },
            },
            "nvh264enc0",
        ),
    ),
    error: Error {
        domain: gst-library-error-quark,
        code: 5,
        message: "Could not configure supporting library.",
    },
    debug: Some(
        "../sys/nvcodec/gstnvbaseenc.c(1745): gst_nv_base_enc_set_format (): /GstPipeline:pipeline1/GstNvH264Enc:nvh264enc0:\nSelected preset not supported",
    ),
    details: None,
}
0:00:06.339116165 23639 0x7973ec038a40 WARN                 default gstdebugutils.c:881:gst_debug_bin_to_dot_file: Failed to open file '/app/data/dot_files/0.00.06.339107731-webrtcsink-discovery-pipeline1-error.dot' for writing: No such file or directory
0:00:06.339260734 23639 0x7976b4004670 WARN          nvvideoconvert gstnvvideoconvert.c:1818:gst_nvvideoconvert_set_caps:<nvvideoconvert10> Cannot keep DAR
0:00:06.339683056 23639 0x7976b4004670 WARN                   nvenc gstnvbaseenc.c:1745:gst_nv_base_enc_set_format:<nvh265enc0> error: Selected preset not supported
0:00:06.339709152 23639 0x7976b4004670 WARN            videoencoder gstvideoencoder.c:773:gst_video_encoder_setcaps:<nvh265enc0> rejected caps video/x-raw, width=(int)616, height=(int)514, multiview-mode=(string)mono, multiview-flags=(GstVideoMultiviewFlagsSet)0:ffffffff:/right-view-first/left-flipped/left-flopped/right-flipped/right-flopped/half-aspect/mixed-mono, framerate=(fraction)15/1, batch-size=(uint)1, num-surfaces-per-frame=(int)1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, format=(string)NV12, block-linear=(boolean)false, nvbuf-memory-type=(string)nvbuf-mem-cuda-device, gpu-id=(int)0
0:00:06.339999822 23639 0x7976b4004670 WARN                   nvenc gstnvbaseenc.c:1745:gst_nv_base_enc_set_format:<nvh265enc0> error: Selected preset not supported
0:00:06.340020406 23639 0x7976b4004670 WARN            videoencoder gstvideoencoder.c:773:gst_video_encoder_setcaps:<nvh265enc0> rejected caps video/x-raw, width=(int)616, height=(int)514, multiview-mode=(string)mono, multiview-flags=(GstVideoMultiviewFlagsSet)0:ffffffff:/right-view-first/left-flipped/left-flopped/right-flipped/right-flopped/half-aspect/mixed-mono, framerate=(fraction)15/1, batch-size=(uint)1, num-surfaces-per-frame=(int)1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, format=(string)NV12, block-linear=(boolean)false, nvbuf-memory-type=(string)nvbuf-mem-cuda-device, gpu-id=(int)0
0:00:06.340032414 23639 0x7976b4004670 WARN                GST_PADS gstpad.c:4392:gst_pad_peer_query:<capsfilter9:src> could not send sticky events
0:00:06.340801249 23639 0x7976b4004670 WARN                   nvenc gstnvbaseenc.c:1745:gst_nv_base_enc_set_format:<nvh265enc0> error: Selected preset not supported
0:00:06.340827455 23639 0x7976b4004670 WARN            videoencoder gstvideoencoder.c:773:gst_video_encoder_setcaps:<nvh265enc0> rejected caps video/x-raw, width=(int)616, height=(int)514, multiview-mode=(string)mono, multiview-flags=(GstVideoMultiviewFlagsSet)0:ffffffff:/right-view-first/left-flipped/left-flopped/right-flipped/right-flopped/half-aspect/mixed-mono, framerate=(fraction)15/1, batch-size=(uint)1, num-surfaces-per-frame=(int)1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, format=(string)NV12, block-linear=(boolean)false, nvbuf-memory-type=(string)nvbuf-mem-cuda-device, gpu-id=(int)0
0:00:06.341680860 23639 0x7973ec038a40 WARN                 default gstdebugutils.c:881:gst_debug_bin_to_dot_file: Failed to open file '/app/data/dot_files/0.00.06.341674634-webrtcsink-discovery-pipeline2-done.dot' for writing: No such file or directory
0:00:06.342349467 23639 0x7976b4004670 WARN                   nvenc gstnvbaseenc.c:1745:gst_nv_base_enc_set_format:<nvh265enc0> error: Selected preset not supported
0:00:06.342379200 23639 0x7976b4004670 WARN            videoencoder gstvideoencoder.c:773:gst_video_encoder_setcaps:<nvh265enc0> rejected caps video/x-raw, width=(int)616, height=(int)514, multiview-mode=(string)mono, multiview-flags=(GstVideoMultiviewFlagsSet)0:ffffffff:/right-view-first/left-flipped/left-flopped/right-flipped/right-flopped/half-aspect/mixed-mono, framerate=(fraction)15/1, batch-size=(uint)1, num-surfaces-per-frame=(int)1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, format=(string)NV12, block-linear=(boolean)false, nvbuf-memory-type=(string)nvbuf-mem-cuda-device, gpu-id=(int)0
0:00:06.353201737 23639 0x7973ec038a40 WARN              webrtcsink net/webrtc/src/webrtcsink/imp.rs:4425:gstrswebrtc::webrtcsink::imp::BaseWebRTCSink::run_discovery_pipeline::{{closure}}:<webrtcsink> Error in discovery pipeline: Error {
    structure: Some(
        GstMessageError {
            gerror: (GError) ((GError*) 0x7972f8006770),
            debug: (gchararray) "../sys/nvcodec/gstnvbaseenc.c(1745): gst_nv_base_enc_set_format (): /GstPipeline:pipeline3/GstNvH265Enc:nvh265enc0:\nSelected preset not supported",
        },
    ),
    source: Some(
        (
            Object {
                inner: TypedObjectRef {
                    inner: 0x00007973ec580dd0,
                    type: GstNvH265Enc,
                },
            },
            "nvh265enc0",
        ),
    ),
    error: Error {
        domain: gst-library-error-quark,
        code: 5,
        message: "Could not configure supporting library.",
    },
    debug: Some(
        "../sys/nvcodec/gstnvbaseenc.c(1745): gst_nv_base_enc_set_format (): /GstPipeline:pipeline3/GstNvH265Enc:nvh265enc0:\nSelected preset not supported",
    ),
    details: None,
}
0:00:06.353240489 23639 0x7973ec038a40 WARN                 default gstdebugutils.c:881:gst_debug_bin_to_dot_file: Failed to open file '/app/data/dot_files/0.00.06.353229745-webrtcsink-discovery-pipeline3-error.dot' for writing: No such file or directory
0:00:06.354988637 23639 0x7973ec038a40 WARN              webrtcsink net/webrtc/src/webrtcsink/imp.rs:4571:gstrswebrtc::webrtcsink::imp::BaseWebRTCSink::lookup_caps::{{closure}}:<webrtcsink> Codec discovery pipeline failed: Could not configure supporting library.
0:00:06.354996274 23639 0x7973ec038a40 WARN              webrtcsink net/webrtc/src/webrtcsink/imp.rs:4571:gstrswebrtc::webrtcsink::imp::BaseWebRTCSink::lookup_caps::{{closure}}:<webrtcsink> Codec discovery pipeline failed: Could not configure supporting library.

I am just unsure if this really uses hardware accelerated encoding.

I was finally able to solve this issue with some help from nvidia. Now webrtcsink can discover the encoder and do congestion control correctly.
The encoder provided for x86 is not opensource, but the jetson variant can also be built for it, so this solves this issue on both platforms, dGPU and Jetson.
The encoder source code can be found here:

mkdir nv-videocodec
cd nv-videocodec
git clone -b l4t/l4t-r39.2.1 https://gitlab.com/nvidia/nv-tegra/tegra/gst-src/gst-nvvideo4linux2.git
git clone -b l4t/l4t-r39.2.1 https://gitlab.com/nvidia/nv-tegra/tegra/v4l2-src/v4l2_libs

And can be built by copying this Makefile to nv-videocodec/gst-nvvideo4linux

###############################################################################
#
# Copyright (c) 2018-2026, NVIDIA CORPORATION.  All rights reserved.
#
# Build libgstnvvideo4linux2.so against a DeepStream install:
#   /opt/nvidia/deepstream/deepstream
#
# Registers nvv4l2decoder, nvv4l2h264enc, nvv4l2h265enc (and NVENC siblings).
#
#   make
#   make install
#   GST_PLUGIN_PATH=$PWD/build gst-inspect-1.0 nvv4l2decoder
#
# Override the SDK root if needed:
#   make DS_SDK_ROOT=/opt/nvidia/deepstream/deepstream-9.1
#
###############################################################################

SO_NAME := libgstnvvideo4linux2.so

CC ?= gcc
TARGET_DEVICE := $(shell $(CC) -dumpmachine | cut -f1 -d -)

SRC_DIR := gst-v4l2
BUILD_DIR := build
V4L2_INC_DIR ?= $(CURDIR)/../v4l2_libs/include

# DeepStream SDK (prebuilt headers + libs). The default path is the
# versioned symlink shipped with the SDK.
DS_SDK_ROOT ?= /opt/nvidia/deepstream/deepstream
ifeq ($(wildcard $(DS_SDK_ROOT)/sources/includes/nvbufsurface.h),)
  ifneq ($(wildcard /opt/nvidia/deepstream/deepstream-9.1/sources/includes/nvbufsurface.h),)
    DS_SDK_ROOT := /opt/nvidia/deepstream/deepstream-9.1
  endif
endif

DS_INC_DIR ?= $(DS_SDK_ROOT)/sources/includes
LIB_INSTALL_DIR ?= $(DS_SDK_ROOT)/lib
GST_INSTALL_DIR ?= $(DS_SDK_ROOT)/lib/gst-plugins

# Optional DEST_DIR prefix used by the shipped README (`DEST_DIR=<dir> make install`)
DEST_DIR ?=

CUDA_VER ?= $(shell basename $$(readlink -f /usr/local/cuda 2>/dev/null) | sed -n 's/^cuda-//p')
ifeq ($(CUDA_VER),)
  CUDA_VER := 13.2
endif
CUDA_INC_DIR ?= /usr/local/cuda-$(CUDA_VER)/include
ifeq ($(wildcard $(CUDA_INC_DIR)/cuda.h),)
  CUDA_INC_DIR := /usr/local/cuda/include
endif

# Do not use pkg-config libv4l2: headers come from v4l2_libs, the .so from DeepStream.
PKGS := gstreamer-1.0 \
	gstreamer-base-1.0 \
	gstreamer-video-1.0 \
	gstreamer-allocators-1.0 \
	glib-2.0

SRCS := $(wildcard $(SRC_DIR)/*.c)
OBJS := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SRCS))
TARGET := $(BUILD_DIR)/$(SO_NAME)

CFLAGS := -fPIC -std=gnu11 \
	-DEXPLICITLY_ADDED=1 \
	-DGETTEXT_PACKAGE=1 \
	-DHAVE_LIBV4L2=1 \
	-DUSE_V4L2_TARGET_NV=1

ifeq ($(TARGET_DEVICE),aarch64)
  ifneq ($(wildcard /usr/src/jetson_multimedia_api/include),)
    INCLUDES += -I/usr/src/jetson_multimedia_api/include
  endif
else
  CFLAGS += -DUSE_V4L2_TARGET_NV_CODECSDK=1 \
            -DUSE_V4L2_TARGET_NV_X86=1 \
            -DUSE_V4L2_GST_HEADER_VER_1_8
endif

# v4l2_libs supplies libv4l2.h. DeepStream supplies nvbufsurface.h /
# gstnvdsseimeta.h / gst-nvcustomevent.h. Tree-local v4l2_nv_extensions.h
# is not installed with DeepStream.
# The arm64 DeepStream image lacks gstnvdsseimeta.h (x86 ships it under
# sources/includes); a copy of that MIT header lives next to this Makefile.
# It is searched last, so a platform-provided one wins.
INCLUDES += -I$(V4L2_INC_DIR) \
            -I$(DS_INC_DIR) \
            -I$(CUDA_INC_DIR) \
            -I. \
            -I$(SRC_DIR) \
            -I$(SRC_DIR)/gst \
            -I$(SRC_DIR)/ext \
            -I$(CURDIR)/nv-videocodec-include

CFLAGS += $(shell pkg-config --cflags $(PKGS))
CFLAGS += $(INCLUDES)

LDFLAGS := -shared -Wl,--no-undefined \
	-L$(LIB_INSTALL_DIR) \
	-Wl,-rpath,$(LIB_INSTALL_DIR)

LIBS := -lnvbufsurface -lnvbufsurftransform -l:libv4l2.so.0 -ldl -lm -lpthread
LIBS += $(shell pkg-config --libs $(PKGS))

.PHONY: all install clean help

all: $(TARGET)

$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
	@mkdir -p $(BUILD_DIR)
	$(CC) -c $< $(CFLAGS) -o $@

$(TARGET): $(OBJS)
	$(CC) -o $@ $(OBJS) $(LDFLAGS) $(LIBS)

install: $(TARGET)
	mkdir -p $(DEST_DIR)$(GST_INSTALL_DIR)
	cp -vp $(TARGET) $(DEST_DIR)$(GST_INSTALL_DIR)

clean:
	rm -rf $(BUILD_DIR)

help:
	@echo "Build $(SO_NAME) (nvv4l2decoder / nvv4l2h264enc / nvv4l2h265enc)"
	@echo "  DS_SDK_ROOT=$(DS_SDK_ROOT)"
	@echo "  V4L2_INC_DIR=$(V4L2_INC_DIR)"
	@echo "  LIB_INSTALL_DIR=$(LIB_INSTALL_DIR)"
	@echo "  GST_INSTALL_DIR=$(GST_INSTALL_DIR)"
	@echo "  TARGET=$(TARGET)"
	@echo ""
	@echo "Targets:"
	@echo "  make / make all   Compile the plugin into $(BUILD_DIR)/"
	@echo "  make install      Copy to $(GST_INSTALL_DIR)"
	@echo "  make clean        Remove $(BUILD_DIR)/"
	@echo ""
	@echo "Run without installing:"
	@echo "  export GST_PLUGIN_PATH=\$$PWD/$(BUILD_DIR):\$$GST_PLUGIN_PATH"
	@echo "  gst-inspect-1.0 nvv4l2decoder"

before building apply the following patch to the provided open source code, the encoder now correctly provides key frames on request by webrtcsink or other elements emitting GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME.

docker/patches/0001-force-key-unit-event-triggers-idr.patch:1-28

diff --git a/gst-v4l2/gstv4l2videoenc.c b/gst-v4l2/gstv4l2videoenc.c
index fa38e5e..f256cc7 100644
--- a/gst-v4l2/gstv4l2videoenc.c
+++ b/gst-v4l2/gstv4l2videoenc.c
@@ -1923,6 +1923,23 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
       goto start_task_failed;
   }
 
+#ifdef USE_V4L2_TARGET_NV
+  if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame)) {
+    GST_DEBUG_OBJECT (self, "force-key-unit: requesting IDR for frame %d",
+        frame->system_frame_number);
+    if (is_cuvid == TRUE) {
+      if (!set_v4l2_video_mpeg_class (self->v4l2output,
+              V4L2_CID_MPEG_VIDEOENC_FORCE_IDR_FRAME, 1))
+        GST_WARNING_OBJECT (self, "S_EXT_CTRLS for FORCE_IDR_FRAME failed");
+    }
+#ifndef USE_V4L2_TARGET_NV_X86
+    else {
+      gst_v4l2_video_encoder_forceIDR (self);
+    }
+#endif
+  }
+#endif
+
   if (frame->input_buffer) {
     GstVideoSEIMeta *meta =
         (GstVideoSEIMeta *) gst_buffer_get_meta (frame->input_buffer,

Since the encoder element is not providing constrained-baseline profile support, which is mandatory for the discovery process of webrtcsink, the constrained-baseline profile must be linked to the default baseline profile. This profile is the same as constrained-baseline according to Nvidia support: https://forums.developer.nvidia.com/t/nvv4l2h264enc-on-dgpu-rejects-profile-1-constrained-baseline/383425

docker/patches/0002-constrained-baseline-maps-to-baseline.patch:1-22

diff --git a/gst-v4l2/gstv4l2h264enc.c b/gst-v4l2/gstv4l2h264enc.c
index 0a90330..e01f068 100644
--- a/gst-v4l2/gstv4l2h264enc.c
+++ b/gst-v4l2/gstv4l2h264enc.c
@@ -290,7 +290,7 @@ v4l2_profile_from_string (const gchar * profile)
   if (g_str_equal (profile, "baseline")) {
     v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
   } else if (g_str_equal (profile, "constrained-baseline")) {
-    v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE;
+    v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
   } else if (g_str_equal (profile, "main")) {
     v4l2_profile = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
   } else if (g_str_equal (profile, "extended")) {
@@ -335,7 +335,7 @@ v4l2_profile_to_string (gint v4l2_profile)
 {
   switch (v4l2_profile) {
     case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
-      return "baseline";
+      return "constrained-baseline";
     case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
       return "constrained-baseline";
     case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:

i am using the provided Makefile successfully, installing the encoder with following lines in my Docker image, for the base image i am using nvcr.io/nvidia/deepstream:9.1-triton-multiarch for development:

Dockerfile:187-200

COPY ./docker/Makefile ./docker/patches/ /tmp/nv-videocodec-build/
COPY ./docker/nv-videocodec-include/ /tmp/nv-videocodec-build/nv-videocodec-include/
RUN set -eux; \
    mkdir /opt/nv-videocodec; cd /opt/nv-videocodec; \
    git clone https://gitlab.com/nvidia/nv-tegra/tegra/gst-src/gst-nvvideo4linux2.git; \
    git clone https://gitlab.com/nvidia/nv-tegra/tegra/v4l2-src/v4l2_libs; \
    git -C gst-nvvideo4linux2 checkout f9ac956fb7010a3b5a9758a1181ada8c332d83ec; \
    git -C v4l2_libs checkout 346cc4215b16b50719e02bab0bfead93e9fcf183; \
    cd gst-nvvideo4linux2; \
    git apply --verbose /tmp/nv-videocodec-build/*.patch; \
    cp -r /tmp/nv-videocodec-build/Makefile /tmp/nv-videocodec-build/nv-videocodec-include .; \
    make DS_SDK_ROOT=/opt/nvidia/deepstream/deepstream-9.1; \
    make install; \
    cd /; rm -rf /opt/nv-videocodec /tmp/nv-videocodec-build

To get this to build on jetson devices, this file is needed:

docker/nv-videocodec-include/gstnvdsseimeta.h:1-46

/**
 * Copyright (c) 2022, NVIDIA CORPORATION.  All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#ifndef __GST_NVDS_SEI_META_H__
#define __GST_NVDS_SEI_META_H__

#include <gst/gst.h>

#define GST_VIDEO_SEI_META_API_TYPE (gst_video_sei_meta_api_get_type())
#define GST_VIDEO_SEI_META_INFO (gst_video_sei_meta_get_info())

#define GST_USER_SEI_META g_quark_from_static_string("GST.USER.SEI.META")

typedef struct _GstVideoSEIMeta {
    GstMeta meta;
    guint sei_metadata_type;
    guint sei_metadata_size;
    void *sei_metadata_ptr;
} GstVideoSEIMeta;

GType gst_video_sei_meta_api_get_type(void) asm("gst_video_sei_meta_api_get_type");
const GstMetaInfo *gst_video_sei_meta_get_info(void) asm("gst_video_sei_meta_get_info");

GstVideoSEIMeta *gst_buffer_add_video_sei_meta(GstBuffer *buffer);
GstVideoSEIMeta *gst_buffer_get_video_sei_meta(GstBuffer *buffer);

#endif /*__GST_NVDS_SEI_META_H__*/