diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c index 964e06bfeb..5dac08b9d1 100644 --- a/gst/rtsp-server/rtsp-client.c +++ b/gst/rtsp-server/rtsp-client.c @@ -2026,7 +2026,7 @@ handle_play_request (GstRTSPClient * client, GstRTSPContext * ctx) if (str) gst_rtsp_message_take_header (ctx->response, GST_RTSP_HDR_RANGE, str); - if (!gst_rtsp_media_is_receive_only (media)) { + if (gst_rtsp_media_has_completed_sender (media)) { /* the scale and speed headers must always be added if they were present in * the request. however, even if they were not, we still add them if * applied_rate or rate deviate from the "normal", i.e. 1.0 */ diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 4aaed7ce6e..35a9ec0cfd 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -2562,7 +2562,10 @@ gst_rtsp_media_get_rates (GstRTSPMedia * media, gdouble * rate, { GstRTSPMediaPrivate *priv; GstRTSPStream *stream; + gdouble save_rate, save_applied_rate; gboolean result = TRUE; + gboolean first_stream = TRUE; + gint i; g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); @@ -2576,11 +2579,34 @@ gst_rtsp_media_get_rates (GstRTSPMedia * media, gdouble * rate, g_mutex_lock (&priv->lock); g_assert (priv->streams->len > 0); - stream = g_ptr_array_index (priv->streams, 0); - if (!gst_rtsp_stream_get_rates (stream, rate, applied_rate)) { + for (i = 0; i < priv->streams->len; i++) { + stream = g_ptr_array_index (priv->streams, i); + if (gst_rtsp_stream_is_complete (stream)) { + if (gst_rtsp_stream_get_rates (stream, rate, applied_rate)) { + if (first_stream) { + save_rate = *rate; + save_applied_rate = *applied_rate; + first_stream = FALSE; + } else { + if (save_rate != *rate || save_applied_rate != *applied_rate) { + /* diffrent rate or applied_rate, weird */ + g_assert (FALSE); + result = FALSE; + break; + } + } + } else { + /* complete stream withot rate and applied_rate, weird */ + g_assert (FALSE); + result = FALSE; + break; + } + } + } + + if (!result) { GST_WARNING_OBJECT (media, - "failed to obtain rate and applied_rate from first stream"); - result = FALSE; + "failed to obtain consistent rate and applied_rate"); } g_mutex_unlock (&priv->lock); @@ -4781,6 +4807,36 @@ gst_rtsp_media_is_receive_only (GstRTSPMedia * media) return receive_only; } +/** + * gst_rtsp_media_has_completed_sender: + * + * See gst_rtsp_stream_is_complete(), gst_rtsp_stream_is_sender(). + * + * Returns: whether @media has at least one complete sender stream. + * Since: 1.18 + */ +gboolean +gst_rtsp_media_has_completed_sender (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + gboolean sender = FALSE; + guint i; + + g_mutex_lock (&priv->lock); + for (i = 0; i < priv->streams->len; i++) { + GstRTSPStream *stream = g_ptr_array_index (priv->streams, i); + if (gst_rtsp_stream_is_complete (stream)) + if (gst_rtsp_stream_is_sender (stream) || + !gst_rtsp_stream_is_receiver (stream)) { + sender = TRUE; + break; + } + } + g_mutex_unlock (&priv->lock); + + return sender; +} + /** * gst_rtsp_media_set_rate_control: * diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h index 987a8ad017..5379f65e64 100644 --- a/gst/rtsp-server/rtsp-media.h +++ b/gst/rtsp-server/rtsp-media.h @@ -421,6 +421,9 @@ gboolean gst_rtsp_media_complete_pipeline (GstRTSPMedia * media, GP GST_RTSP_SERVER_API gboolean gst_rtsp_media_is_receive_only (GstRTSPMedia * media); +GST_RTSP_SERVER_API +gboolean gst_rtsp_media_has_completed_sender (GstRTSPMedia * media); + GST_RTSP_SERVER_API void gst_rtsp_media_set_rate_control (GstRTSPMedia * media, gboolean enabled); diff --git a/tests/check/gst/rtspserver.c b/tests/check/gst/rtspserver.c index d342a436d3..f3bd5d0676 100644 --- a/tests/check/gst/rtspserver.c +++ b/tests/check/gst/rtspserver.c @@ -2401,6 +2401,78 @@ GST_START_TEST (test_multiple_transports) GST_END_TEST; +GST_START_TEST (test_suspend_mode_reset_only_audio) +{ + GstRTSPMountPoints *mounts; + gchar *service; + GstRTSPMediaFactory *factory; + GstRTSPConnection *conn; + GstSDPMessage *sdp_message = NULL; + const GstSDPMedia *sdp_media; + const gchar *audio_control; + GstRTSPRange client_port; + gchar *session = NULL; + GstRTSPTransport *audio_transport = NULL; + GSocket *rtp_socket, *rtcp_socket; + + mounts = gst_rtsp_server_get_mount_points (server); + + factory = gst_rtsp_media_factory_new (); + gst_rtsp_media_factory_set_suspend_mode (factory, + GST_RTSP_SUSPEND_MODE_RESET); + gst_rtsp_media_factory_set_launch (factory, + "( " VIDEO_PIPELINE " " AUDIO_PIPELINE " )"); + gst_rtsp_mount_points_add_factory (mounts, TEST_MOUNT_POINT, factory); + g_object_unref (mounts); + + /* set port to any */ + gst_rtsp_server_set_service (server, "0"); + + /* attach to default main context */ + source_id = gst_rtsp_server_attach (server, NULL); + fail_if (source_id == 0); + + /* get port */ + service = gst_rtsp_server_get_service (server); + test_port = atoi (service); + fail_unless (test_port != 0); + g_free (service); + + conn = connect_to_server (test_port, TEST_MOUNT_POINT); + + sdp_message = do_describe (conn, TEST_MOUNT_POINT); + + /* get control strings from DESCRIBE response */ + fail_unless (gst_sdp_message_medias_len (sdp_message) == 2); + sdp_media = gst_sdp_message_get_media (sdp_message, 1); + audio_control = gst_sdp_media_get_attribute_val (sdp_media, "control"); + + get_client_ports_full (&client_port, &rtp_socket, &rtcp_socket); + + /* do SETUP for audio */ + fail_unless (do_setup (conn, audio_control, &client_port, &session, + &audio_transport) == GST_RTSP_STS_OK); + + /* send PLAY request and check that we get 200 OK */ + fail_unless (do_simple_request (conn, GST_RTSP_PLAY, + session) == GST_RTSP_STS_OK); + + /* send TEARDOWN request and check that we get 200 OK */ + fail_unless (do_simple_request (conn, GST_RTSP_TEARDOWN, + session) == GST_RTSP_STS_OK); + + /* clean up and iterate so the clean-up can finish */ + g_free (session); + gst_rtsp_transport_free (audio_transport); + gst_sdp_message_free (sdp_message); + gst_rtsp_connection_free (conn); + + stop_server (); + iterate (); +} + +GST_END_TEST; + static Suite * rtspserver_suite (void) { @@ -2439,6 +2511,7 @@ rtspserver_suite (void) tcase_add_test (tc, test_announce_without_sdp); tcase_add_test (tc, test_record_tcp); tcase_add_test (tc, test_multiple_transports); + tcase_add_test (tc, test_suspend_mode_reset_only_audio); return s; }