mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-18 15:51:11 +00:00
gst/rtsp/gstrtspsrc.c: Send RTCP messages back to the server over the TCP connection.
Original commit message from CVS: * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_handle_src_event), (gst_rtspsrc_handle_src_query), (gst_rtspsrc_sink_chain), (gst_rtspsrc_stream_configure_manager), (gst_rtspsrc_stream_free_udp), (gst_rtspsrc_stream_configure_tcp), (gst_rtspsrc_stream_configure_mcast), (gst_rtspsrc_stream_configure_udp), (gst_rtspsrc_stream_configure_udp_sink), (gst_rtspsrc_stream_configure_transport): Send RTCP messages back to the server over the TCP connection. * gst/rtsp/rtspconnection.c: (rtsp_connection_write), (rtsp_connection_send), (rtsp_connection_read), (read_body), (rtsp_connection_receive): * gst/rtsp/rtspconnection.h: Factor out and expose lowlevel _write and _read methods. Implement sending data messages to the server.
This commit is contained in:
parent
4d42c097a6
commit
fb80e57990
4 changed files with 183 additions and 56 deletions
19
ChangeLog
19
ChangeLog
|
@ -1,3 +1,22 @@
|
||||||
|
2007-05-04 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_handle_src_event),
|
||||||
|
(gst_rtspsrc_handle_src_query), (gst_rtspsrc_sink_chain),
|
||||||
|
(gst_rtspsrc_stream_configure_manager),
|
||||||
|
(gst_rtspsrc_stream_free_udp), (gst_rtspsrc_stream_configure_tcp),
|
||||||
|
(gst_rtspsrc_stream_configure_mcast),
|
||||||
|
(gst_rtspsrc_stream_configure_udp),
|
||||||
|
(gst_rtspsrc_stream_configure_udp_sink),
|
||||||
|
(gst_rtspsrc_stream_configure_transport):
|
||||||
|
Send RTCP messages back to the server over the TCP connection.
|
||||||
|
|
||||||
|
* gst/rtsp/rtspconnection.c: (rtsp_connection_write),
|
||||||
|
(rtsp_connection_send), (rtsp_connection_read), (read_body),
|
||||||
|
(rtsp_connection_receive):
|
||||||
|
* gst/rtsp/rtspconnection.h:
|
||||||
|
Factor out and expose lowlevel _write and _read methods.
|
||||||
|
Implement sending data messages to the server.
|
||||||
|
|
||||||
2007-05-03 Wim Taymans <wim@fluendo.com>
|
2007-05-03 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* gst/multipart/multipartmux.c: (gst_multipart_mux_queue_pads),
|
* gst/multipart/multipartmux.c: (gst_multipart_mux_queue_pads),
|
||||||
|
|
|
@ -120,12 +120,19 @@ static GstStaticPadTemplate rtptemplate = GST_STATIC_PAD_TEMPLATE ("stream%d",
|
||||||
GST_PAD_SOMETIMES,
|
GST_PAD_SOMETIMES,
|
||||||
GST_STATIC_CAPS ("application/x-rtp; application/x-rdt"));
|
GST_STATIC_CAPS ("application/x-rtp; application/x-rdt"));
|
||||||
|
|
||||||
/* template used internally */
|
/* templates used internally */
|
||||||
static GstStaticPadTemplate anytemplate = GST_STATIC_PAD_TEMPLATE ("internal%d",
|
static GstStaticPadTemplate anysrctemplate =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("internalsrc%d",
|
||||||
GST_PAD_SRC,
|
GST_PAD_SRC,
|
||||||
GST_PAD_SOMETIMES,
|
GST_PAD_SOMETIMES,
|
||||||
GST_STATIC_CAPS_ANY);
|
GST_STATIC_CAPS_ANY);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate anysinktemplate =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("internalsink%d",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_SOMETIMES,
|
||||||
|
GST_STATIC_CAPS_ANY);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
/* FILL ME */
|
/* FILL ME */
|
||||||
|
@ -1081,6 +1088,40 @@ gst_rtspsrc_handle_src_query (GstPad * pad, GstQuery * query)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* callback for RTCP messages to be sent to the server when operating in TCP
|
||||||
|
* mode. */
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_rtspsrc_sink_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstRTSPSrc *src;
|
||||||
|
GstRTSPStream *stream;
|
||||||
|
GstFlowReturn res = GST_FLOW_OK;
|
||||||
|
guint8 *data;
|
||||||
|
guint size;
|
||||||
|
RTSPResult ret;
|
||||||
|
RTSPMessage message = { 0 };
|
||||||
|
|
||||||
|
stream = (GstRTSPStream *) gst_pad_get_element_private (pad);
|
||||||
|
src = stream->parent;
|
||||||
|
|
||||||
|
data = GST_BUFFER_DATA (buffer);
|
||||||
|
size = GST_BUFFER_SIZE (buffer);
|
||||||
|
|
||||||
|
rtsp_message_init_data (&message, stream->channel[1]);
|
||||||
|
|
||||||
|
rtsp_message_take_body (&message, data, size);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (src, "sending %u bytes RTCP", size);
|
||||||
|
ret = rtsp_connection_send (src->connection, &message, NULL);
|
||||||
|
GST_DEBUG_OBJECT (src, "sent RTCP, %d", ret);
|
||||||
|
|
||||||
|
rtsp_message_steal_body (&message, &data, &size);
|
||||||
|
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pad_unblocked (GstPad * pad, gboolean blocked, GstRTSPSrc * src)
|
pad_unblocked (GstPad * pad, gboolean blocked, GstRTSPSrc * src)
|
||||||
{
|
{
|
||||||
|
@ -1350,14 +1391,12 @@ gst_rtspsrc_stream_configure_tcp (GstRTSPSrc * src, GstRTSPStream * stream,
|
||||||
|
|
||||||
*outpad = gst_object_ref (stream->channelpad[0]);
|
*outpad = gst_object_ref (stream->channelpad[0]);
|
||||||
} else {
|
} else {
|
||||||
GstPadTemplate *template;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src, "using manager source pad");
|
GST_DEBUG_OBJECT (src, "using manager source pad");
|
||||||
|
|
||||||
template = gst_static_pad_template_get (&anytemplate);
|
template = gst_static_pad_template_get (&anysrctemplate);
|
||||||
|
|
||||||
/* allocate pads for sending the channel data into the manager */
|
/* allocate pads for sending the channel data into the manager */
|
||||||
pad0 = gst_pad_new_from_template (template, "internal0");
|
pad0 = gst_pad_new_from_template (template, "internalsrc0");
|
||||||
gst_pad_set_event_function (pad0, gst_rtspsrc_handle_src_event);
|
gst_pad_set_event_function (pad0, gst_rtspsrc_handle_src_event);
|
||||||
gst_pad_set_query_function (pad0, gst_rtspsrc_handle_src_query);
|
gst_pad_set_query_function (pad0, gst_rtspsrc_handle_src_query);
|
||||||
gst_pad_link (pad0, stream->channelpad[0]);
|
gst_pad_link (pad0, stream->channelpad[0]);
|
||||||
|
@ -1367,12 +1406,31 @@ gst_rtspsrc_stream_configure_tcp (GstRTSPSrc * src, GstRTSPStream * stream,
|
||||||
if (stream->channelpad[1]) {
|
if (stream->channelpad[1]) {
|
||||||
/* if we have a sinkpad for the other channel, create a pad and link to the
|
/* if we have a sinkpad for the other channel, create a pad and link to the
|
||||||
* manager. */
|
* manager. */
|
||||||
pad1 = gst_pad_new_from_template (template, "internal1");
|
pad1 = gst_pad_new_from_template (template, "internalsrc1");
|
||||||
gst_pad_link (pad1, stream->channelpad[1]);
|
gst_pad_link (pad1, stream->channelpad[1]);
|
||||||
stream->channelpad[1] = pad1;
|
stream->channelpad[1] = pad1;
|
||||||
}
|
}
|
||||||
gst_object_unref (template);
|
gst_object_unref (template);
|
||||||
}
|
}
|
||||||
|
/* setup RTCP transport back to the server */
|
||||||
|
if (src->session) {
|
||||||
|
GstPad *pad;
|
||||||
|
|
||||||
|
template = gst_static_pad_template_get (&anysinktemplate);
|
||||||
|
|
||||||
|
stream->rtcppad = gst_pad_new_from_template (template, "internalsink0");
|
||||||
|
gst_pad_set_chain_function (stream->rtcppad, gst_rtspsrc_sink_chain);
|
||||||
|
gst_pad_set_element_private (stream->rtcppad, stream);
|
||||||
|
gst_pad_set_active (stream->rtcppad, TRUE);
|
||||||
|
|
||||||
|
/* get session RTCP pad */
|
||||||
|
name = g_strdup_printf ("send_rtcp_src_%d", stream->id);
|
||||||
|
pad = gst_element_get_request_pad (src->session, name);
|
||||||
|
g_free (name);
|
||||||
|
|
||||||
|
/* and link */
|
||||||
|
gst_pad_link (pad, stream->rtcppad);
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1500,6 +1558,10 @@ gst_rtspsrc_stream_configure_udp_sink (GstRTSPSrc * src, GstRTSPStream * stream,
|
||||||
gint port;
|
gint port;
|
||||||
gchar *destination, *uri, *name;
|
gchar *destination, *uri, *name;
|
||||||
|
|
||||||
|
/* no session, we're done */
|
||||||
|
if (src->session == NULL)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
/* get host and port */
|
/* get host and port */
|
||||||
if (transport->lower_transport == RTSP_LOWER_TRANS_UDP_MCAST)
|
if (transport->lower_transport == RTSP_LOWER_TRANS_UDP_MCAST)
|
||||||
port = transport->port.max;
|
port = transport->port.max;
|
||||||
|
|
|
@ -264,13 +264,44 @@ append_auth_header (RTSPConnection * conn, RTSPMessage * message, GString * str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RTSPResult
|
||||||
|
rtsp_connection_write (RTSPConnection * conn, const guint8 * data, guint size,
|
||||||
|
GTimeVal * timeout)
|
||||||
|
{
|
||||||
|
guint towrite;
|
||||||
|
|
||||||
|
g_return_val_if_fail (conn != NULL, RTSP_EINVAL);
|
||||||
|
g_return_val_if_fail (data != NULL || size == 0, RTSP_EINVAL);
|
||||||
|
|
||||||
|
towrite = size;
|
||||||
|
|
||||||
|
while (towrite > 0) {
|
||||||
|
gint written;
|
||||||
|
|
||||||
|
written = write (conn->fd, data, towrite);
|
||||||
|
if (written < 0) {
|
||||||
|
if (errno != EAGAIN && errno != EINTR)
|
||||||
|
goto write_error;
|
||||||
|
} else {
|
||||||
|
towrite -= written;
|
||||||
|
data += written;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return RTSP_OK;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
write_error:
|
||||||
|
{
|
||||||
|
return RTSP_ESYS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RTSPResult
|
RTSPResult
|
||||||
rtsp_connection_send (RTSPConnection * conn, RTSPMessage * message,
|
rtsp_connection_send (RTSPConnection * conn, RTSPMessage * message,
|
||||||
GTimeVal * timeout)
|
GTimeVal * timeout)
|
||||||
{
|
{
|
||||||
GString *str;
|
GString *str = NULL;
|
||||||
gint towrite;
|
RTSPResult res;
|
||||||
gchar *data;
|
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
WSADATA w;
|
WSADATA w;
|
||||||
|
@ -305,57 +336,69 @@ rtsp_connection_send (RTSPConnection * conn, RTSPMessage * message,
|
||||||
g_string_append_printf (str, "RTSP/1.0 %d %s\r\n",
|
g_string_append_printf (str, "RTSP/1.0 %d %s\r\n",
|
||||||
message->type_data.response.code, message->type_data.response.reason);
|
message->type_data.response.code, message->type_data.response.reason);
|
||||||
break;
|
break;
|
||||||
|
case RTSP_MESSAGE_DATA:
|
||||||
|
{
|
||||||
|
guint8 data_header[4];
|
||||||
|
|
||||||
|
/* prepare data header */
|
||||||
|
data_header[0] = '$';
|
||||||
|
data_header[1] = message->type_data.data.channel;
|
||||||
|
data_header[2] = (message->body_size >> 8) & 0xff;
|
||||||
|
data_header[3] = message->body_size & 0xff;
|
||||||
|
|
||||||
|
/* create string with header and data */
|
||||||
|
str = g_string_append_len (str, (gchar *) data_header, 4);
|
||||||
|
str =
|
||||||
|
g_string_append_len (str, (gchar *) message->body,
|
||||||
|
message->body_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* append session id if we have one */
|
/* append specific headers and body */
|
||||||
if (conn->session_id[0] != '\0') {
|
switch (message->type) {
|
||||||
append_header (RTSP_HDR_SESSION, conn->session_id, str);
|
case RTSP_MESSAGE_REQUEST:
|
||||||
}
|
case RTSP_MESSAGE_RESPONSE:
|
||||||
|
/* append session id if we have one */
|
||||||
|
if (conn->session_id[0] != '\0') {
|
||||||
|
append_header (RTSP_HDR_SESSION, conn->session_id, str);
|
||||||
|
}
|
||||||
|
/* append headers */
|
||||||
|
g_hash_table_foreach (message->hdr_fields, (GHFunc) append_header, str);
|
||||||
|
|
||||||
/* append headers */
|
/* Append any authentication headers */
|
||||||
g_hash_table_foreach (message->hdr_fields, (GHFunc) append_header, str);
|
append_auth_header (conn, message, str);
|
||||||
|
|
||||||
/* Append any authentication headers */
|
/* append Content-Length and body if needed */
|
||||||
append_auth_header (conn, message, str);
|
if (message->body != NULL && message->body_size > 0) {
|
||||||
|
gchar *len;
|
||||||
|
|
||||||
/* append Content-Length and body if needed */
|
len = g_strdup_printf ("%d", message->body_size);
|
||||||
if (message->body != NULL && message->body_size > 0) {
|
append_header (RTSP_HDR_CONTENT_LENGTH, len, str);
|
||||||
gchar *len;
|
g_free (len);
|
||||||
|
/* header ends here */
|
||||||
len = g_strdup_printf ("%d", message->body_size);
|
g_string_append (str, "\r\n");
|
||||||
append_header (RTSP_HDR_CONTENT_LENGTH, len, str);
|
str =
|
||||||
g_free (len);
|
g_string_append_len (str, (gchar *) message->body,
|
||||||
/* header ends here */
|
message->body_size);
|
||||||
g_string_append (str, "\r\n");
|
} else {
|
||||||
str =
|
/* just end headers */
|
||||||
g_string_append_len (str, (gchar *) message->body, message->body_size);
|
g_string_append (str, "\r\n");
|
||||||
} else {
|
}
|
||||||
/* just end headers */
|
break;
|
||||||
g_string_append (str, "\r\n");
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write request */
|
/* write request */
|
||||||
towrite = str->len;
|
res = rtsp_connection_write (conn, (guint8 *) str->str, str->len, timeout);
|
||||||
data = str->str;
|
|
||||||
|
|
||||||
while (towrite > 0) {
|
|
||||||
gint written;
|
|
||||||
|
|
||||||
written = write (conn->fd, data, towrite);
|
|
||||||
if (written < 0) {
|
|
||||||
if (errno != EAGAIN && errno != EINTR)
|
|
||||||
goto write_error;
|
|
||||||
} else {
|
|
||||||
towrite -= written;
|
|
||||||
data += written;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_string_free (str, TRUE);
|
g_string_free (str, TRUE);
|
||||||
|
|
||||||
return RTSP_OK;
|
return res;
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
startup_error:
|
startup_error:
|
||||||
|
@ -371,11 +414,6 @@ version_error:
|
||||||
return RTSP_EWSAVERSION;
|
return RTSP_EWSAVERSION;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
write_error:
|
|
||||||
{
|
|
||||||
g_string_free (str, TRUE);
|
|
||||||
return RTSP_ESYS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RTSPResult
|
static RTSPResult
|
||||||
|
@ -550,7 +588,7 @@ no_column:
|
||||||
}
|
}
|
||||||
|
|
||||||
RTSPResult
|
RTSPResult
|
||||||
rtsp_connection_read (RTSPConnection * conn, gpointer data, guint size,
|
rtsp_connection_read (RTSPConnection * conn, guint8 * data, guint size,
|
||||||
GTimeVal * timeout)
|
GTimeVal * timeout)
|
||||||
{
|
{
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
|
@ -631,7 +669,7 @@ rtsp_connection_read (RTSPConnection * conn, gpointer data, guint size,
|
||||||
goto read_error;
|
goto read_error;
|
||||||
} else {
|
} else {
|
||||||
toread -= bytes;
|
toread -= bytes;
|
||||||
data = (char *) data + bytes;
|
data += bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return RTSP_OK;
|
return RTSP_OK;
|
||||||
|
@ -663,7 +701,7 @@ static RTSPResult
|
||||||
read_body (RTSPConnection * conn, glong content_length, RTSPMessage * msg,
|
read_body (RTSPConnection * conn, glong content_length, RTSPMessage * msg,
|
||||||
GTimeVal * timeout)
|
GTimeVal * timeout)
|
||||||
{
|
{
|
||||||
gchar *body;
|
guint8 *body;
|
||||||
RTSPResult res;
|
RTSPResult res;
|
||||||
|
|
||||||
if (content_length <= 0) {
|
if (content_length <= 0) {
|
||||||
|
@ -732,7 +770,8 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg,
|
||||||
rtsp_message_init_data (msg, (gint) c);
|
rtsp_message_init_data (msg, (gint) c);
|
||||||
|
|
||||||
/* next two bytes are the length of the data */
|
/* next two bytes are the length of the data */
|
||||||
RTSP_CHECK (rtsp_connection_read (conn, &size, 2, timeout), read_error);
|
RTSP_CHECK (rtsp_connection_read (conn, (guint8 *) & size, 2, timeout),
|
||||||
|
read_error);
|
||||||
|
|
||||||
size = GUINT16_FROM_BE (size);
|
size = GUINT16_FROM_BE (size);
|
||||||
|
|
||||||
|
|
|
@ -78,10 +78,17 @@ RTSPResult rtsp_connection_connect (RTSPConnection *conn, GTimeVal *timeou
|
||||||
RTSPResult rtsp_connection_close (RTSPConnection *conn);
|
RTSPResult rtsp_connection_close (RTSPConnection *conn);
|
||||||
RTSPResult rtsp_connection_free (RTSPConnection *conn);
|
RTSPResult rtsp_connection_free (RTSPConnection *conn);
|
||||||
|
|
||||||
|
/* sending/receiving raw bytes */
|
||||||
|
RTSPResult rtsp_connection_read (RTSPConnection * conn, guint8 * data,
|
||||||
|
guint size, GTimeVal * timeout);
|
||||||
|
RTSPResult rtsp_connection_write (RTSPConnection * conn, const guint8 * data,
|
||||||
|
guint size, GTimeVal * timeout);
|
||||||
|
|
||||||
/* sending/receiving messages */
|
/* sending/receiving messages */
|
||||||
RTSPResult rtsp_connection_send (RTSPConnection *conn, RTSPMessage *message, GTimeVal *timeout);
|
RTSPResult rtsp_connection_send (RTSPConnection *conn, RTSPMessage *message, GTimeVal *timeout);
|
||||||
RTSPResult rtsp_connection_receive (RTSPConnection *conn, RTSPMessage *message, GTimeVal *timeout);
|
RTSPResult rtsp_connection_receive (RTSPConnection *conn, RTSPMessage *message, GTimeVal *timeout);
|
||||||
|
|
||||||
|
/* flushing state */
|
||||||
RTSPResult rtsp_connection_flush (RTSPConnection *conn, gboolean flush);
|
RTSPResult rtsp_connection_flush (RTSPConnection *conn, gboolean flush);
|
||||||
|
|
||||||
/* Configure Authentication data */
|
/* Configure Authentication data */
|
||||||
|
|
Loading…
Reference in a new issue