[ad_1]
Quick summary
video stream crashes if multiple clients connect at the same time due to the clients (all but 1) that skip the media-configure callback trying to change the bitrate by accessing a not yet configured pipeline. I’m asking how to wait with calling change_bitrate
as long as the configure-media
callback hasn’t yet finished.
Detailed overview
I’m developing a door phone application that shows video footage of a user (that just rang the door) over the RTSP protocol on one or multiple screens (called clients from now on) in e.g. an appartment building.
When the application is running, it will not create a pipeline before the first client has connected. A new client callback is created in the following way:
/* Configure Callbacks */
/* Create new client handler (Called on new client connect) */
LOG_debug("Creating 'client-connected' signal handler");
g_signal_connect(info.server, "client-connected", G_CALLBACK(new_client_handler), &info);
Which calls this function as soon as a client has connected:
/**
* new_client_handler
* Called by rtsp server on a new client connection
*/
static void new_client_handler(GstRTSPServer *server, GstRTSPClient *client, struct stream_info *si)
{
DEBUG_ENTER;
/* Used to initiate the media-configure callback */
static gboolean first_run = TRUE;
GstRTSPConnection *connection = gst_rtsp_client_get_connection(client);
if (connection == NULL)
{
LOG_err("Could not get RTSP connection");
DEBUG_EXIT;
return;
}
GstRTSPUrl *url = gst_rtsp_connection_get_url(connection);
if (url == NULL)
{
LOG_err("Could not get RTSP connection URL");
DEBUG_EXIT;
return;
}
si->num_cli++;
gchar* uri = gst_rtsp_url_get_request_uri(url);
LOG_info("[%d]A new client %s has connected", si->num_cli, uri);
g_free(uri);
si->connected = TRUE;
/* Create media-configure handler */
/*relevant part for question*/
if (si->num_cli == 1)
{ /* Initial Setup */
/**
* Stream info is required, which is only
* available on the first connection. Stream info is created
* upon the first connection and is never destroyed after that.
*/
if (first_run == TRUE)
{
LOG_debug("Creating 'media-configure' signal handler");
g_signal_connect(si->factory, "media-configure", G_CALLBACK(media_configure_handler),
si);
}
}
else
{
change_bitrate(si); //This makes video stream crash if 'media_configure_handler' isn't yet finished
}
/* Create new client_close_handler */
LOG_debug("Creating 'closed' signal handler");
g_signal_connect(client, "closed", G_CALLBACK(client_close_handler), si);
first_run = FALSE;
DEBUG_EXIT;
}
When a client is the first one to connect, it sets up the media-configure
callback to initialize the pipeline. The configuration code looks like this:
**
* media_configure_handler
* Setup pipeline when the stream is first configured
*/
static void media_configure_handler(GstRTSPMediaFactory *factory, GstRTSPMedia *media,
struct stream_info *si)
{
DEBUG_ENTER;
si->media = media;
LOG_info("[%d]Configuring pipeline...", si->num_cli);
si->pipeline = GST_BIN(gst_rtsp_media_get_element(media)); //Pipeline gets configured here
setup_elements(si);
if (si->num_cli == 1)
{
/* Create Msg Event Handler */
LOG_debug("Creating 'periodic message' handler");
g_timeout_add(si->msg_rate * 1000, (GSourceFunc) periodic_msg_handler, si);
}
DEBUG_EXIT;
}
A second (or nth) client that connects skips the media configuration step and instead goes to change_bitrate
. Here the bitrate is adjusted based on the amount of connected clients.
/**
* change_bitrate
* handle changing of bitrates
*/
static void change_bitrate(struct stream_info *si)
{
DEBUG_ENTER;
int c = si->curr_bitrate;
int step = (si->max_bitrate - si->min_bitrate) / si->steps;
GstElement *elem = search_pipeline(si->pipeline, "enc"); //crashes due to an unitialized pipeline
const gchar *name = g_ascii_strdown(G_OBJECT_TYPE_NAME(elem), -1);
GstStructure *extra_controls;
...
}
This all works fine if a single client connects first. Later, the connection can handle multiple clients and adjusts the bitrate accordingly.
The problem arises if the first connection is by multiple clients:
In this case, both clients enter an instance of new_client_handler
, in which the first one will set up the media_configure_handler
. The second connection tries to change the bitrate, but fails because the pipeline is not yet configured by the callback.
How can i make the second (and nth) connection wait until the media configure callback has finished and thus a pipeline is available?
[ad_2]