Proper way to stop nvarguscamerasrc and release all resources?

Hi NVIDIA team,

I’m looking for the recommended way to gracefully stop an nvarguscamerasrc pipeline and ensure that all Argus resources are released.

My pipeline is simply:


gst-launch-1.0 nvarguscamerasrc ! \
'video/x-raw(memory:NVMM), width=4000, height=3000, format=NV12, framerate=30/1' ! \
fakesink

In my application, I try to stop the pipeline by sending an EOS event and waiting for the EOS message from the bus before setting the pipeline to GST_STATE_NULL.


void gst_message_handler(GstElement* pipeline, int gst_msg) {
    GstBusPtr bus(gst_element_get_bus(pipeline));

    GstMessagePtr msg(
        gst_bus_timed_pop_filtered(
            bus.get(),
            GST_CLOCK_TIME_NONE,
            static_cast<GstMessageType>(gst_msg)));

    if (msg != nullptr) {
        if (GST_MESSAGE_TYPE(msg.get()) == GST_MESSAGE_EOS) {
            logging("Receive EOS");
            gst_element_set_state(pipeline, GST_STATE_NULL);
        } else if (GST_MESSAGE_TYPE(msg.get()) == GST_MESSAGE_ERROR) {
            GError* err = nullptr;
            gchar* debug_info = nullptr;

            gst_message_parse_error(msg.get(), &err, &debug_info);

            logging("Gst Message Error: {}", err->message);

            g_clear_error(&err);
            g_free(debug_info);
        }
    }
}

auto StopGstThread = std::thread(
    [pipeline = _main_pipeline.get()]() {
        gst_message_handler(pipeline, GST_MESSAGE_EOS);
    });

gst_element_send_event(_main_pipeline.get(), gst_event_new_eos());

if (StopGstThread.joinable()) {
    StopGstThread.join();
}

g_main_loop_quit(_main_loop.get());

However, the EOS message never arrives. The thread blocks forever in:


gst_bus_timed_pop_filtered(..., GST_CLOCK_TIME_NONE, GST_MESSAGE_EOS);

As a result, the pipeline never transitions to GST_STATE_NULL.

My questions are:

  1. Is sending an EOS event the correct way to stop a pipeline using nvarguscamerasrc?
  2. Does nvarguscamerasrc support propagating EOS, or is there a different recommended shutdown sequence?
  3. What is the proper procedure to ensure all camera/Argus resources are released before restarting the pipeline?

Any guidance or example code would be greatly appreciated. Thanks!

hello triconguyen251,

usually, we’ll have -e included in the gst pipeline. with the -e options, it will send an EoS at shutdown.

besides..
you may refer to Argus samples, such as.. Argus/public/samples/userAutoExposure.
in general, here’re the flow of app shutdown process.

     └── Shutdown after requested frame count                                                                                                                     
          ├─ Destroy Request
          ├─ Destroy OutputStreamSettings
          ├─ Destroy EventQueue
          ├─ Destroy CaptureSession                                                                                                                               
          │    └─ Repeating capture stops implicitly
          ├─ Destroy EGL OutputStream                                                                                                                             
          ├─ Stop and join PreviewConsumerThread
          │    ├─ Delete GL program/textures                                                                                                                      
          │    └─ Destroy GL context
          ├─ Destroy CameraProvider  
          ├─ Shut down window                                                  
          └─ Clean up EGL display

Hi @JerryChange ,

I am running pipeline with my Cpp programing with

gst_parse_launch();

and i send EOS then listen when the pipeline catch the EOS event, but it has been never called

void stop_gstreamer() {

gst_element_send_event(\_main_pipeline.get(), gst_event_new_eos());

}

I have add listen to the bus before i start the pipeline, here is my listener

gboolean GstreamerInterface::bus_callback(GstBus *bus, GstMessage *msg) {

switch (GST_MESSAGE_TYPE(*msg*)) {

case GST_MESSAGE_EOS:

logging_DEBUG(“EOS received on bus, quitting main loop.\n”);

if (_main_pipeline) {

g_main_loop_quit(_main_loop.get());

gst_element_set_state(GST_ELEMENT(_main_pipeline.get()), GST_STATE_NULL);

            // main_pipeline is a smart pointer

            // already hasGstElementDeleter => comment unref manual code

            // gst_object_unref(GST_OBJECT(\_main_pipeline.get()));

g_source_remove(bus_watch_id);

_main_pipeline.reset();

_is_pipeline_running.store(false, std::memory_order_relaxed);

logging_INFO(“Main pipeline stopped”);

        }

break;

case GST_MESSAGE_ERROR: {

        GError \*err   = nullptr;

        gchar  \*debug = nullptr;

gst_message_parse_error(msg, &err, &debug);

logging_ERROR(“Error: %s\n”, err->message);

g_error_free(err);

g_free(debug);

        // g_main_loop_quit(\_main_loop.get());

break;

    }

default:

break;

}

return TRUE; // keep watching

}

How to send the EOS to the pipeline and wait until it terminate correctly and completely clear all resource ?

hello triconguyen251,

-e option is a gst-launch-1.0 command-line option; it must not be placed in a gst_parse_launch() string. cpp code should be.. gst_element_send_event(pipeline, gst_event_new_eos());
please see-also similar discussion thread, Topic 176364 for reference.