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.
This commit is contained in:
Göran Jönsson 2019-08-21 14:57:25 +02:00
parent 4319e17b0e
commit 16bc937ed9
4 changed files with 137 additions and 5 deletions

View file

@ -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 */

View file

@ -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:
*

View file

@ -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);

View file

@ -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;
}