From 16bc937ed95c85c9d02a314a3b065eebc575a97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20J=C3=B6nsson?= Date: Wed, 21 Aug 2019 14:57:25 +0200 Subject: [PATCH] Use complete streams for scale and speed. Without this patch it's always stream0 that is used to get segment event that is used to set scale and speed. This even if client not doing SETUP for stream0. At least in suspend mode reset this not working since then it's just random if send_rtp_sink have got any segment event. There are no check if send_rtp_sink for stream0 got any data before media is prerolled after PLAY request. --- gst/rtsp-server/rtsp-client.c | 2 +- gst/rtsp-server/rtsp-media.c | 64 ++++++++++++++++++++++++++++-- gst/rtsp-server/rtsp-media.h | 3 ++ tests/check/gst/rtspserver.c | 73 +++++++++++++++++++++++++++++++++++ 4 files changed, 137 insertions(+), 5 deletions(-) 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; }