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>
|
||||
|
||||
* 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_STATIC_CAPS ("application/x-rtp; application/x-rdt"));
|
||||
|
||||
/* template used internally */
|
||||
static GstStaticPadTemplate anytemplate = GST_STATIC_PAD_TEMPLATE ("internal%d",
|
||||
/* templates used internally */
|
||||
static GstStaticPadTemplate anysrctemplate =
|
||||
GST_STATIC_PAD_TEMPLATE ("internalsrc%d",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_SOMETIMES,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static GstStaticPadTemplate anysinktemplate =
|
||||
GST_STATIC_PAD_TEMPLATE ("internalsink%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_SOMETIMES,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
|
@ -1081,6 +1088,40 @@ gst_rtspsrc_handle_src_query (GstPad * pad, GstQuery * query)
|
|||
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
|
||||
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]);
|
||||
} else {
|
||||
GstPadTemplate *template;
|
||||
|
||||
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 */
|
||||
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_query_function (pad0, gst_rtspsrc_handle_src_query);
|
||||
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 we have a sinkpad for the other channel, create a pad and link to the
|
||||
* manager. */
|
||||
pad1 = gst_pad_new_from_template (template, "internal1");
|
||||
pad1 = gst_pad_new_from_template (template, "internalsrc1");
|
||||
gst_pad_link (pad1, stream->channelpad[1]);
|
||||
stream->channelpad[1] = pad1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1500,6 +1558,10 @@ gst_rtspsrc_stream_configure_udp_sink (GstRTSPSrc * src, GstRTSPStream * stream,
|
|||
gint port;
|
||||
gchar *destination, *uri, *name;
|
||||
|
||||
/* no session, we're done */
|
||||
if (src->session == NULL)
|
||||
return TRUE;
|
||||
|
||||
/* get host and port */
|
||||
if (transport->lower_transport == RTSP_LOWER_TRANS_UDP_MCAST)
|
||||
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
|
||||
rtsp_connection_send (RTSPConnection * conn, RTSPMessage * message,
|
||||
GTimeVal * timeout)
|
||||
{
|
||||
GString *str;
|
||||
gint towrite;
|
||||
gchar *data;
|
||||
GString *str = NULL;
|
||||
RTSPResult res;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
WSADATA w;
|
||||
|
@ -305,16 +336,36 @@ rtsp_connection_send (RTSPConnection * conn, RTSPMessage * message,
|
|||
g_string_append_printf (str, "RTSP/1.0 %d %s\r\n",
|
||||
message->type_data.response.code, message->type_data.response.reason);
|
||||
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:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
/* append specific headers and body */
|
||||
switch (message->type) {
|
||||
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);
|
||||
|
||||
|
@ -331,31 +382,23 @@ rtsp_connection_send (RTSPConnection * conn, RTSPMessage * message,
|
|||
/* header ends here */
|
||||
g_string_append (str, "\r\n");
|
||||
str =
|
||||
g_string_append_len (str, (gchar *) message->body, message->body_size);
|
||||
g_string_append_len (str, (gchar *) message->body,
|
||||
message->body_size);
|
||||
} else {
|
||||
/* just end headers */
|
||||
g_string_append (str, "\r\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* write request */
|
||||
towrite = str->len;
|
||||
data = str->str;
|
||||
res = rtsp_connection_write (conn, (guint8 *) str->str, str->len, timeout);
|
||||
|
||||
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);
|
||||
|
||||
return RTSP_OK;
|
||||
return res;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
startup_error:
|
||||
|
@ -371,11 +414,6 @@ version_error:
|
|||
return RTSP_EWSAVERSION;
|
||||
}
|
||||
#endif
|
||||
write_error:
|
||||
{
|
||||
g_string_free (str, TRUE);
|
||||
return RTSP_ESYS;
|
||||
}
|
||||
}
|
||||
|
||||
static RTSPResult
|
||||
|
@ -550,7 +588,7 @@ no_column:
|
|||
}
|
||||
|
||||
RTSPResult
|
||||
rtsp_connection_read (RTSPConnection * conn, gpointer data, guint size,
|
||||
rtsp_connection_read (RTSPConnection * conn, guint8 * data, guint size,
|
||||
GTimeVal * timeout)
|
||||
{
|
||||
fd_set readfds;
|
||||
|
@ -631,7 +669,7 @@ rtsp_connection_read (RTSPConnection * conn, gpointer data, guint size,
|
|||
goto read_error;
|
||||
} else {
|
||||
toread -= bytes;
|
||||
data = (char *) data + bytes;
|
||||
data += bytes;
|
||||
}
|
||||
}
|
||||
return RTSP_OK;
|
||||
|
@ -663,7 +701,7 @@ static RTSPResult
|
|||
read_body (RTSPConnection * conn, glong content_length, RTSPMessage * msg,
|
||||
GTimeVal * timeout)
|
||||
{
|
||||
gchar *body;
|
||||
guint8 *body;
|
||||
RTSPResult res;
|
||||
|
||||
if (content_length <= 0) {
|
||||
|
@ -732,7 +770,8 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg,
|
|||
rtsp_message_init_data (msg, (gint) c);
|
||||
|
||||
/* 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);
|
||||
|
||||
|
|
|
@ -78,10 +78,17 @@ RTSPResult rtsp_connection_connect (RTSPConnection *conn, GTimeVal *timeou
|
|||
RTSPResult rtsp_connection_close (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 */
|
||||
RTSPResult rtsp_connection_send (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);
|
||||
|
||||
/* Configure Authentication data */
|
||||
|
|
Loading…
Reference in a new issue