Gstreamer pipeline signal for rtspclientsink

1

I've been using gstreamer for a while - I am impressed how well it works. But recently a requirement has surfaced to examine a content of RTSP requests and responses. I was thinking that I could use handle-request callback feature of rtspclientsink - correct me if I am wrong. But I have been unable to get the callback working at all. Here is the code example I've been playing with. Any ideas?

static void handle_request_callback (GstElement  rtsp_client_sink,
                         gpointer  request,
                         gpointer  response,
                         gpointer  udata)
{
    printf("here\n\r");
}

int main (int   argc,   char *argv[])
{
    GMainLoop *loop;
    GstElement *pipeline, *videosrc, *sink, *videofilter, *videoencoder, *encoderfilter, *h264parse;
    GstCaps *filtercaps;
    GstPad *pad;

    /* init GStreamer */
    gst_init (&argc, &argv);
    loop = g_main_loop_new (NULL, FALSE);

    /* build */
    pipeline = gst_pipeline_new ("my-pipeline");
    videosrc = gst_element_factory_make ("v4l2src", "videosrc");
    if (videosrc == NULL)
        g_error ("Could not create 'v4l2src' element");

    videofilter = gst_element_factory_make ("capsfilter", "videofilter");
    g_assert (videofilter != NULL); /* should always exist */

    encoderfilter = gst_element_factory_make ("capsfilter", "encoderfilter");
    g_assert (encoderfilter != NULL); /* should always exist */

    h264parse = gst_element_factory_make ("h264parse", "parser");
    if (h264parse == NULL)
        g_error ("Could not create 'h264parse' element");

    videoencoder = gst_element_factory_make ("omxh264enc", "videoencoder");
    if (videoencoder == NULL)
        g_error ("Could not create 'omxh264enc' element");

    sink = gst_element_factory_make ("rtspclientsink", "sink");
    if (sink == NULL)
        g_error ("Could not create 'rtspclientsink' element");


    g_object_set(G_OBJECT(sink), "protocols", 0x00000004, NULL);
    g_object_set(G_OBJECT(sink), "latency", "100", NULL);
    g_object_set(G_OBJECT(sink), "location", "rtspt://192.169.1.2:1935/video", NULL);
    g_object_set(G_OBJECT(sink), "name", "rtspsink", NULL);
    //g_object_set(G_OBJECT(sink), "debug", true, NULL);


    gst_bin_add_many (GST_BIN (pipeline), videosrc, videofilter, videoencoder, h264parse, sink, NULL);
    gst_element_link_many (videosrc, videofilter, videoencoder, h264parse, sink, NULL);
    filtercaps = gst_caps_new_simple ("video/x-raw",
           "width", G_TYPE_INT, 1280,
           "height", G_TYPE_INT, 720,
           "framerate", GST_TYPE_FRACTION, 30, 1,
           NULL);
    g_object_set (G_OBJECT (videofilter), "caps", filtercaps, NULL);
    gst_caps_unref (filtercaps);

    filtercaps = gst_caps_new_simple ("video/x-h264",
           "width", G_TYPE_INT, 1280,
           "height", G_TYPE_INT, 720,
           "framerate", GST_TYPE_FRACTION, 30, 1,
           "profile", G_TYPE_STRING, "high",
           NULL);
    g_object_set (G_OBJECT (encoderfilter), "caps", filtercaps, NULL);
    gst_caps_unref (filtercaps);    

    gulong ret = g_signal_connect(sink, "handle-request", G_CALLBACK(handle_request_callback), sink);
    printf("%d\r\n", ret);

    /* run */
    gst_element_set_state (pipeline, GST_STATE_PLAYING);

    /* wait until it's up and running or failed */
    if (gst_element_get_state (pipeline, NULL, NULL, -1) == GST_STATE_CHANGE_FAILURE) {
        g_error ("Failed to go into PLAYING state");
    }

    g_print ("Running ...\n");
    g_main_loop_run (loop);

    /* exit */
    gst_element_set_state (pipeline, GST_STATE_NULL);
    gst_object_unref (pipeline);

    return 0;
}

here is rtspclientsink information:

$ gst-inspect-1.0 rtspclientsink 
Factory Details:
  Rank                     none (0)
  Long-name                RTSP RECORD client
  Klass                    Sink/Network
  Description              Send data over the network via RTSP RECORD(RFC 2326)
  Author                   Jan Schmidt <jan@centricular.com>

Plugin Details:
  Name                     rtspclientsink
  Description              RTSP client sink element
  Filename                 /usr/lib/arm-linux-gnueabihf/gstreamer-1.0/libgstrtspclientsink.so
  Version                  1.14.4
  License                  LGPL
  Source module            gst-rtsp-server
  Source release date      2018-10-02
  Binary package           GStreamer RTSP Server Library source release
  Origin URL               Unknown package origin
callback
gstreamer
asked on Stack Overflow Feb 20, 2020 by PeterR

1 Answer

0

I've figured it out by looking the gstrtspclientsink.c file (https://github.com/GStreamer/gst-rtsp-server/blob/master/tests/check/gst/rtspclientsink.c). The signal emit function for handle-request is called from a part of the code meant to work as rtsp server while rtspclientsink is a RTSP client that starts by sending ANNOUNCE + sdp (instead of DESCRIBE).

Basically rtspclientsink "handle-request" signal only works for requests originated from server. In the context of RTSP ANNOUNCE where initial request is generated on a device producing media content that signal will never be triggered.

Anyway - g_signal_emit() for "handle-request" like signal could be added to pre and post processing logic of RTSP commands to allow to manipulate RTSP requests and monitor RTSP responses.

answered on Stack Overflow Feb 21, 2020 by PeterR • edited Feb 23, 2020 by Community

User contributions licensed under CC BY-SA 3.0