gstreamer/tests/check/gst/media.c
Nikita Bobkov f31f79f60e Reverse playback support
GStreamer plays segment from stop to start when doing reverse playback.
RTSP implies that media should be played from start of Range header to
its stop. Hence we swap start and stop times before passing them to
gst_element_seek.

Also make gst_rtsp_stream_query_stop always return value that can be
used as stop time of Range header.
2019-06-04 14:32:51 +02:00

866 lines
26 KiB
C

/* GStreamer
* Copyright (C) 2012 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <gst/check/gstcheck.h>
#include <rtsp-media-factory.h>
/* Check if the media can return a SDP. We don't actually check whether
* the contents are valid or not */
static gboolean
media_has_sdp (GstRTSPMedia * media)
{
GstSDPInfo info;
GstSDPMessage *sdp;
gchar *sdp_str;
info.is_ipv6 = FALSE;
info.server_ip = "0.0.0.0";
/* Check if media can generate a SDP */
gst_sdp_message_new (&sdp);
GST_DEBUG ("Getting SDP");
if (!gst_rtsp_sdp_from_media (sdp, &info, media)) {
GST_WARNING ("failed to get the SDP");
gst_sdp_message_free (sdp);
return FALSE;
}
sdp_str = gst_sdp_message_as_text (sdp);
GST_DEBUG ("Got SDP\n%s", sdp_str);
g_free (sdp_str);
gst_sdp_message_free (sdp);
return TRUE;
}
GST_START_TEST (test_media_seek)
{
GstRTSPMediaFactory *factory;
GstRTSPMedia *media;
GstRTSPUrl *url;
GstRTSPStream *stream;
GstRTSPTimeRange *range;
gchar *str;
GstRTSPThreadPool *pool;
GstRTSPThread *thread;
GstRTSPTransport *transport;
gdouble rate = 0;
gdouble applied_rate = 0;
factory = gst_rtsp_media_factory_new ();
fail_if (gst_rtsp_media_factory_is_shared (factory));
fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test",
&url) == GST_RTSP_OK);
gst_rtsp_media_factory_set_launch (factory,
"( videotestsrc ! rtpvrawpay pt=96 name=pay0 )");
media = gst_rtsp_media_factory_construct (factory, url);
fail_unless (GST_IS_RTSP_MEDIA (media));
fail_unless (gst_rtsp_media_n_streams (media) == 1);
stream = gst_rtsp_media_get_stream (media, 0);
fail_unless (stream != NULL);
pool = gst_rtsp_thread_pool_new ();
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_unless (gst_rtsp_media_prepare (media, thread));
fail_unless (media_has_sdp (media));
/* define transport */
fail_unless (gst_rtsp_transport_new (&transport) == GST_RTSP_OK);
transport->lower_transport = GST_RTSP_LOWER_TRANS_TCP;
fail_unless (gst_rtsp_stream_complete_stream (stream, transport));
fail_unless (gst_rtsp_transport_free (transport) == GST_RTSP_OK);
fail_unless (gst_rtsp_range_parse ("npt=5.0-", &range) == GST_RTSP_OK);
/* the media is seekable now */
fail_unless (gst_rtsp_media_seek (media, range));
str = gst_rtsp_media_get_range_string (media, FALSE, GST_RTSP_RANGE_NPT);
fail_unless (g_str_equal (str, "npt=5-"));
g_free (str);
/* seeking without rate should result in rate == 1.0 */
fail_unless (gst_rtsp_media_seek (media, range));
fail_unless (gst_rtsp_media_get_rates (media, &rate, &applied_rate));
fail_unless (rate == 1.0);
fail_unless (applied_rate == 1.0);
/* seeking with rate set to 1.5 should result in rate == 1.5 */
fail_unless (gst_rtsp_media_seek_full_with_rate (media, range,
GST_SEEK_FLAG_NONE, 1.5));
fail_unless (gst_rtsp_media_get_rates (media, &rate, &applied_rate));
fail_unless (rate == 1.5);
fail_unless (applied_rate == 1.0);
/* seeking with rate set to -2.0 should result in rate == -2.0 */
fail_unless (gst_rtsp_range_parse ("npt=10-5", &range) == GST_RTSP_OK);
fail_unless (gst_rtsp_media_seek_full_with_rate (media, range,
GST_SEEK_FLAG_NONE, -2.0));
fail_unless (gst_rtsp_media_get_rates (media, &rate, &applied_rate));
fail_unless (rate == -2.0);
fail_unless (applied_rate == 1.0);
gst_rtsp_range_free (range);
fail_unless (gst_rtsp_media_unprepare (media));
g_object_unref (media);
gst_rtsp_url_free (url);
g_object_unref (factory);
g_object_unref (pool);
gst_rtsp_thread_pool_cleanup ();
}
GST_END_TEST;
/* case: media is complete and contains two streams but only one is active */
GST_START_TEST (test_media_seek_one_active_stream)
{
GstRTSPMediaFactory *factory;
GstRTSPMedia *media;
GstRTSPUrl *url;
GstRTSPStream *stream1;
GstRTSPStream *stream2;
GstRTSPTimeRange *range;
GstRTSPThreadPool *pool;
GstRTSPThread *thread;
GstRTSPTransport *transport;
char *range_str;
GstRTSPTimeRange *play_range;
factory = gst_rtsp_media_factory_new ();
fail_if (gst_rtsp_media_factory_is_shared (factory));
fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test",
&url) == GST_RTSP_OK);
gst_rtsp_media_factory_set_launch (factory,
"( videotestsrc ! rtpvrawpay pt=96 name=pay0 "
" audiotestsrc ! audioconvert ! rtpL16pay name=pay1 )");
media = gst_rtsp_media_factory_construct (factory, url);
fail_unless (GST_IS_RTSP_MEDIA (media));
fail_unless (gst_rtsp_media_n_streams (media) == 2);
stream1 = gst_rtsp_media_get_stream (media, 0);
fail_unless (stream1 != NULL);
pool = gst_rtsp_thread_pool_new ();
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_unless (gst_rtsp_media_prepare (media, thread));
fail_unless (media_has_sdp (media));
/* define transport */
fail_unless (gst_rtsp_transport_new (&transport) == GST_RTSP_OK);
transport->lower_transport = GST_RTSP_LOWER_TRANS_TCP;
fail_unless_equals_int64 (gst_rtsp_media_seekable (media), G_MAXINT64);
/* video stream is complete and seekable */
fail_unless (gst_rtsp_stream_complete_stream (stream1, transport));
fail_unless (gst_rtsp_stream_seekable (stream1));
/* audio stream is blocked (it does not contain any transport based part),
* but it's seekable */
stream2 = gst_rtsp_media_get_stream (media, 1);
fail_unless (stream2 != NULL);
fail_unless (gst_rtsp_stream_seekable (stream2));
fail_unless (gst_rtsp_transport_free (transport) == GST_RTSP_OK);
fail_unless (gst_rtsp_range_parse ("npt=3.0-", &range) == GST_RTSP_OK);
/* the media is seekable now */
fail_unless (gst_rtsp_media_seek (media, range));
/* verify that we got the expected range, 'npt=3.0-' */
range_str = gst_rtsp_media_get_range_string (media, TRUE, GST_RTSP_RANGE_NPT);
fail_unless (gst_rtsp_range_parse (range_str, &play_range) == GST_RTSP_OK);
fail_unless (play_range->min.seconds == range->min.seconds);
fail_unless (play_range->max.seconds == range->max.seconds);
gst_rtsp_range_free (range);
gst_rtsp_range_free (play_range);
g_free (range_str);
fail_unless (gst_rtsp_media_unprepare (media));
g_object_unref (media);
gst_rtsp_url_free (url);
g_object_unref (factory);
g_object_unref (pool);
gst_rtsp_thread_pool_cleanup ();
}
GST_END_TEST;
GST_START_TEST (test_media_seek_no_sinks)
{
GstRTSPMediaFactory *factory;
GstRTSPMedia *media;
GstRTSPUrl *url;
GstRTSPStream *stream;
GstRTSPTimeRange *range;
gchar *str;
GstRTSPThreadPool *pool;
GstRTSPThread *thread;
factory = gst_rtsp_media_factory_new ();
fail_if (gst_rtsp_media_factory_is_shared (factory));
fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test",
&url) == GST_RTSP_OK);
gst_rtsp_media_factory_set_launch (factory,
"( videotestsrc ! rtpvrawpay pt=96 name=pay0 )");
media = gst_rtsp_media_factory_construct (factory, url);
fail_unless (GST_IS_RTSP_MEDIA (media));
fail_unless (gst_rtsp_media_n_streams (media) == 1);
stream = gst_rtsp_media_get_stream (media, 0);
fail_unless (stream != NULL);
/* fails, need to be prepared */
str = gst_rtsp_media_get_range_string (media, FALSE, GST_RTSP_RANGE_NPT);
fail_unless (str == NULL);
fail_unless (gst_rtsp_range_parse ("npt=5.0-", &range) == GST_RTSP_OK);
/* fails, need to be prepared */
fail_if (gst_rtsp_media_seek (media, range));
pool = gst_rtsp_thread_pool_new ();
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_unless (gst_rtsp_media_prepare (media, thread));
fail_unless (media_has_sdp (media));
str = gst_rtsp_media_get_range_string (media, FALSE, GST_RTSP_RANGE_NPT);
fail_unless (g_str_equal (str, "npt=0-"));
g_free (str);
str = gst_rtsp_media_get_range_string (media, TRUE, GST_RTSP_RANGE_NPT);
fail_unless (g_str_equal (str, "npt=0-"));
g_free (str);
/* fails, need to be prepared and contain sink elements */
fail_if (gst_rtsp_media_seek (media, range));
fail_unless (gst_rtsp_media_unprepare (media));
/* should fail again */
str = gst_rtsp_media_get_range_string (media, FALSE, GST_RTSP_RANGE_NPT);
fail_unless (str == NULL);
fail_if (gst_rtsp_media_seek (media, range));
gst_rtsp_range_free (range);
g_object_unref (media);
gst_rtsp_url_free (url);
g_object_unref (factory);
g_object_unref (pool);
gst_rtsp_thread_pool_cleanup ();
}
GST_END_TEST;
GST_START_TEST (test_media)
{
GstRTSPMedia *media;
GstElement *bin, *e1, *e2;
bin = gst_bin_new ("bin");
fail_if (bin == NULL);
e1 = gst_element_factory_make ("videotestsrc", NULL);
fail_if (e1 == NULL);
e2 = gst_element_factory_make ("rtpvrawpay", "pay0");
fail_if (e2 == NULL);
g_object_set (e2, "pt", 96, NULL);
gst_bin_add_many (GST_BIN_CAST (bin), e1, e2, NULL);
gst_element_link_many (e1, e2, NULL);
media = gst_rtsp_media_new (bin);
fail_unless (GST_IS_RTSP_MEDIA (media));
g_object_unref (media);
}
GST_END_TEST;
static void
test_prepare_reusable (const gchar * launch_line, gboolean is_live)
{
GstRTSPMediaFactory *factory;
GstRTSPMedia *media;
GstRTSPUrl *url;
GstRTSPThread *thread;
GstRTSPThreadPool *pool;
factory = gst_rtsp_media_factory_new ();
fail_if (gst_rtsp_media_factory_is_shared (factory));
fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test",
&url) == GST_RTSP_OK);
gst_rtsp_media_factory_set_launch (factory, launch_line);
media = gst_rtsp_media_factory_construct (factory, url);
fail_unless (GST_IS_RTSP_MEDIA (media));
fail_unless (gst_rtsp_media_n_streams (media) == 1);
g_object_set (G_OBJECT (media), "reusable", TRUE, NULL);
pool = gst_rtsp_thread_pool_new ();
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_unless (gst_rtsp_media_prepare (media, thread));
fail_unless (media_has_sdp (media));
if (is_live) { /* Live is not seekable */
fail_unless_equals_int64 (gst_rtsp_media_seekable (media), -1);
} else {
fail_unless_equals_int64 (gst_rtsp_media_seekable (media), G_MAXINT64);
}
fail_unless (gst_rtsp_media_unprepare (media));
fail_unless (gst_rtsp_media_n_streams (media) == 1);
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_unless (gst_rtsp_media_prepare (media, thread));
fail_unless (media_has_sdp (media));
fail_unless (gst_rtsp_media_unprepare (media));
g_object_unref (media);
gst_rtsp_url_free (url);
g_object_unref (factory);
g_object_unref (pool);
}
GST_START_TEST (test_media_reusable)
{
/* test reusable media */
test_prepare_reusable ("( videotestsrc ! rtpvrawpay pt=96 name=pay0 )",
FALSE);
test_prepare_reusable
("( videotestsrc is-live=true ! rtpvrawpay pt=96 name=pay0 )", TRUE);
}
GST_END_TEST;
GST_START_TEST (test_media_prepare)
{
GstRTSPMediaFactory *factory;
GstRTSPMedia *media;
GstRTSPUrl *url;
GstRTSPThreadPool *pool;
GstRTSPThread *thread;
pool = gst_rtsp_thread_pool_new ();
/* test non-reusable media first */
factory = gst_rtsp_media_factory_new ();
fail_if (gst_rtsp_media_factory_is_shared (factory));
fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test",
&url) == GST_RTSP_OK);
gst_rtsp_media_factory_set_launch (factory,
"( videotestsrc ! rtpvrawpay pt=96 name=pay0 )");
media = gst_rtsp_media_factory_construct (factory, url);
fail_unless (GST_IS_RTSP_MEDIA (media));
fail_unless (gst_rtsp_media_n_streams (media) == 1);
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_unless (gst_rtsp_media_prepare (media, thread));
fail_unless (media_has_sdp (media));
fail_unless_equals_int64 (gst_rtsp_media_seekable (media), G_MAXINT64);
fail_unless (gst_rtsp_media_unprepare (media));
fail_unless (gst_rtsp_media_n_streams (media) == 1);
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_if (gst_rtsp_media_prepare (media, thread));
g_object_unref (media);
gst_rtsp_url_free (url);
g_object_unref (factory);
g_object_unref (pool);
gst_rtsp_thread_pool_cleanup ();
}
GST_END_TEST;
enum _SyncState
{
SYNC_STATE_INIT,
SYNC_STATE_1,
SYNC_STATE_2,
SYNC_STATE_RACE
};
typedef enum _SyncState SyncState;
struct _help_thread_data
{
GstRTSPThreadPool *pool;
GstRTSPMedia *media;
GstRTSPTransport *transport;
GstRTSPStream *stream;
SyncState *state;
GMutex *sync_mutex;
GCond *sync_cond;
};
typedef struct _help_thread_data help_thread_data;
static gpointer
help_thread_main (gpointer user_data)
{
help_thread_data *data;
GstRTSPThread *thread;
GPtrArray *transports;
GstRTSPStreamTransport *stream_transport;
data = (help_thread_data *) user_data;
GST_INFO ("Another thread sharing media");
/* wait SYNC_STATE_1 */
g_mutex_lock (data->sync_mutex);
while (*data->state < SYNC_STATE_1)
g_cond_wait (data->sync_cond, data->sync_mutex);
g_mutex_unlock (data->sync_mutex);
/* prepare */
thread = gst_rtsp_thread_pool_get_thread (data->pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_unless (gst_rtsp_media_prepare (data->media, thread));
/* set SYNC_STATE_2 */
g_mutex_lock (data->sync_mutex);
*data->state = SYNC_STATE_2;
g_cond_signal (data->sync_cond);
g_mutex_unlock (data->sync_mutex);
/* wait SYNC_STATE_RACE */
g_mutex_lock (data->sync_mutex);
while (*data->state < SYNC_STATE_RACE)
g_cond_wait (data->sync_cond, data->sync_mutex);
g_mutex_unlock (data->sync_mutex);
/* set state */
transports = g_ptr_array_new_with_free_func (g_object_unref);
fail_unless (transports != NULL);
stream_transport =
gst_rtsp_stream_transport_new (data->stream, data->transport);
fail_unless (stream_transport != NULL);
g_ptr_array_add (transports, stream_transport);
fail_unless (gst_rtsp_media_set_state (data->media, GST_STATE_NULL,
transports));
/* clean up */
GST_INFO ("Thread exit");
fail_unless (gst_rtsp_media_unprepare (data->media));
g_ptr_array_unref (transports);
return NULL;
}
GST_START_TEST (test_media_shared_race_test_unsuspend_vs_set_state_null)
{
help_thread_data data;
GstRTSPMediaFactory *factory;
GstRTSPMedia *media;
GstRTSPUrl *url;
GstRTSPThreadPool *pool;
GstRTSPThread *thread;
GThread *sharing_media_thread;
GstRTSPTransport *transport;
GstRTSPStream *stream;
SyncState state = SYNC_STATE_INIT;
GMutex sync_mutex;
GCond sync_cond;
g_mutex_init (&sync_mutex);
g_cond_init (&sync_cond);
pool = gst_rtsp_thread_pool_new ();
/* test non-reusable media first */
factory = gst_rtsp_media_factory_new ();
gst_rtsp_media_factory_set_shared (factory, TRUE);
fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test",
&url) == GST_RTSP_OK);
gst_rtsp_media_factory_set_launch (factory,
"( videotestsrc ! rtpvrawpay pt=96 name=pay0 )");
media = gst_rtsp_media_factory_construct (factory, url);
fail_unless (GST_IS_RTSP_MEDIA (media));
fail_unless (gst_rtsp_media_n_streams (media) == 1);
gst_rtsp_media_set_suspend_mode (media, GST_RTSP_SUSPEND_MODE_RESET);
stream = gst_rtsp_media_get_stream (media, 0);
fail_unless (stream != NULL);
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_unless (gst_rtsp_media_prepare (media, thread));
/* help thread */
data.pool = pool;
data.media = media;
data.stream = stream;
data.state = &state;
data.sync_mutex = &sync_mutex;
data.sync_cond = &sync_cond;
sharing_media_thread = g_thread_new ("new thread", help_thread_main, &data);
fail_unless (sharing_media_thread != NULL);
/* set state SYNC_STATE_1 */
g_mutex_lock (&sync_mutex);
state = SYNC_STATE_1;
g_cond_signal (&sync_cond);
g_mutex_unlock (&sync_mutex);
/* wait SYNC_STATE_2 */
g_mutex_lock (&sync_mutex);
while (state < SYNC_STATE_2)
g_cond_wait (&sync_cond, &sync_mutex);
g_mutex_unlock (&sync_mutex);
gst_rtsp_media_suspend (media);
fail_unless (gst_rtsp_transport_new (&transport) == GST_RTSP_OK);
transport->lower_transport = GST_RTSP_LOWER_TRANS_TCP;
fail_unless (gst_rtsp_stream_complete_stream (stream, transport));
data.transport = transport;
/* set state SYNC_STATE_RACE let the race begin unsuspend <-> set state GST_STATE_NULL */
g_mutex_lock (&sync_mutex);
state = SYNC_STATE_RACE;
g_cond_signal (&sync_cond);
g_mutex_unlock (&sync_mutex);
fail_unless (gst_rtsp_media_unsuspend (media));
/* sync end of other thread */
g_thread_join (sharing_media_thread);
/* clean up */
g_cond_clear (&sync_cond);
g_mutex_clear (&sync_mutex);
fail_unless (gst_rtsp_media_unprepare (media));
g_object_unref (media);
gst_rtsp_url_free (url);
g_object_unref (factory);
g_object_unref (pool);
gst_rtsp_thread_pool_cleanup ();
}
GST_END_TEST;
#define FLAG_HAVE_CAPS GST_ELEMENT_FLAG_LAST
static void
on_notify_caps (GstPad * pad, GParamSpec * pspec, GstElement * pay)
{
GstCaps *caps;
g_object_get (pad, "caps", &caps, NULL);
GST_DEBUG ("notify %" GST_PTR_FORMAT, caps);
if (caps) {
if (!GST_OBJECT_FLAG_IS_SET (pay, FLAG_HAVE_CAPS)) {
g_signal_emit_by_name (pay, "pad-added", pad);
g_signal_emit_by_name (pay, "no-more-pads", NULL);
GST_OBJECT_FLAG_SET (pay, FLAG_HAVE_CAPS);
}
gst_caps_unref (caps);
} else {
if (GST_OBJECT_FLAG_IS_SET (pay, FLAG_HAVE_CAPS)) {
g_signal_emit_by_name (pay, "pad-removed", pad);
GST_OBJECT_FLAG_UNSET (pay, FLAG_HAVE_CAPS);
}
}
}
GST_START_TEST (test_media_dyn_prepare)
{
GstRTSPMedia *media;
GstElement *bin, *src, *pay;
GstElement *pipeline;
GstPad *srcpad;
GstRTSPThreadPool *pool;
GstRTSPThread *thread;
bin = gst_bin_new ("bin");
fail_if (bin == NULL);
src = gst_element_factory_make ("videotestsrc", NULL);
fail_if (src == NULL);
pay = gst_element_factory_make ("rtpvrawpay", "dynpay0");
fail_if (pay == NULL);
g_object_set (pay, "pt", 96, NULL);
gst_bin_add_many (GST_BIN_CAST (bin), src, pay, NULL);
gst_element_link_many (src, pay, NULL);
media = gst_rtsp_media_new (bin);
fail_unless (GST_IS_RTSP_MEDIA (media));
g_object_set (G_OBJECT (media), "reusable", TRUE, NULL);
pipeline = gst_pipeline_new ("media-pipeline");
gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline));
gst_rtsp_media_collect_streams (media);
srcpad = gst_element_get_static_pad (pay, "src");
g_signal_connect (srcpad, "notify::caps", (GCallback) on_notify_caps, pay);
pool = gst_rtsp_thread_pool_new ();
fail_unless (gst_rtsp_media_n_streams (media) == 0);
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_unless (gst_rtsp_media_prepare (media, thread));
fail_unless (gst_rtsp_media_n_streams (media) == 1);
fail_unless (media_has_sdp (media));
fail_unless_equals_int64 (gst_rtsp_media_seekable (media), G_MAXINT64);
fail_unless (gst_rtsp_media_unprepare (media));
fail_unless (gst_rtsp_media_n_streams (media) == 0);
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_unless (gst_rtsp_media_prepare (media, thread));
fail_unless (gst_rtsp_media_n_streams (media) == 1);
fail_unless (media_has_sdp (media));
fail_unless_equals_int64 (gst_rtsp_media_seekable (media), G_MAXINT64);
fail_unless (gst_rtsp_media_unprepare (media));
fail_unless (gst_rtsp_media_n_streams (media) == 0);
gst_object_unref (srcpad);
g_object_unref (media);
g_object_unref (pool);
gst_rtsp_thread_pool_cleanup ();
}
GST_END_TEST;
GST_START_TEST (test_media_take_pipeline)
{
GstRTSPMediaFactory *factory;
GstRTSPMedia *media;
GstRTSPUrl *url;
GstElement *pipeline;
factory = gst_rtsp_media_factory_new ();
fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test",
&url) == GST_RTSP_OK);
gst_rtsp_media_factory_set_launch (factory,
"( fakesrc ! text/plain ! rtpgstpay name=pay0 )");
media = gst_rtsp_media_factory_construct (factory, url);
fail_unless (GST_IS_RTSP_MEDIA (media));
pipeline = gst_pipeline_new ("media-pipeline");
gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline));
g_object_unref (media);
gst_rtsp_url_free (url);
g_object_unref (factory);
}
GST_END_TEST;
GST_START_TEST (test_media_reset)
{
GstRTSPMediaFactory *factory;
GstRTSPMedia *media;
GstRTSPUrl *url;
GstRTSPThreadPool *pool;
GstRTSPThread *thread;
pool = gst_rtsp_thread_pool_new ();
factory = gst_rtsp_media_factory_new ();
fail_if (gst_rtsp_media_factory_is_shared (factory));
gst_rtsp_url_parse ("rtsp://localhost:8554/test", &url);
gst_rtsp_media_factory_set_launch (factory,
"( videotestsrc ! rtpvrawpay pt=96 name=pay0 )");
media = gst_rtsp_media_factory_construct (factory, url);
fail_unless (GST_IS_RTSP_MEDIA (media));
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_unless (gst_rtsp_media_prepare (media, thread));
fail_unless (media_has_sdp (media));
fail_unless_equals_int64 (gst_rtsp_media_seekable (media), G_MAXINT64);
fail_unless (gst_rtsp_media_suspend (media));
fail_unless (gst_rtsp_media_unprepare (media));
g_object_unref (media);
media = gst_rtsp_media_factory_construct (factory, url);
fail_unless (GST_IS_RTSP_MEDIA (media));
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
gst_rtsp_media_set_suspend_mode (media, GST_RTSP_SUSPEND_MODE_RESET);
fail_unless (gst_rtsp_media_prepare (media, thread));
fail_unless (media_has_sdp (media));
fail_unless_equals_int64 (gst_rtsp_media_seekable (media), G_MAXINT64);
fail_unless (gst_rtsp_media_suspend (media));
fail_unless (gst_rtsp_media_unprepare (media));
g_object_unref (media);
gst_rtsp_url_free (url);
g_object_unref (factory);
g_object_unref (pool);
gst_rtsp_thread_pool_cleanup ();
}
GST_END_TEST;
GST_START_TEST (test_media_multidyn_prepare)
{
GstRTSPMedia *media;
GstElement *bin, *src0, *pay0, *src1, *pay1;
GstElement *pipeline;
GstPad *srcpad0, *srcpad1;
GstRTSPThreadPool *pool;
GstRTSPThread *thread;
bin = gst_bin_new ("bin");
fail_if (bin == NULL);
src0 = gst_element_factory_make ("videotestsrc", NULL);
fail_if (src0 == NULL);
pay0 = gst_element_factory_make ("rtpvrawpay", "dynpay0");
fail_if (pay0 == NULL);
g_object_set (pay0, "pt", 96, NULL);
src1 = gst_element_factory_make ("videotestsrc", NULL);
fail_if (src1 == NULL);
pay1 = gst_element_factory_make ("rtpvrawpay", "dynpay1");
fail_if (pay1 == NULL);
g_object_set (pay1, "pt", 97, NULL);
gst_bin_add_many (GST_BIN_CAST (bin), src0, pay0, src1, pay1, NULL);
gst_element_link_many (src0, pay0, NULL);
gst_element_link_many (src1, pay1, NULL);
media = gst_rtsp_media_new (bin);
fail_unless (GST_IS_RTSP_MEDIA (media));
g_object_set (G_OBJECT (media), "reusable", TRUE, NULL);
pipeline = gst_pipeline_new ("media-pipeline");
gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline));
gst_rtsp_media_collect_streams (media);
srcpad0 = gst_element_get_static_pad (pay0, "src");
srcpad1 = gst_element_get_static_pad (pay1, "src");
g_signal_connect (srcpad0, "notify::caps", (GCallback) on_notify_caps, pay0);
g_signal_connect (srcpad1, "notify::caps", (GCallback) on_notify_caps, pay1);
pool = gst_rtsp_thread_pool_new ();
fail_unless_equals_int (gst_rtsp_media_n_streams (media), 0);
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_unless (gst_rtsp_media_prepare (media, thread));
fail_unless_equals_int (gst_rtsp_media_n_streams (media), 2);
fail_unless (media_has_sdp (media));
fail_unless_equals_int64 (gst_rtsp_media_seekable (media), G_MAXINT64);
fail_unless (gst_rtsp_media_unprepare (media));
fail_unless_equals_int (gst_rtsp_media_n_streams (media), 0);
thread = gst_rtsp_thread_pool_get_thread (pool,
GST_RTSP_THREAD_TYPE_MEDIA, NULL);
fail_unless (gst_rtsp_media_prepare (media, thread));
fail_unless_equals_int (gst_rtsp_media_n_streams (media), 2);
fail_unless (media_has_sdp (media));
fail_unless_equals_int64 (gst_rtsp_media_seekable (media), G_MAXINT64);
fail_unless (gst_rtsp_media_unprepare (media));
fail_unless_equals_int (gst_rtsp_media_n_streams (media), 0);
gst_object_unref (srcpad0);
gst_object_unref (srcpad1);
g_object_unref (media);
g_object_unref (pool);
gst_rtsp_thread_pool_cleanup ();
}
GST_END_TEST;
static Suite *
rtspmedia_suite (void)
{
Suite *s = suite_create ("rtspmedia");
TCase *tc = tcase_create ("general");
suite_add_tcase (s, tc);
tcase_set_timeout (tc, 20);
tcase_add_test (tc, test_media_seek);
tcase_add_test (tc, test_media_seek_no_sinks);
tcase_add_test (tc, test_media_seek_one_active_stream);
tcase_add_test (tc, test_media);
tcase_add_test (tc, test_media_prepare);
tcase_add_test (tc, test_media_shared_race_test_unsuspend_vs_set_state_null);
tcase_add_test (tc, test_media_reusable);
tcase_add_test (tc, test_media_dyn_prepare);
tcase_add_test (tc, test_media_take_pipeline);
tcase_add_test (tc, test_media_reset);
tcase_add_test (tc, test_media_multidyn_prepare);
return s;
}
GST_CHECK_MAIN (rtspmedia);