diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2006-09-18 17:37:46 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2006-09-18 17:37:46 +0000 |
commit | a437e9f0edd49646c2fe36162f77575e219b7efa (patch) | |
tree | b028fe57793da3d6545d3892021dc08c0a790b13 /gst | |
parent | ee58147b3d3f135f7a1c8c80f38bd2b5767d524f (diff) |
gst/rtsp/gstrtspsrc.*: Small cleanups, added documentation.
Original commit message from CVS:
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_media_to_caps),
(gst_rtspsrc_send), (gst_rtspsrc_parse_methods),
(gst_rtspsrc_open), (gst_rtspsrc_close), (gst_rtspsrc_play),
(gst_rtspsrc_pause), (gst_rtspsrc_change_state),
(gst_rtspsrc_uri_get_uri), (gst_rtspsrc_uri_set_uri):
* gst/rtsp/gstrtspsrc.h:
Small cleanups, added documentation.
Try to clean up the requests and responses.
Refactor parsing the supported methods.
* gst/rtsp/rtspconnection.c: (rtsp_connection_open),
(rtsp_connection_create), (rtsp_connection_send),
(parse_response_status), (parse_request_line),
(rtsp_connection_receive), (rtsp_connection_close),
(rtsp_connection_free):
* gst/rtsp/rtsptransport.c: (rtsp_transport_new),
(rtsp_transport_init), (rtsp_transport_parse),
(rtsp_transport_free):
* gst/rtsp/rtspurl.c: (rtsp_url_parse):
* gst/rtsp/sdpmessage.c: (sdp_message_new), (sdp_message_init),
(sdp_message_clean), (sdp_message_free), (sdp_media_new),
(sdp_media_init), (sdp_message_parse_buffer), (sdp_message_dump):
Use g_return_val some more.
* gst/rtsp/rtspdefs.h:
Add more enum values to track initial states.
* gst/rtsp/rtspmessage.c: (rtsp_message_new_request),
(rtsp_message_init_request), (rtsp_message_new_response),
(rtsp_message_init_response), (rtsp_message_init_data),
(rtsp_message_unset), (rtsp_message_free),
(rtsp_message_add_header), (rtsp_message_remove_header),
(rtsp_message_get_header), (rtsp_message_set_body),
(rtsp_message_take_body), (rtsp_message_get_body),
(rtsp_message_steal_body), (rtsp_message_dump):
* gst/rtsp/rtspmessage.h:
Reorder arguments, object goes as the first one.
Use g_return_val some more.
Diffstat (limited to 'gst')
-rw-r--r-- | gst/rtsp/gstrtspsrc.c | 505 | ||||
-rw-r--r-- | gst/rtsp/gstrtspsrc.h | 4 | ||||
-rw-r--r-- | gst/rtsp/rtspconnection.c | 26 | ||||
-rw-r--r-- | gst/rtsp/rtspdefs.h | 3 | ||||
-rw-r--r-- | gst/rtsp/rtspmessage.c | 132 | ||||
-rw-r--r-- | gst/rtsp/rtspmessage.h | 16 | ||||
-rw-r--r-- | gst/rtsp/rtsptransport.c | 11 | ||||
-rw-r--r-- | gst/rtsp/rtspurl.c | 6 | ||||
-rw-r--r-- | gst/rtsp/sdpmessage.c | 29 |
9 files changed, 426 insertions, 306 deletions
diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c index 1353852c..3bc87932 100644 --- a/gst/rtsp/gstrtspsrc.c +++ b/gst/rtsp/gstrtspsrc.c @@ -354,6 +354,10 @@ G_STMT_START { \ while (*p && g_ascii_isspace (*p)) \ p++; +/* rtpmap contains: + * + * <payload> <encoding_name>/<clock_rate>[/<encoding_params>] + */ static gboolean gst_rtspsrc_parse_rtpmap (gchar * rtpmap, gint * payload, gchar ** name, gint * rate, gchar ** params) @@ -413,10 +417,9 @@ gst_rtspsrc_media_to_caps (SDPMedia * media) GstStructure *s; payload = sdp_media_get_format (media, 0); - if (payload == NULL) { - g_warning ("payload type not given"); - return NULL; - } + if (payload == NULL) + goto no_payload; + pt = atoi (payload); /* dynamic payloads need rtpmap */ @@ -428,18 +431,18 @@ gst_rtspsrc_media_to_caps (SDPMedia * media) ret = gst_rtspsrc_parse_rtpmap (rtpmap, &payload, &name, &rate, ¶ms); if (ret) { if (payload != pt) { + /* FIXME, not fatal? */ g_warning ("rtpmap of wrong payload type"); name = NULL; rate = -1; params = NULL; } } else { + /* FIXME, not fatal? */ g_warning ("error parsing rtpmap"); } - } else { - g_warning ("rtpmap type not given for dynamic payload %d", pt); - return NULL; - } + } else + goto no_rtpmap; } caps = gst_caps_new_simple ("application/x-rtp", @@ -494,6 +497,18 @@ gst_rtspsrc_media_to_caps (SDPMedia * media) } } return caps; + + /* ERRORS */ +no_payload: + { + g_warning ("payload type not given"); + return NULL; + } +no_rtpmap: + { + g_warning ("rtpmap type not given for dynamic payload %d", pt); + return NULL; + } } static gboolean @@ -948,29 +963,48 @@ need_pause: } } +/** + * gst_rtspsrc_send: + * @src: the rtsp source + * @request: must point to a valid request + * @response: must point to an empty #RTSPMessage + * + * send @request and retrieve the response in @response. optionally @code can be + * non-NULL in which case it will contain the status code of the response. + * + * If This function returns TRUE, @response will contain a valid response + * message that should be cleaned with rtsp_message_unset() after usage. + * + * If @code is NULL, this function will return FALSE (with an invalid @response + * message) if the response code was not 200 (OK). + * + * Returns: TRUE if the processing was successful. + */ static gboolean gst_rtspsrc_send (GstRTSPSrc * src, RTSPMessage * request, RTSPMessage * response, RTSPStatusCode * code) { RTSPResult res; + RTSPStatusCode thecode; - if (src->debug) { + if (src->debug) rtsp_message_dump (request); - } + if ((res = rtsp_connection_send (src->connection, request)) < 0) goto send_error; if ((res = rtsp_connection_receive (src->connection, response)) < 0) goto receive_error; - if (code) { - *code = response->type_data.response.code; - } - - if (src->debug) { + if (src->debug) rtsp_message_dump (response); - } - if (response->type_data.response.code != RTSP_STS_OK) + + thecode = response->type_data.response.code; + /* if the caller wanted the result code, we store it. Else we check if it's + * OK. */ + if (code) + *code = thecode; + else if (thecode != RTSP_STS_OK) goto error_response; return TRUE; @@ -990,9 +1024,92 @@ receive_error: } error_response: { - GST_ELEMENT_ERROR (src, RESOURCE, READ, ("Got error response: %d (%s).", - response->type_data.response.code, - response->type_data.response.reason), (NULL)); + switch (response->type_data.response.code) { + case RTSP_STS_NOT_FOUND: + GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, ("%s", + response->type_data.response.reason), (NULL)); + break; + default: + GST_ELEMENT_ERROR (src, RESOURCE, READ, ("Got error response: %d (%s).", + response->type_data.response.code, + response->type_data.response.reason), (NULL)); + break; + } + /* we return FALSE so we should unset the response ourselves */ + rtsp_message_unset (response); + return FALSE; + } +} + +/* parse the response and collect all the supported methods. We need this + * information so that we don't try to send an unsupported request to the + * server. + */ +static gboolean +gst_rtspsrc_parse_methods (GstRTSPSrc * src, RTSPMessage * response) +{ + gchar *respoptions = NULL; + gchar **options; + gint i; + + /* clear supported methods */ + src->methods = 0; + + /* Try Allow Header first */ + rtsp_message_get_header (response, RTSP_HDR_ALLOW, &respoptions); + if (!respoptions) + /* Then maybe Public Header... */ + rtsp_message_get_header (response, RTSP_HDR_PUBLIC, &respoptions); + if (!respoptions) { + /* this field is not required, assume the server supports + * DESCRIBE and SETUP*/ + GST_DEBUG_OBJECT (src, "could not get OPTIONS"); + src->methods = RTSP_DESCRIBE | RTSP_SETUP; + goto done; + } + + /* If we get here, the server gave a list of supported methods, parse + * them here. The string is like: + * + * OPTIONS, DESCRIBE, ANNOUNCE, PLAY, SETUP, ... + */ + options = g_strsplit (respoptions, ",", 0); + + i = 0; + while (options[i]) { + gchar *stripped; + gint method; + + stripped = g_strstrip (options[i]); + method = rtsp_find_method (stripped); + + /* keep bitfield of supported methods */ + if (method != -1) + src->methods |= method; + i++; + } + g_strfreev (options); + + /* we need describe and setup */ + if (!(src->methods & RTSP_DESCRIBE)) + goto no_describe; + if (!(src->methods & RTSP_SETUP)) + goto no_setup; + +done: + return TRUE; + + /* ERRORS */ +no_describe: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + ("Server does not support DESCRIBE."), (NULL)); + return FALSE; + } +no_setup: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + ("Server does not support SETUP."), (NULL)); return FALSE; } } @@ -1005,11 +1122,13 @@ gst_rtspsrc_open (GstRTSPSrc * src) RTSPMessage response = { 0 }; guint8 *data; guint size; + gint i, n_streams; SDPMessage sdp = { 0 }; GstRTSPProto protocols; + GstRTSPStream *stream = NULL; /* can't continue without a valid url */ - if (src->url == NULL) + if (G_UNLIKELY (src->url == NULL)) goto no_url; /* open connection */ @@ -1019,7 +1138,7 @@ gst_rtspsrc_open (GstRTSPSrc * src) /* create OPTIONS */ GST_DEBUG_OBJECT (src, "create options..."); - res = rtsp_message_init_request (RTSP_OPTIONS, src->location, &request); + res = rtsp_message_init_request (&request, RTSP_OPTIONS, src->location); if (res < 0) goto create_request_failed; @@ -1028,56 +1147,13 @@ gst_rtspsrc_open (GstRTSPSrc * src) if (!gst_rtspsrc_send (src, &request, &response, NULL)) goto send_error; - { - gchar *respoptions = NULL; - gchar **options; - gint i; - - /* Try Allow Header first */ - rtsp_message_get_header (&response, RTSP_HDR_ALLOW, &respoptions); - if (!respoptions) { - /* Then maybe Public Header... */ - rtsp_message_get_header (&response, RTSP_HDR_PUBLIC, &respoptions); - if (!respoptions) { - /* this field is not required, assume the server supports - * DESCRIBE and SETUP*/ - GST_DEBUG_OBJECT (src, "could not get OPTIONS"); - src->options = RTSP_DESCRIBE | RTSP_SETUP; - goto no_options; - } - } - - /* parse options */ - options = g_strsplit (respoptions, ",", 0); - - i = 0; - while (options[i]) { - gchar *stripped; - gint method; - - stripped = g_strdup (options[i]); - stripped = g_strstrip (stripped); - method = rtsp_find_method (stripped); - g_free (stripped); - - /* keep bitfield of supported methods */ - if (method != -1) - src->options |= method; - i++; - } - g_strfreev (options); - - no_options: - /* we need describe and setup */ - if (!(src->options & RTSP_DESCRIBE)) - goto no_describe; - if (!(src->options & RTSP_SETUP)) - goto no_setup; - } + /* parse OPTIONS */ + if (!gst_rtspsrc_parse_methods (src, &response)) + goto methods_error; /* create DESCRIBE */ GST_DEBUG_OBJECT (src, "create describe..."); - res = rtsp_message_init_request (RTSP_DESCRIBE, src->location, &request); + res = rtsp_message_init_request (&request, RTSP_DESCRIBE, src->location); if (res < 0) goto create_request_failed; @@ -1117,134 +1193,138 @@ gst_rtspsrc_open (GstRTSPSrc * src) protocols = src->protocols; /* setup streams */ - { - gint i; - - for (i = 0; i < sdp_message_medias_len (&sdp); i++) { - SDPMedia *media; - gchar *setup_url; - gchar *control_url; - gchar *transports; - GstRTSPStream *stream; - - media = sdp_message_get_media (&sdp, i); - - stream = gst_rtspsrc_create_stream (src); - - GST_DEBUG_OBJECT (src, "setup media %d", i); - control_url = sdp_media_get_attribute_val (media, "control"); - if (control_url == NULL) { - GST_DEBUG_OBJECT (src, "no control url found, skipping stream"); - continue; - } + n_streams = sdp_message_medias_len (&sdp); + for (i = 0; i < n_streams; i++) { + SDPMedia *media; + gchar *setup_url; + gchar *control_url; + gchar *transports; + + media = sdp_message_get_media (&sdp, i); + + GST_DEBUG_OBJECT (src, "setup media %d", i); + control_url = sdp_media_get_attribute_val (media, "control"); + if (control_url == NULL) { + GST_DEBUG_OBJECT (src, "no control url found, skipping stream %d", i); + continue; + } - /* check absolute/relative URL */ - /* FIXME, what if the control_url starts with a '/' or a non rtsp: protocol? */ - if (g_str_has_prefix (control_url, "rtsp://")) { - setup_url = g_strdup (control_url); - } else { - setup_url = g_strdup_printf ("%s/%s", src->location, control_url); - } + /* check absolute/relative URL */ + /* FIXME, what if the control_url starts with a '/' or a non rtsp: protocol? */ + if (g_str_has_prefix (control_url, "rtsp://")) { + setup_url = g_strdup (control_url); + } else { + setup_url = g_strdup_printf ("%s/%s", src->location, control_url); + } - GST_DEBUG_OBJECT (src, "setup %s", setup_url); + GST_DEBUG_OBJECT (src, "setup %s", setup_url); - /* create SETUP request */ - res = rtsp_message_init_request (RTSP_SETUP, setup_url, &request); - g_free (setup_url); - if (res < 0) - goto create_request_failed; + /* create SETUP request */ + res = rtsp_message_init_request (&request, RTSP_SETUP, setup_url); + g_free (setup_url); + if (res < 0) + goto create_request_failed; - transports = g_strdup (""); - if (protocols & GST_RTSP_PROTO_UDP_UNICAST) { - gchar *new; - gint rtpport, rtcpport; - gchar *trxparams; + stream = gst_rtspsrc_create_stream (src); - /* allocate two UDP ports */ - if (!gst_rtspsrc_stream_setup_rtp (stream, media, &rtpport, &rtcpport)) - goto setup_rtp_failed; + transports = g_strdup (""); + if (protocols & GST_RTSP_PROTO_UDP_UNICAST) { + gchar *new; + gint rtpport, rtcpport; + gchar *trxparams; - GST_DEBUG_OBJECT (src, "setting up RTP ports %d-%d", rtpport, rtcpport); + /* allocate two UDP ports */ + if (!gst_rtspsrc_stream_setup_rtp (stream, media, &rtpport, &rtcpport)) + goto setup_rtp_failed; - trxparams = g_strdup_printf ("client_port=%d-%d", rtpport, rtcpport); - new = g_strconcat (transports, "RTP/AVP/UDP;unicast;", trxparams, NULL); - g_free (trxparams); - g_free (transports); - transports = new; - } - if (protocols & GST_RTSP_PROTO_UDP_MULTICAST) { - gchar *new; - - GST_DEBUG_OBJECT (src, "setting up MULTICAST"); - - /* we don't hav to allocate any UDP ports yet, if the selected transport - * turns out to be multicast we can create them and join the multicast - * group indicated in the transport reply */ - new = - g_strconcat (transports, transports[0] ? "," : "", - "RTP/AVP/UDP;multicast", NULL); - g_free (transports); - transports = new; - } - if (protocols & GST_RTSP_PROTO_TCP) { - gchar *new; + GST_DEBUG_OBJECT (src, "setting up RTP ports %d-%d", rtpport, rtcpport); - GST_DEBUG_OBJECT (src, "setting up TCP"); + trxparams = g_strdup_printf ("client_port=%d-%d", rtpport, rtcpport); + new = g_strconcat (transports, "RTP/AVP/UDP;unicast;", trxparams, NULL); + g_free (trxparams); + g_free (transports); + transports = new; + } + if (protocols & GST_RTSP_PROTO_UDP_MULTICAST) { + gchar *new; - new = - g_strconcat (transports, transports[0] ? "," : "", "RTP/AVP/TCP", - NULL); - g_free (transports); - transports = new; - } + GST_DEBUG_OBJECT (src, "setting up MULTICAST"); - /* select transport, copy is made when adding to header */ - rtsp_message_add_header (&request, RTSP_HDR_TRANSPORT, transports); + /* we don't hav to allocate any UDP ports yet, if the selected transport + * turns out to be multicast we can create them and join the multicast + * group indicated in the transport reply */ + new = + g_strconcat (transports, transports[0] ? "," : "", + "RTP/AVP/UDP;multicast", NULL); g_free (transports); + transports = new; + } + if (protocols & GST_RTSP_PROTO_TCP) { + gchar *new; - if (!gst_rtspsrc_send (src, &request, &response, NULL)) - goto send_error; + GST_DEBUG_OBJECT (src, "setting up TCP"); - /* parse response transport */ - { - gchar *resptrans = NULL; - RTSPTransport transport = { 0 }; + new = + g_strconcat (transports, transports[0] ? "," : "", "RTP/AVP/TCP", + NULL); + g_free (transports); + transports = new; + } - rtsp_message_get_header (&response, RTSP_HDR_TRANSPORT, &resptrans); - if (!resptrans) - goto no_transport; + /* select transport, copy is made when adding to header */ + rtsp_message_add_header (&request, RTSP_HDR_TRANSPORT, transports); + g_free (transports); - /* parse transport */ - rtsp_transport_parse (resptrans, &transport); + if (!gst_rtspsrc_send (src, &request, &response, NULL)) + goto send_error; - /* update allowed transports for other streams. once the transport of - * one stream has been determined, we make sure that all other streams - * are configured in the same way */ - if (transport.lower_transport == RTSP_LOWER_TRANS_TCP) { - GST_DEBUG_OBJECT (src, "stream %d as TCP", i); - protocols = GST_RTSP_PROTO_TCP; - src->interleaved = TRUE; + /* parse response transport */ + { + gchar *resptrans = NULL; + RTSPTransport transport = { 0 }; + + rtsp_message_get_header (&response, RTSP_HDR_TRANSPORT, &resptrans); + if (!resptrans) + goto no_transport; + + /* parse transport */ + rtsp_transport_parse (resptrans, &transport); + + /* update allowed transports for other streams. once the transport of + * one stream has been determined, we make sure that all other streams + * are configured in the same way */ + if (transport.lower_transport == RTSP_LOWER_TRANS_TCP) { + GST_DEBUG_OBJECT (src, "stream %d as TCP", i); + protocols = GST_RTSP_PROTO_TCP; + src->interleaved = TRUE; + } else { + if (transport.multicast) { + /* only allow multicast for other streams */ + GST_DEBUG_OBJECT (src, "stream %d as MULTICAST", i); + protocols = GST_RTSP_PROTO_UDP_MULTICAST; } else { - if (transport.multicast) { - /* only allow multicast for other streams */ - GST_DEBUG_OBJECT (src, "stream %d as MULTICAST", i); - protocols = GST_RTSP_PROTO_UDP_MULTICAST; - } else { - /* only allow unicast for other streams */ - GST_DEBUG_OBJECT (src, "stream %d as UNICAST", i); - protocols = GST_RTSP_PROTO_UDP_UNICAST; - } - } - /* now configure the stream with the transport */ - if (!gst_rtspsrc_stream_configure_transport (stream, media, &transport)) { - GST_DEBUG_OBJECT (src, - "could not configure stream transport, skipping stream"); + /* only allow unicast for other streams */ + GST_DEBUG_OBJECT (src, "stream %d as UNICAST", i); + protocols = GST_RTSP_PROTO_UDP_UNICAST; } - /* clean up our transport struct */ - rtsp_transport_init (&transport); } + /* now configure the stream with the transport */ + if (!gst_rtspsrc_stream_configure_transport (stream, media, &transport)) { + GST_DEBUG_OBJECT (src, + "could not configure stream %d transport, skipping stream", i); + } + /* clean up our transport struct */ + rtsp_transport_init (&transport); } } + /* if we got here all was configured. We have dynamic pads so we notify that + * we are done */ + gst_element_no_more_pads (GST_ELEMENT_CAST (src)); + + /* clean up any messages */ + rtsp_message_unset (&request); + rtsp_message_unset (&response); + return TRUE; /* ERRORS */ @@ -1252,53 +1332,53 @@ no_url: { GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, ("No valid RTSP url was provided"), (NULL)); - return FALSE; + goto cleanup_error; } could_not_open: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, ("Could not open connection."), (NULL)); - return FALSE; + goto cleanup_error; } create_request_failed: { GST_ELEMENT_ERROR (src, LIBRARY, INIT, ("Could not create request."), (NULL)); - return FALSE; + goto cleanup_error; } send_error: { GST_ELEMENT_ERROR (src, RESOURCE, WRITE, ("Could not send message."), (NULL)); - return FALSE; - } -no_describe: - { - GST_ELEMENT_ERROR (src, RESOURCE, WRITE, - ("Server does not support DESCRIBE."), (NULL)); - return FALSE; + goto cleanup_error; } -no_setup: +methods_error: { - GST_ELEMENT_ERROR (src, RESOURCE, WRITE, - ("Server does not support SETUP."), (NULL)); - return FALSE; + /* error was posted */ + goto cleanup_error; } wrong_content_type: { - GST_ELEMENT_ERROR (src, RESOURCE, WRITE, + GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, ("Server does not support SDP."), (NULL)); - return FALSE; + goto cleanup_error; } setup_rtp_failed: { - GST_ELEMENT_ERROR (src, RESOURCE, WRITE, ("Could not setup rtp."), (NULL)); - return FALSE; + GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, ("Could not setup rtp."), + (NULL)); + goto cleanup_error; } no_transport: { - GST_ELEMENT_ERROR (src, RESOURCE, WRITE, + GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, ("Server did not select transport."), (NULL)); + goto cleanup_error; + } +cleanup_error: + { + rtsp_message_unset (&request); + rtsp_message_unset (&response); return FALSE; } } @@ -1328,14 +1408,18 @@ gst_rtspsrc_close (GstRTSPSrc * src) src->task = NULL; } - if (src->options & RTSP_PLAY) { + if (src->methods & RTSP_PLAY) { /* do TEARDOWN */ - res = rtsp_message_init_request (RTSP_TEARDOWN, src->location, &request); + res = rtsp_message_init_request (&request, RTSP_TEARDOWN, src->location); if (res < 0) goto create_request_failed; if (!gst_rtspsrc_send (src, &request, &response, NULL)) goto send_error; + + /* FIXME, parse result? */ + rtsp_message_unset (&request); + rtsp_message_unset (&response); } /* close connection */ @@ -1354,6 +1438,7 @@ create_request_failed: } send_error: { + rtsp_message_unset (&request); GST_ELEMENT_ERROR (src, RESOURCE, WRITE, ("Could not send message."), (NULL)); return FALSE; @@ -1372,13 +1457,13 @@ gst_rtspsrc_play (GstRTSPSrc * src) RTSPMessage response = { 0 }; RTSPResult res; - if (!(src->options & RTSP_PLAY)) + if (!(src->methods & RTSP_PLAY)) return TRUE; GST_DEBUG_OBJECT (src, "PLAY..."); /* do play */ - res = rtsp_message_init_request (RTSP_PLAY, src->location, &request); + res = rtsp_message_init_request (&request, RTSP_PLAY, src->location); if (res < 0) goto create_request_failed; @@ -1387,10 +1472,16 @@ gst_rtspsrc_play (GstRTSPSrc * src) if (!gst_rtspsrc_send (src, &request, &response, NULL)) goto send_error; + rtsp_message_unset (&request); + rtsp_message_unset (&response); + + /* for interleaved transport, we receive the data on the RTSP connection + * instead of UDP. We start a task to select and read from that connection. */ if (src->interleaved) { src->task = gst_task_create ((GstTaskFunction) gst_rtspsrc_loop, src); gst_task_set_lock (src->task, src->stream_rec_lock); + src->running = TRUE; gst_task_start (src->task); } @@ -1405,6 +1496,7 @@ create_request_failed: } send_error: { + rtsp_message_unset (&request); GST_ELEMENT_ERROR (src, RESOURCE, WRITE, ("Could not send message."), (NULL)); return FALSE; @@ -1418,18 +1510,21 @@ gst_rtspsrc_pause (GstRTSPSrc * src) RTSPMessage response = { 0 }; RTSPResult res; - if (!(src->options & RTSP_PAUSE)) + if (!(src->methods & RTSP_PAUSE)) return TRUE; GST_DEBUG_OBJECT (src, "PAUSE..."); /* do pause */ - res = rtsp_message_init_request (RTSP_PAUSE, src->location, &request); + res = rtsp_message_init_request (&request, RTSP_PAUSE, src->location); if (res < 0) goto create_request_failed; if (!gst_rtspsrc_send (src, &request, &response, NULL)) goto send_error; + rtsp_message_unset (&request); + rtsp_message_unset (&response); + return TRUE; /* ERRORS */ @@ -1441,6 +1536,7 @@ create_request_failed: } send_error: { + rtsp_message_unset (&request); GST_ELEMENT_ERROR (src, RESOURCE, WRITE, ("Could not send message."), (NULL)); return FALSE; @@ -1461,7 +1557,7 @@ gst_rtspsrc_change_state (GstElement * element, GstStateChange transition) break; case GST_STATE_CHANGE_READY_TO_PAUSED: rtspsrc->interleaved = FALSE; - rtspsrc->options = 0; + gst_segment_init (&rtspsrc->segment, GST_FORMAT_TIME); if (!gst_rtspsrc_open (rtspsrc)) goto open_failed; break; @@ -1521,6 +1617,7 @@ gst_rtspsrc_uri_get_uri (GstURIHandler * handler) { GstRTSPSrc *src = GST_RTSPSRC (handler); + /* should not dup */ return src->location; } @@ -1560,8 +1657,8 @@ was_ok: } parse_error: { - GST_ERROR_OBJECT (src, "Not a valid RTSP url '%s' (%d)", GST_STR_NULL (uri), - res); + GST_ERROR_OBJECT (src, "Not a valid RTSP url '%s' (%d)", + GST_STR_NULL (uri), res); return FALSE; } } diff --git a/gst/rtsp/gstrtspsrc.h b/gst/rtsp/gstrtspsrc.h index 73267edd..3b3f7240 100644 --- a/gst/rtsp/gstrtspsrc.h +++ b/gst/rtsp/gstrtspsrc.h @@ -103,8 +103,8 @@ struct _GstRTSPSrc { guint retry; GstRTSPProto protocols; - /* supported options */ - gint options; + /* supported methods */ + gint methods; RTSPConnection *connection; RTSPMessage *request; diff --git a/gst/rtsp/rtspconnection.c b/gst/rtsp/rtspconnection.c index f773fa28..5d1ab22c 100644 --- a/gst/rtsp/rtspconnection.c +++ b/gst/rtsp/rtspconnection.c @@ -71,8 +71,8 @@ rtsp_connection_open (RTSPUrl * url, RTSPConnection ** conn) struct in_addr addr; gint ret; - if (url == NULL || conn == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (url != NULL, RTSP_EINVAL); + g_return_val_if_fail (conn != NULL, RTSP_EINVAL); if (url->protocol != RTSP_PROTO_TCP) return RTSP_ENOTIMPL; @@ -128,6 +128,8 @@ rtsp_connection_create (gint fd, RTSPConnection ** conn) { RTSPConnection *newconn; + g_return_val_if_fail (conn != NULL, RTSP_EINVAL); + /* FIXME check fd, must be connected SOCK_STREAM */ newconn = g_new (RTSPConnection, 1); @@ -157,8 +159,8 @@ rtsp_connection_send (RTSPConnection * conn, RTSPMessage * message) gint towrite; gchar *data; - if (conn == NULL || message == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (conn != NULL, RTSP_EINVAL); + g_return_val_if_fail (message != NULL, RTSP_EINVAL); #ifdef G_OS_WIN32 WSADATA w; @@ -333,7 +335,7 @@ parse_response_status (gchar * buffer, RTSPMessage * msg) while (g_ascii_isspace (*bptr)) bptr++; - rtsp_message_init_response (code, bptr, NULL, msg); + rtsp_message_init_response (msg, code, bptr, NULL); return RTSP_OK; @@ -365,7 +367,7 @@ parse_request_line (gchar * buffer, RTSPMessage * msg) if (strcmp (versionstr, "RTSP/1.0") != 0) goto wrong_version; - rtsp_message_init_request (method, urlstr, msg); + rtsp_message_init_request (msg, method, urlstr); return RTSP_OK; @@ -456,8 +458,8 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg) RTSPResult res; gboolean need_body; - if (conn == NULL || msg == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (conn != NULL, RTSP_EINVAL); + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); line = 0; @@ -490,7 +492,7 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg) goto error; /* now we create a data message */ - rtsp_message_init_data ((gint) c, msg); + rtsp_message_init_data (msg, (gint) c); /* next two bytes are the length of the data */ ret = read (conn->fd, &size, 2); @@ -590,8 +592,7 @@ rtsp_connection_close (RTSPConnection * conn) { gint res; - if (conn == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (conn != NULL, RTSP_EINVAL); res = CLOSE_SOCKET (conn->fd); #ifdef G_OS_WIN32 @@ -612,8 +613,7 @@ sys_error: RTSPResult rtsp_connection_free (RTSPConnection * conn) { - if (conn == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (conn != NULL, RTSP_EINVAL); #ifdef G_OS_WIN32 WSACleanup (); diff --git a/gst/rtsp/rtspdefs.h b/gst/rtsp/rtspdefs.h index 169ce48c..a7e89320 100644 --- a/gst/rtsp/rtspdefs.h +++ b/gst/rtsp/rtspdefs.h @@ -50,6 +50,7 @@ typedef enum { } RTSPFamily; typedef enum { + RTSP_STATE_INVALID, RTSP_STATE_INIT, RTSP_STATE_READY, RTSP_STATE_PLAYING, @@ -57,6 +58,7 @@ typedef enum { } RTSPState; typedef enum { + RTSP_INVALID = 0, RTSP_DESCRIBE = (1 << 0), RTSP_ANNOUNCE = (1 << 1), RTSP_GET_PARAMETER = (1 << 2), @@ -120,6 +122,7 @@ typedef enum { } RTSPHeaderField; typedef enum { + RTSP_STS_INVALID = 0, RTSP_STS_CONTINUE = 100, RTSP_STS_OK = 200, RTSP_STS_CREATED = 201, diff --git a/gst/rtsp/rtspmessage.c b/gst/rtsp/rtspmessage.c index fd45f599..bd1473bb 100644 --- a/gst/rtsp/rtspmessage.c +++ b/gst/rtsp/rtspmessage.c @@ -20,84 +20,69 @@ #include "rtspmessage.h" RTSPResult -rtsp_message_new_request (RTSPMethod method, gchar * uri, RTSPMessage ** msg) +rtsp_message_new_request (RTSPMessage ** msg, RTSPMethod method, gchar * uri) { RTSPMessage *newmsg; - if (msg == NULL || uri == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); + g_return_val_if_fail (uri != NULL, RTSP_EINVAL); newmsg = g_new0 (RTSPMessage, 1); *msg = newmsg; - return rtsp_message_init_request (method, uri, newmsg); + return rtsp_message_init_request (newmsg, method, uri); } RTSPResult -rtsp_message_init_request (RTSPMethod method, gchar * uri, RTSPMessage * msg) +rtsp_message_init_request (RTSPMessage * msg, RTSPMethod method, gchar * uri) { - if (msg == NULL || uri == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (uri != NULL, RTSP_EINVAL); + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); + + rtsp_message_unset (msg); msg->type = RTSP_MESSAGE_REQUEST; msg->type_data.request.method = method; - g_free (msg->type_data.request.uri); msg->type_data.request.uri = g_strdup (uri); - - if (msg->hdr_fields != NULL) - g_hash_table_destroy (msg->hdr_fields); msg->hdr_fields = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); - if (msg->body) { - g_free (msg->body); - msg->body = NULL; - } - msg->body_size = 0; - return RTSP_OK; } RTSPResult -rtsp_message_new_response (RTSPStatusCode code, gchar * reason, - RTSPMessage * request, RTSPMessage ** msg) +rtsp_message_new_response (RTSPMessage ** msg, RTSPStatusCode code, + gchar * reason, RTSPMessage * request) { RTSPMessage *newmsg; - if (msg == NULL || reason == NULL || request == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (reason != NULL, RTSP_EINVAL); + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); + g_return_val_if_fail (request != NULL, RTSP_EINVAL); newmsg = g_new0 (RTSPMessage, 1); *msg = newmsg; - return rtsp_message_init_response (code, reason, request, newmsg); + return rtsp_message_init_response (newmsg, code, reason, request); } RTSPResult -rtsp_message_init_response (RTSPStatusCode code, gchar * reason, - RTSPMessage * request, RTSPMessage * msg) +rtsp_message_init_response (RTSPMessage * msg, RTSPStatusCode code, + gchar * reason, RTSPMessage * request) { - if (reason == NULL || msg == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); + g_return_val_if_fail (reason != NULL, RTSP_EINVAL); + + rtsp_message_unset (msg); msg->type = RTSP_MESSAGE_RESPONSE; msg->type_data.response.code = code; - g_free (msg->type_data.response.reason); msg->type_data.response.reason = g_strdup (reason); - - if (msg->hdr_fields != NULL) - g_hash_table_destroy (msg->hdr_fields); msg->hdr_fields = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); - if (msg->body) { - g_free (msg->body); - msg->body = NULL; - } - msg->body_size = 0; - if (request) { /* FIXME copy headers */ } @@ -106,10 +91,11 @@ rtsp_message_init_response (RTSPStatusCode code, gchar * reason, } RTSPResult -rtsp_message_init_data (gint channel, RTSPMessage * msg) +rtsp_message_init_data (RTSPMessage * msg, gint channel) { - if (msg == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); + + rtsp_message_unset (msg); msg->type = RTSP_MESSAGE_DATA; msg->type_data.data.channel = channel; @@ -117,13 +103,51 @@ rtsp_message_init_data (gint channel, RTSPMessage * msg) return RTSP_OK; } +RTSPResult +rtsp_message_unset (RTSPMessage * msg) +{ + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); + + msg->type = RTSP_MESSAGE_INVALID; + msg->type_data.request.method = RTSP_INVALID; + g_free (msg->type_data.request.uri); + msg->type_data.request.uri = NULL; + + msg->type_data.response.code = RTSP_STS_INVALID; + g_free (msg->type_data.response.reason); + msg->type_data.response.reason = NULL; + + if (msg->hdr_fields != NULL) + g_hash_table_destroy (msg->hdr_fields); + msg->hdr_fields = NULL; + + g_free (msg->body); + msg->body = NULL; + msg->body_size = 0; + + return RTSP_OK; +} + +RTSPResult +rtsp_message_free (RTSPMessage * msg) +{ + RTSPResult res; + + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); + + res = rtsp_message_unset (msg); + if (res == RTSP_OK) + g_free (msg); + + return res; +} RTSPResult rtsp_message_add_header (RTSPMessage * msg, RTSPHeaderField field, gchar * value) { - if (msg == NULL || value == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); + g_return_val_if_fail (value != NULL, RTSP_EINVAL); g_hash_table_insert (msg->hdr_fields, GINT_TO_POINTER (field), g_strdup (value)); @@ -134,8 +158,7 @@ rtsp_message_add_header (RTSPMessage * msg, RTSPHeaderField field, RTSPResult rtsp_message_remove_header (RTSPMessage * msg, RTSPHeaderField field) { - if (msg == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); g_hash_table_remove (msg->hdr_fields, GINT_TO_POINTER (field)); @@ -148,8 +171,8 @@ rtsp_message_get_header (RTSPMessage * msg, RTSPHeaderField field, { gchar *val; - if (msg == NULL || value == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); + g_return_val_if_fail (value != NULL, RTSP_EINVAL); val = g_hash_table_lookup (msg->hdr_fields, GINT_TO_POINTER (field)); if (val == NULL) @@ -163,8 +186,7 @@ rtsp_message_get_header (RTSPMessage * msg, RTSPHeaderField field, RTSPResult rtsp_message_set_body (RTSPMessage * msg, guint8 * data, guint size) { - if (msg == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); return rtsp_message_take_body (msg, g_memdup (data, size), size); } @@ -172,8 +194,7 @@ rtsp_message_set_body (RTSPMessage * msg, guint8 * data, guint size) RTSPResult rtsp_message_take_body (RTSPMessage * msg, guint8 * data, guint size) { - if (msg == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); if (msg->body) g_free (msg->body); @@ -187,8 +208,9 @@ rtsp_message_take_body (RTSPMessage * msg, guint8 * data, guint size) RTSPResult rtsp_message_get_body (RTSPMessage * msg, guint8 ** data, guint * size) { - if (msg == NULL || data == NULL || size == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); + g_return_val_if_fail (data != NULL, RTSP_EINVAL); + g_return_val_if_fail (size != NULL, RTSP_EINVAL); *data = msg->body; *size = msg->body_size; @@ -199,8 +221,9 @@ rtsp_message_get_body (RTSPMessage * msg, guint8 ** data, guint * size) RTSPResult rtsp_message_steal_body (RTSPMessage * msg, guint8 ** data, guint * size) { - if (msg == NULL || data == NULL || size == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); + g_return_val_if_fail (data != NULL, RTSP_EINVAL); + g_return_val_if_fail (size != NULL, RTSP_EINVAL); *data = msg->body; *size = msg->body_size; @@ -257,8 +280,7 @@ rtsp_message_dump (RTSPMessage * msg) guint8 *data; guint size; - if (msg == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); if (msg->type == RTSP_MESSAGE_REQUEST) { g_print ("request message %p\n", msg); diff --git a/gst/rtsp/rtspmessage.h b/gst/rtsp/rtspmessage.h index 3488cac1..ced3f840 100644 --- a/gst/rtsp/rtspmessage.h +++ b/gst/rtsp/rtspmessage.h @@ -28,6 +28,7 @@ G_BEGIN_DECLS typedef enum { + RTSP_MESSAGE_INVALID, RTSP_MESSAGE_REQUEST, RTSP_MESSAGE_RESPONSE, RTSP_MESSAGE_DATA, @@ -58,15 +59,16 @@ typedef struct _RTSPMessage } RTSPMessage; -RTSPResult rtsp_message_new_request (RTSPMethod method, gchar *uri, RTSPMessage **msg); -RTSPResult rtsp_message_init_request (RTSPMethod method, gchar *uri, RTSPMessage *msg); +RTSPResult rtsp_message_new_request (RTSPMessage **msg, RTSPMethod method, gchar *uri); +RTSPResult rtsp_message_init_request (RTSPMessage *msg, RTSPMethod method, gchar *uri); -RTSPResult rtsp_message_new_response (RTSPStatusCode code, gchar *reason, - RTSPMessage *request, RTSPMessage **msg); -RTSPResult rtsp_message_init_response (RTSPStatusCode code, gchar *reason, - RTSPMessage *request, RTSPMessage *msg); -RTSPResult rtsp_message_init_data (gint channel, RTSPMessage *msg); +RTSPResult rtsp_message_new_response (RTSPMessage **msg, RTSPStatusCode code, gchar *reason, + RTSPMessage *request); +RTSPResult rtsp_message_init_response (RTSPMessage *msg, RTSPStatusCode code, gchar *reason, + RTSPMessage *request); +RTSPResult rtsp_message_init_data (RTSPMessage *msg, gint channel); +RTSPResult rtsp_message_unset (RTSPMessage *msg); RTSPResult rtsp_message_free (RTSPMessage *msg); diff --git a/gst/rtsp/rtsptransport.c b/gst/rtsp/rtsptransport.c index 3fdea275..57ec9204 100644 --- a/gst/rtsp/rtsptransport.c +++ b/gst/rtsp/rtsptransport.c @@ -27,8 +27,7 @@ rtsp_transport_new (RTSPTransport ** transport) { RTSPTransport *trans; - if (transport == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (transport != NULL, RTSP_EINVAL); trans = g_new0 (RTSPTransport, 1); @@ -40,6 +39,8 @@ rtsp_transport_new (RTSPTransport ** transport) RTSPResult rtsp_transport_init (RTSPTransport * transport) { + g_return_val_if_fail (transport != NULL, RTSP_EINVAL); + g_free (transport->destination); g_free (transport->source); g_free (transport->ssrc); @@ -83,8 +84,8 @@ rtsp_transport_parse (gchar * str, RTSPTransport * transport) gchar **split, *down; gint i; - if (str == NULL || transport == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (transport != NULL, RTSP_EINVAL); + g_return_val_if_fail (str != NULL, RTSP_EINVAL); rtsp_transport_init (transport); @@ -141,6 +142,8 @@ rtsp_transport_parse (gchar * str, RTSPTransport * transport) RTSPResult rtsp_transport_free (RTSPTransport * transport) { + g_return_val_if_fail (transport != NULL, RTSP_EINVAL); + rtsp_transport_init (transport); g_free (transport); return RTSP_OK; diff --git a/gst/rtsp/rtspurl.c b/gst/rtsp/rtspurl.c index c5e429f7..dc861fd0 100644 --- a/gst/rtsp/rtspurl.c +++ b/gst/rtsp/rtspurl.c @@ -34,10 +34,10 @@ rtsp_url_parse (const gchar * urlstr, RTSPUrl ** url) RTSPUrl *res; gchar *p, *slash, *at, *col; - res = g_new0 (RTSPUrl, 1); + g_return_val_if_fail (urlstr != NULL, RTSP_EINVAL); + g_return_val_if_fail (url != NULL, RTSP_EINVAL); - if (urlstr == NULL) - goto invalid; + res = g_new0 (RTSPUrl, 1); p = (gchar *) urlstr; if (g_str_has_prefix (p, RTSP_PROTO)) { diff --git a/gst/rtsp/sdpmessage.c b/gst/rtsp/sdpmessage.c index 5ab9b85f..23aab927 100644 --- a/gst/rtsp/sdpmessage.c +++ b/gst/rtsp/sdpmessage.c @@ -76,8 +76,7 @@ sdp_message_new (SDPMessage ** msg) { SDPMessage *newmsg; - if (msg == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); newmsg = g_new0 (SDPMessage, 1); @@ -89,8 +88,7 @@ sdp_message_new (SDPMessage ** msg) RTSPResult sdp_message_init (SDPMessage * msg) { - if (msg == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); FREE_STRING (msg->version); FREE_STRING (msg->origin.username); @@ -123,8 +121,7 @@ sdp_message_init (SDPMessage * msg) RTSPResult sdp_message_clean (SDPMessage * msg) { - if (msg == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); FREE_ARRAY (msg->emails); FREE_ARRAY (msg->phones); @@ -140,8 +137,7 @@ sdp_message_clean (SDPMessage * msg) RTSPResult sdp_message_free (SDPMessage * msg) { - if (msg == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); sdp_message_clean (msg); @@ -156,8 +152,7 @@ sdp_media_new (SDPMedia ** media) { SDPMedia *newmedia; - if (media == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (media != NULL, RTSP_EINVAL); newmedia = g_new0 (SDPMedia, 1); @@ -169,8 +164,7 @@ sdp_media_new (SDPMedia ** media) RTSPResult sdp_media_init (SDPMedia * media) { - if (media == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (media != NULL, RTSP_EINVAL); FREE_STRING (media->media); media->port = 0; @@ -578,8 +572,9 @@ sdp_message_parse_buffer (guint8 * data, guint size, SDPMessage * msg) gchar buffer[4096]; gint idx = 0; - if (msg == NULL || data == NULL || size == 0) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); + g_return_val_if_fail (data != NULL, RTSP_EINVAL); + g_return_val_if_fail (size != 0, RTSP_EINVAL); c.state = SDP_SESSION; c.msg = msg; @@ -651,8 +646,7 @@ print_media (SDPMedia * media) RTSPResult sdp_message_dump (SDPMessage * msg) { - if (msg == NULL) - return RTSP_EINVAL; + g_return_val_if_fail (msg != NULL, RTSP_EINVAL); g_print ("sdp packet %p:\n", msg); g_print (" version: '%s'\n", msg->version); @@ -666,6 +660,7 @@ sdp_message_dump (SDPMessage * msg) g_print (" session_name: '%s'\n", msg->session_name); g_print (" information: '%s'\n", msg->information); g_print (" uri: '%s'\n", msg->uri); + if (msg->emails->len > 0) { gint i; @@ -710,7 +705,5 @@ sdp_message_dump (SDPMessage * msg) print_media (&g_array_index (msg->medias, SDPMedia, i)); } } - - return RTSP_OK; } |