GStreamer c++ pipeline crashes upon using force-IDR with nvv4l2h265enc

I have an application in c++ code that receives a h264 camera stream from an ethernet camera and decodes and encodes it in h265 to send it to another pc via udpsink. The receiving pc runs several pipelines with udpsrc and displays them on the screen in a GUI. For my application I need to switch the positions of the camera streams in the GUI, I acomplish that by changing the udpsink port since every pipeline in the GUI has another port. Problem is that upon switchg the images have artifacts until the next IDR frame is received. To counter that I force and IDR frame when I switch the ports.
unfortunately that crashes my code with no debug messages at all. I did that same with an “older” pipeline using omxh265enc, that worked just fine.

My Setup
Orin NX, Jetpack 5.1, GStreamer 1.16.3

Pipeline on Orin
gst-launch-1.0 udpsrc port=5001 ! application/x-rtp, payload=96 ! rtpjitterbuffer latency=0 drop-on-latency=true ! rtph264depay ! queue leaky=2 ! nvv4l2decoder ! queue leaky=2 ! nvvidconv flip-method =2 ! “video/x-raw(memory:NVMM), format=I420, width=800, height=480” ! queue leaky=2 ! nvv4l2h265enc maxperf-enable = true preset-level = 1 bitrate=1500000 control-rate=1 EnableTwopassCBR=true ! h265parse ! rtph265pay config-interval=1 pt=96 ! gdppay ! udpsink host=192.168.0.118 port=5701 sync=false

Pipeline on receiving PC
gst-launch-1.0 udpsrc port=5702 ! gdpdepay ! rtpjitterbuffer latency=0 drop-on-latency=true ! rtph265depay ! queue leaky=2 ! avdec_h265 ! queue leaky=2 ! videoconvert n-threads=6 ! queue leaky=2 ! xvimagesink sync=false

Hi,
Could you try h264 encoding? Would like to clarify if it’s specific to h265.

1 Like

You may try:

  • adjusting sender/receiver ports, as you’re sending to port 5701 but trying to read from port 5702
  • removing the gdp payloader. RTP would be enough, and repayloading may break RTP.

Try as sender:

gst-launch-1.0 udpsrc port=5001 ! application/x-rtp,encoding-name=H264 ! rtpjitterbuffer ! rtph264depay ! nvv4l2decoder ! nvvidconv flip-method =2 ! 'video/x-raw(memory:NVMM), format=NV12, width=800, height=480' ! queue ! nvv4l2h265enc maxperf-enable=true preset-level=1 bitrate=1500000 control-rate=1 EnableTwopassCBR=true insert-sps-pps=1 insert-vui=1 idrinterval=15 ! rtph265pay ! udpsink host=192.168.0.118 port=5701

and as receiver:

gst-launch-1.0 udpsrc port=5701 ! application/x-rtp,encoding-name=H265 ! rtpjitterbuffer ! queue ! rtph265depay ! avdec_h265 ! videoconvert ! xvimagesink 

If it works, start modifying from this. If not, post the errors.

1 Like

I’ve tried it with H264 encoding with the nvv4l2h264enc element, works perfectly. Same code with H265 still crashes. I tried increasing the debug level on the console output but still get no messages.

Sure the ports in my example are wrong, but that’s not the case it’s just an example pipeline since I run c++ code.
I removed the gdppay element, thank for the hint, but sadly that didn’t help and as I mentioned in my reply above I get no error messages.

Hi,
Thanks for the information. We will set up Jetpack 5.1.1 and try to reproduce the issue.

Hi,
We run the test sample n Jetpack 5.1.1 and do not observe the issue:

#include <cstdlib>
#include <gst/gst.h>
#include <gst/gstinfo.h>
#include <gst/app/gstappsink.h>
#include <glib-unix.h>
#include <dlfcn.h>

#include <iostream>
#include <sstream>
#include <thread>

using namespace std;

#define USE(x) ((void)(x))

static GstPipeline *gst_pipeline = nullptr;
static string launch_string;
static unsigned int accumulate_size = 0;
static unsigned int accumulate_count = 0;

static void appsink_eos(GstAppSink * appsink, gpointer user_data)
{
    printf("app sink receive eos\n");
}

static GstFlowReturn new_buffer(GstAppSink *appsink, gpointer user_data)
{
    GstSample *sample = NULL;

    g_signal_emit_by_name (appsink, "pull-sample", &sample,NULL);

    if (sample)
    {
        GstBuffer *buffer = NULL;
        GstCaps   *caps   = NULL;
        GstMapInfo map    = {0};

        caps = gst_sample_get_caps (sample);
        if (!caps)
        {
            printf("could not get snapshot format\n");
        }
        gst_caps_get_structure (caps, 0);
        buffer = gst_sample_get_buffer (sample);
        gst_buffer_map (buffer, &map, GST_MAP_READ);

        //printf("map.size = %lu\n", map.size);
        accumulate_size += map.size;
        accumulate_count ++;
        if (accumulate_count == 30) {
            unsigned int average_rate = (accumulate_size<<3);
            printf("bitrate = %d bps \n", average_rate);
            accumulate_size = accumulate_count = 0;
        }

        gst_buffer_unmap(buffer, &map);

        gst_sample_unref (sample);
    }
    else
    {
        g_print ("could not make snapshot\n");
    }

    return GST_FLOW_OK;
}

int main(int argc, char** argv) {
    USE(argc);
    USE(argv);

    gst_init (&argc, &argv);

    GMainLoop *main_loop;
    main_loop = g_main_loop_new (NULL, FALSE);
    ostringstream launch_stream;
    int w = 1920;
    int h = 1080;
    GstAppSinkCallbacks callbacks = {appsink_eos, NULL, new_buffer};

    launch_stream
    << "videotestsrc is-live=1 ! nvvidconv ! "
    << "video/x-raw(memory:NVMM), width="<< w <<", height="<< h <<", framerate=30/1,format=(string)NV12 ! "
    << "nvv4l2h265enc name=video_enc ! video/x-h265,stream-format=byte-stream ! "
    << "appsink name=mysink ";

    launch_string = launch_stream.str();

    g_print("Using launch string: %s\n", launch_string.c_str());

    GError *error = nullptr;
    gst_pipeline  = (GstPipeline*) gst_parse_launch(launch_string.c_str(), &error);

    if (gst_pipeline == nullptr) {
        g_print( "Failed to parse launch: %s\n", error->message);
        return -1;
    }
    if(error) g_error_free(error);

    GstElement *encoder = gst_bin_get_by_name(GST_BIN(gst_pipeline), "video_enc");
    if(!GST_IS_ELEMENT(encoder)) {
        g_print( "Failed to get encoder from pipeline \n");
        return -1;
    }

    GstElement *appsink_ = gst_bin_get_by_name(GST_BIN(gst_pipeline), "mysink");
    gst_app_sink_set_callbacks (GST_APP_SINK(appsink_), &callbacks, NULL, NULL);

    gst_element_set_state((GstElement*)gst_pipeline, GST_STATE_PLAYING); 
    sleep(5);
    GstFlowReturn ret;
    g_print("signal force-IDR \n");
    g_signal_emit_by_name (G_OBJECT(encoder), "force-IDR", NULL, &ret);
    sleep(10);

    //send EOS
    GstPad *pad = gst_element_get_static_pad(encoder, "sink");
    gst_pad_send_event(pad, gst_event_new_eos());
    gst_object_unref(pad);
    // Wait for EOS message
    GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(gst_pipeline));
    gst_bus_poll(bus, GST_MESSAGE_EOS, GST_CLOCK_TIME_NONE);
    
    gst_element_set_state((GstElement*)gst_pipeline, GST_STATE_NULL);
    gst_object_unref(GST_OBJECT(gst_pipeline));

    g_main_loop_unref(main_loop);

    g_print("going to exit \n");
    return 0;
}

Build command:

$ g++ -Wall -std=c++11  test.cpp -o test $(pkg-config --cflags --libs gstreamer-app-1.0)

Please try it in your setup and see if it can be run successfully.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.