How to handle camera disconnect?

I am using this pipeline:

launch_stream
    << "rtspsrc location=" << camera_url << " ! "
    << "decodebin ! "
    << "nvvidconv ! "
    << "video/x-raw, format=I420 ! "
    //<< "autovideoconvert ! video/x-raw,format=RGB ! "
    << "appsink name=mysink ";

My code is largely based on test2.cpp sample referenced here.

Upon camera disconnect, the appsink eos callback is fired.
I am trying to repeatedly set the pipeline status to NULL and then to PLAYBACK until state change success is received.

Is there a standard way of dealing with camera disconnects?

Thanks

This is my restart code:

void restart_thread()
{
        int count = 0;

        while(true) {
                if(count++ % 20 == 0){
                        sleep(1);
                        gst_element_set_state((GstElement*)gst_pipeline, GST_STATE_NULL);
                        sleep(1);
                        gst_element_set_state((GstElement*)gst_pipeline, GST_STATE_PLAYING);
                }

                GstStateChangeReturn ret = gst_element_get_state((GstElement*)gst_pipeline, nullptr,
                                nullptr, GST_CLOCK_TIME_NONE);

                if(ret == GST_STATE_CHANGE_SUCCESS)
                {
                        std::cout << "restart state change success." << std::endl;
                        eos = 0;
                        break;
                }
                else if(ret == GST_STATE_CHANGE_FAILURE)
                {
                        std::cout << count << " restart state change failure." << std::endl;
                        //end_capture();
                        //exit(0);
                }
                else
                {
                        std::cout << count << " unidentified state = "<< ret << std::endl;
                }
        }

}

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

    delete restart_handle;
    restart_handle = new std::thread{restart_thread};
    restart_handle->detach();
}

Output when camera is disconnected:

app sink received eos
1 restart state change failure.
2 restart state change failure.
3 restart state change failure.
...
...

When camera comes back, the program just hangs with no output and no progress.


Hi,
Please try to send EOS and do polling before switching to GST_STATE_NULL:

GstElement* src = gst_bin_get_by_name(GST_BIN(gst_pipeline), "mysource");
gst_element_send_event (src, gst_event_new_eos ());
// 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);

Similar code is in
https://devtalk.nvidia.com/default/topic/1058020/jetson-tx2/gstreamer-freeze-when-using-qtmux-and-nvidia-accelerated-h264-h265-encoding/post/5368623/#5368623

Hi,

Thank you for the response.
In the code below, I use ping to wait for the disconnected camera to come back and then switch the pipeline to PLAYING. This goes fine. The camera comes back and the pipeline switches into PLAYING mode successfully. But I see no streaming. The new_buffer callback is not occuring.

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

    delete restart_handle;
    restart_handle = new std::thread{restart_thread};
    restart_handle->detach();
}

void restart_thread()
{
        wait_for_camera_ON( ip_from_url(g_camera_url));
        std::cout << "camera back ON." << std::endl;
        sleep(40);
        std::cout << "setting pipeline to PLAYING" << std::endl;

        eos = 1;
        gst_element_set_state((GstElement*)gst_pipeline, GST_STATE_PLAYING);

        while(eos != 0)
        {
                GstStateChangeReturn ret = gst_element_get_state((GstElement*)gst_pipeline, nullptr,
                                nullptr, GST_CLOCK_TIME_NONE);

                if(ret == GST_STATE_CHANGE_SUCCESS)
                {
                        std::cout << "state change success." << std::endl;
                        eos = 0;
                        break;
                }
                else if(ret == GST_STATE_CHANGE_FAILURE)
                {
                        std::cout << "state change failure.. stopping" << std::endl;
                        //end_capture();
                        exit(0);
                }
                else
                {
                        std::cout << "Intermediate return code.. waiting 5 more secs.." << std::endl;
                        sleep(5);
                }
        }

}

This is the output:

Using launch string: rtspsrc location=rtsp://admin:mercury_123@192.168.1.23:554/Streaming/Channels/101 ! decodebin ! nvvidconv ! video/x-raw, format=I420 ! appsink name=mysink 
nvbuf_utils: Could not get EGL display connection
Opening in BLOCKING MODE 
NvMMLiteOpen : Block : BlockType = 261 
NVMEDIA: Reading vendor.tegra.display-size : status: 6 
NvMMLiteBlockCreate : Block : BlockType = 261 
PID=12176 frames#25 stats=0 FPS : 33 MB : 0 %
PID=12176 frames#50 stats=25 FPS : 33 MB : 9 %
PID=12176 frames#75 stats=24 FPS : 33 MB : 9 %
PID=12176 frames#100 stats=24 FPS : 34 MB : 9 %
PID=12176 frames#125 stats=24 FPS : 34 MB : 9 %
PID=12176 frames#150 stats=25 FPS : 34 MB : 9 %
PID=12176 frames#175 stats=25 FPS : 34 MB : 8 %
PID=12176 frames#200 stats=0 FPS : 32 MB : 0 %
app sink received eos
waiting on camera:192.168.1.23
camera back ON.
setting pipeline to PLAYING
state change success.
(--- long wait without any output here --- )
^C

I am not setting the pipeline to NULL in the modified logic.
Do you have any suggestions here?

Thank you.

Hi,
Please check if you also observe the issue while using software decoder:

launch_stream
    << "rtspsrc location=" << camera_url << " ! "
    << "rtph264depay ! "
    << "h264parse ! "
    << "avdec_h264 ! "
    << "video/x-raw, format=I420 ! "
    << "appsink name=mysink ";

Would like to clarify if it is specific to NVIDIA hardware decoder plugins.

Hi,

Thank you for the response.
I used the pipeline you suggested and the same situation is found.

Using launch string: rtspsrc location=rtsp://admin:mercury_123@192.168.1.23:554/Streaming/Channels/101 ! rtph264depay ! h264parse ! avdec_h264 ! video/x-raw, format=I420 ! appsink name=mysink 
PID=14518 frames#25 stats=0 FPS : 61 MB : 0 %
PID=14518 frames#50 stats=25 FPS : 61 MB : 16 %
PID=14518 frames#75 stats=24 FPS : 61 MB : 18 %
PID=14518 frames#100 stats=24 FPS : 61 MB : 14 %
PID=14518 frames#125 stats=25 FPS : 61 MB : 18 %
app sink received eos
waiting on camera:192.168.1.23
camera back ON.
setting pipeline to PLAYING
state change success.
(--- long wait without any output here --- )
^C

Hi,
It is more like an issue in application programming. Please go to gstreamer forum:
http://gstreamer-devel.966125.n4.nabble.com/

Users in the forum is more experienced in various gstreamer usecases.
Once you get it working with avdec_h264, it should work fine to replace it with nvv4l2decoder.

Thank you for your support so far.

Camera disconnects are common that Nvidia samples should have a way for dealing with them.

Hi,
The sample is from me and I may lack of experience about this usecase. Would be great if you can get support from gstreamer forum and share the solution here. To help me learn from your experience. Thank you.

I solved this by closing the pipeline and going for initializing gstreamer and parse launch the pipeline from scratch. That’s how it works fine.