[farsight2/master] Implement complete 2 person test
Olivier Crête
olivier.crete at collabora.co.uk
Tue Dec 23 15:20:23 PST 2008
---
tests/check/main/generic.c | 112 ++++++++++++
tests/check/main/generic.h | 26 +++-
tests/check/main/rtpconference.c | 370 ++++++++++++++++++++++++++++++++++----
3 files changed, 472 insertions(+), 36 deletions(-)
diff --git a/tests/check/main/generic.c b/tests/check/main/generic.c
index 008242d..9001d4d 100644
--- a/tests/check/main/generic.c
+++ b/tests/check/main/generic.c
@@ -18,8 +18,120 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
#include "generic.h"
+#include <gst/check/gstcheck.h>
+#include <gst/farsight/fs-conference-iface.h>
+struct SimpleTestConference *
+setup_simple_conference (
+ gchar *conference_elem,
+ gchar *cname)
+{
+ struct SimpleTestConference *dat = g_new0 (struct SimpleTestConference, 1);
+ GError *error = NULL;
+
+ dat->pipeline = gst_pipeline_new ("pipeline");
+ fail_if (dat->pipeline == NULL);
+
+ dat->conference = gst_element_factory_make (conference_elem, NULL);
+ fail_if (dat->conference == NULL, "Could not build %s", conference_elem);
+ fail_unless (gst_bin_add (GST_BIN (dat->pipeline), dat->conference),
+ "Could not add conference to the pipeline");
+
+ dat->session = fs_conference_new_session (FS_CONFERENCE (dat->conference),
+ FS_MEDIA_TYPE_AUDIO, &error);
+ if (error)
+ fail ("Error while creating new session (%d): %s",
+ error->code, error->message);
+ fail_if (dat->session == NULL, "Could not make session, but no GError!");
+
+ dat->participant = fs_conference_new_participant (
+ FS_CONFERENCE (dat->conference), cname, &error);
+ if (error)
+ fail ("Error while creating new participant (%d): %s",
+ error->code, error->message);
+ fail_if (dat->session == NULL, "Could not make participant, but no GError!");
+
+ dat->stream = fs_session_new_stream (dat->session, dat->participant,
+ FS_DIRECTION_BOTH, "rawudp", 0, NULL, &error);
+ if (error)
+ fail ("Error while creating new stream (%d): %s",
+ error->code, error->message);
+ fail_if (dat->stream == NULL, "Could not make stream, but no GError!");
+
+ return dat;
+}
+
+
+void
+cleanup_simple_conference (struct SimpleTestConference *dat)
+{
+
+ g_object_unref (dat->stream);
+ g_object_unref (dat->session);
+ g_object_unref (dat->participant);
+ gst_object_unref (dat->pipeline);
+ g_free (dat);
+}
+
+
+void
+setup_fakesrc (struct SimpleTestConference *dat)
+{
+ GstElement *capsfilter = NULL;
+ GstCaps *caps = NULL;
+ GstPad *sinkpad = NULL, *srcpad = NULL;
+
+ g_debug ("Adding fakesrc");
+
+ capsfilter = gst_element_factory_make ("capsfilter", NULL);
+ fail_if (capsfilter == NULL, "Could not make capsfilter");
+ gst_bin_add (GST_BIN (dat->pipeline), capsfilter);
+
+ caps = gst_caps_new_simple ("audio/x-raw-int",
+ "rate", G_TYPE_INT, 8000,
+ "channels", G_TYPE_INT, 1,
+ NULL);
+
+ g_object_set (capsfilter, "caps", caps, NULL);
+
+ gst_caps_unref (caps);
+
+ g_object_get (dat->session, "sink-pad", &sinkpad, NULL);
+ fail_if (sinkpad == NULL, "Could not get session sinkpad");
+
+ srcpad = gst_element_get_static_pad (capsfilter, "src");
+
+ fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK,
+ "Could not link the capsfilter and the fsrtpconference");
+
+ gst_object_unref (sinkpad);
+ gst_object_unref (srcpad);
+
+ dat->fakesrc = gst_element_factory_make ("fakesrc", NULL);
+ fail_if (dat->fakesrc == NULL, "Could not make fakesrc");
+ gst_bin_add (GST_BIN (dat->pipeline), dat->fakesrc);
+
+ g_object_set (dat->fakesrc,
+ /* "num-buffers", 2000, */
+ "sizetype", 2,
+ "sizemax", 10,
+ "is-live", TRUE,
+ NULL);
+
+ fail_unless (gst_element_link_pads (dat->fakesrc, "src", capsfilter, "sink"),
+ "Could not link capsfilter to sink");
+
+ if (dat->started)
+ {
+ gst_element_set_state (dat->pipeline, GST_STATE_PLAYING);
+ dat->started = TRUE;
+ }
+
+}
diff --git a/tests/check/main/generic.h b/tests/check/main/generic.h
index 54d97a9..d431820 100644
--- a/tests/check/main/generic.h
+++ b/tests/check/main/generic.h
@@ -19,12 +19,32 @@
*/
-#include <gst/gst.h>
-
#ifndef __GENERIC_H__
#define __GENERIC_H__
-GstElement *setup_pipeline (gchar *conference_elem);
+#include <gst/gst.h>
+#include <gst/farsight/fs-conference-iface.h>
+
+struct SimpleTestConference {
+ GstElement *pipeline;
+ GstElement *conference;
+ FsSession *session;
+ FsParticipant *participant;
+ FsStream *stream;
+ GstElement *fakesrc;
+
+ gint buffer_count;
+
+ gboolean started;
+};
+
+struct SimpleTestConference *setup_simple_conference (
+ gchar *conference_elem,
+ gchar *cname);
+
+void setup_fakesrc (struct SimpleTestConference *dat);
+
+void cleanup_simple_conference (struct SimpleTestConference *dat);
#endif /* __GENERIC_H__ */
diff --git a/tests/check/main/rtpconference.c b/tests/check/main/rtpconference.c
index 3c70674..417ce7d 100644
--- a/tests/check/main/rtpconference.c
+++ b/tests/check/main/rtpconference.c
@@ -27,55 +27,353 @@
#include "generic.h"
+struct SimpleTestConference *dat1 = NULL;
+struct SimpleTestConference *dat2 = NULL;
+GMainLoop *loop;
+
+
GST_START_TEST (test_rtpconference_new)
{
- GstElement *pipeline = gst_pipeline_new ("pipeline");
- GstElement *conference = NULL;
- FsSession *session;
- FsParticipant *participant;
- FsStream *stream;
+ struct SimpleTestConference *dat = NULL;
+ guint id = 999;
+ GList *local_codecs = NULL;
+ FsMediaType *media_type;
+ GstPad *sinkpad = NULL;
+ gchar *str;
+
+ dat = setup_simple_conference ("fsrtpconference", "bob at 127.0.0.1");
+
+ g_object_get (dat->session,
+ "id", &id,
+ "local-codecs", &local_codecs,
+ "media-type", &media_type,
+ "sink-pad", &sinkpad,
+ NULL);
+
+ fail_unless (id == 1, "The id of the first session should be 1 not %d", id);
+ fail_if (local_codecs == NULL, "Local codecs should not be NULL");
+ fail_unless (media_type == FS_MEDIA_TYPE_AUDIO, "Media type isnt audio,"
+ " its %d", media_type);
+ fail_if (sinkpad == NULL, "Sink pad should not be null");
+ str = g_strdup_printf ("sink_%d", id);
+ fail_unless (!strcmp (str, GST_OBJECT_NAME (sinkpad)), "Sink pad is %s"
+ " instead of being %d", GST_OBJECT_NAME (sinkpad), str);
+ g_free (str);
+
+ cleanup_simple_conference (dat);
+}
+GST_END_TEST;
+
+static gboolean
+_simple_bus_callback (GstBus *bus, GstMessage *message, gpointer user_data)
+{
+
+ switch (GST_MESSAGE_TYPE (message))
+ {
+ case GST_MESSAGE_ELEMENT:
+ if (gst_implements_interface_check (GST_MESSAGE_SRC (message),
+ FS_TYPE_CONFERENCE))
+ {
+ const GValue *errorvalue, *debugvalue;
+ gint errno;
+
+ gst_structure_get_int (message->structure, "error-no", &errno);
+ errorvalue = gst_structure_get_value (message->structure, "error-msg");
+ debugvalue = gst_structure_get_value (message->structure, "debug-msg");
+
+ fail ("Error on BUS (%d) %s .. %s", errno,
+ g_value_get_string (errorvalue),
+ g_value_get_string (debugvalue));
+ }
+
+ break;
+ case GST_MESSAGE_ERROR:
+ {
+ GError *error = NULL;
+ gchar *debug = NULL;
+ gst_message_parse_error (message, &error, &debug);
+
+ fail ("Got an error on the BUS (%d): %s (%s)", error->code,
+ error->message, debug);
+ g_error_free (error);
+ g_free (debug);
+ }
+ break;
+ case GST_MESSAGE_WARNING:
+ {
+ GError *error = NULL;
+ gchar *debug = NULL;
+ gst_message_parse_warning (message, &error, &debug);
+
+ g_debug ("Got a warning on the BUS (%d): %s (%s)", error->code,
+ error->message, debug);
+ g_error_free (error);
+ g_free (debug);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+static void
+_simple_send_codec_changed (FsSession *session, gpointer user_data)
+{
+ FsCodec *codec = NULL;
+ gchar *str = NULL;
+
+ g_object_get (session, "current-send-codec", &codec, NULL);
+ fail_if (codec == NULL, "Could not get new send codec");
+
+ str = fs_codec_to_string (codec);
+ g_debug ("New send codec: %s", str);
+ g_free (str);
+
+ fs_codec_destroy (codec);
+}
+
+static void
+_handoff_handler (GstElement *element, GstBuffer *buffer, GstPad *pad,
+ gpointer user_data)
+{
+ struct SimpleTestConference *dat = user_data;
+
+ g_debug ("Buffer");
+
+ dat->buffer_count++;
+
+ /*
+ fail_if (dat->buffer_count > 20,
+ "Too many buffers %d > 20", dat->buffer_count);
+ */
+
+ if (dat->buffer_count >= 20) {
+ /* TEST OVER */
+ g_main_loop_quit (loop);
+ }
+}
+
+static void
+_src_pad_added (FsStream *self, GstPad *pad, FsCodec *codec, gpointer user_data)
+{
+ struct SimpleTestConference *dat = user_data;
+ GstElement *fakesink = gst_element_factory_make ("fakesink", NULL);
+ GstPad *fakesink_pad = NULL;
+ GstPadLinkReturn ret;
+
+ g_assert (fakesink);
+
+ g_object_set (fakesink,
+ "signal-handoffs", TRUE,
+ "sync", TRUE,
+ "async", TRUE,
+ NULL);
+
+ g_signal_connect (fakesink, "handoff", G_CALLBACK (_handoff_handler), dat);
+
+ gst_bin_add (GST_BIN (dat->pipeline), fakesink);
+
+ fakesink_pad = gst_element_get_static_pad (fakesink, "sink");
+ ret = gst_pad_link (pad, fakesink_pad);
+ gst_object_unref (fakesink_pad);
+
+ fail_if (GST_PAD_LINK_FAILED(ret), "Could not link fakesink");
+
+ fail_if (gst_element_set_state (fakesink, GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE, "Could not set the fakesink to playing");
+
+ g_debug ("Added Fakesink");
+}
+
+
+static void
+_new_active_candidate_pair (FsStream *stream, FsCandidate *local,
+ FsCandidate *remote, gpointer user_data)
+{
+ struct SimpleTestConference *dat = user_data;
+
+ fail_if (local == NULL, "Local candidate NULL");
+ fail_if (remote == NULL, "Remote candidate NULL");
+
+ if (local->component_id != 1)
+ return;
+
+ if (!dat->fakesrc)
+ setup_fakesrc (dat);
+}
+
+
+void
+rtpconference_simple_connect_signals (struct SimpleTestConference *dat)
+{
+ GstBus *bus = NULL;
+
+ bus = gst_element_get_bus (dat->pipeline);
+ gst_bus_add_watch (bus, _simple_bus_callback, dat);
+ gst_object_unref (bus);
+
+ g_signal_connect (dat->session, "send-codec-changed",
+ G_CALLBACK (_simple_send_codec_changed), dat);
+
+ g_signal_connect (dat->stream, "src-pad-added", G_CALLBACK (_src_pad_added),
+ dat);
+
+ g_signal_connect (dat->stream, "new-active-candidate-pair",
+ G_CALLBACK (_new_active_candidate_pair), dat);
+}
+
+
+static gboolean
+_start_pipeline (gpointer user_data)
+{
+ struct SimpleTestConference *dat = user_data;
+
+ g_debug ("Starting pipeline");
+
+ fail_if (gst_element_set_state (dat->pipeline, GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE, "Could not set the pipeline to playing");
+
+ dat->started = TRUE;
+
+ return FALSE;
+}
+
+static void
+_new_negotiated_codecs (FsSession *session, gpointer user_data)
+{
+ GList *codecs = NULL;
GError *error = NULL;
- conference = gst_element_factory_make ("fsrtpconference", NULL);
- fail_if (conference == NULL, "Could not buld fsrtpconference");
- fail_unless (gst_bin_add (GST_BIN (pipeline), conference),
- "Could not add conference to the pipeline");
+ g_debug ("New negotiated codecs");
- session = fs_conference_new_session (FS_CONFERENCE (conference),
- FS_MEDIA_TYPE_AUDIO, &error);
- if (error)
- fail ("Error while creating new session (%d): %s",
- error->code, error->message);
- fail_if (session == NULL, "Could not make session, but no GError!");
+ fail_if (session != dat2->session, "Got signal from the wrong object");
+
+ g_object_get (dat2->session, "negotiated-codecs", &codecs, NULL);
+ fail_if (codecs == NULL, "Could not get the negotiated codecs");
- participant = fs_conference_new_participant (FS_CONFERENCE (conference),
- "bob at 127.0.0.1", &error);
- if (error)
- fail ("Error while creating new participant (%d): %s",
- error->code, error->message);
- fail_if (session == NULL, "Could not make participant, but no GError!");
- stream = fs_session_new_stream (session, participant, FS_DIRECTION_NONE,
- "rawudp", 0, NULL, &error);
+ if (!fs_stream_set_remote_codecs (dat1->stream, codecs, &error))
+ {
+ if (error)
+ fail ("Could not set the remote codecs on dat1 (%d): %s", error->code,
+ error->message);
+ else
+ fail ("Could not set the remote codecs on dat1"
+ " and we DID not get a GError!!");
+ }
+
+ fs_codec_list_destroy (codecs);
+}
+
+
+static void
+_new_local_candidate (FsStream *stream, FsCandidate *candidate,
+ gpointer user_data)
+{
+ struct SimpleTestConference *other_dat = user_data;
+ gboolean ret;
+ GError *error = NULL;
+
+ g_debug ("New local candidate");
+
+ ret = fs_stream_add_remote_candidate (other_dat->stream, candidate, &error);
+
if (error)
- fail ("Error while creating new stream (%d): %s",
- error->code, error->message);
- fail_if (session == NULL, "Could not make stream, but no GError!");
-
- g_object_unref (stream);
- g_object_unref (session);
- g_object_unref (participant);
- gst_object_unref (pipeline);
+ fail ("Error while adding candidate: (%s:%d) %s",
+ g_quark_to_string (error->domain), error->code, error->message);
+
+ fail_unless(ret == TRUE, "No detailed error from add_remote_candidate");
+
+}
+
+void
+set_local_codecs (void)
+{
+ GList *local_codecs = NULL;
+ GList *filtered_codecs = NULL;
+ GList *item = NULL;
+ GError *error = NULL;
+
+ g_object_get (dat1->session, "local-codecs", &local_codecs, NULL);
+
+ fail_if (local_codecs == NULL, "Could not get the local codecs");
+
+ for (item = g_list_first (local_codecs); item; item = g_list_next (item))
+ {
+ FsCodec *codec = item->data;
+ if (codec->id == 0 || codec->id == 8)
+ filtered_codecs = g_list_append (filtered_codecs, codec);
+ }
+
+ fail_if (filtered_codecs == NULL, "PCMA and PCMU are not in the codecs"
+ " you must install gst-plugins-good");
+
+
+ if (!fs_stream_set_remote_codecs (dat2->stream, filtered_codecs, &error))
+ {
+ if (error)
+ fail ("Could not set the remote codecs on dat2 (%d): %s", error->code,
+ error->message);
+ else
+ fail ("Could not set the remote codecs on dat2"
+ " and we DID not get a GError!!");
+ }
+
+ g_list_free (filtered_codecs);
+ fs_codec_list_destroy (local_codecs);
+}
+
+
+GST_START_TEST (test_rtpconference_simple)
+{
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ dat1 = setup_simple_conference ("fsrtpconference", "tester at TesterTop3");
+ dat2 = setup_simple_conference ("fsrtpconference", "tester at TesterTop3");
+
+ rtpconference_simple_connect_signals (dat1);
+ rtpconference_simple_connect_signals (dat2);
+
+ g_idle_add (_start_pipeline, dat1);
+ g_idle_add (_start_pipeline, dat2);
+
+ g_signal_connect (dat2->session, "new-negotiated-codecs",
+ G_CALLBACK (_new_negotiated_codecs), NULL);
+
+ set_local_codecs ();
+
+ g_signal_connect (dat1->stream, "new-local-candidate",
+ G_CALLBACK (_new_local_candidate), dat2);
+ g_signal_connect (dat2->stream, "new-local-candidate",
+ G_CALLBACK (_new_local_candidate), dat1);
+
+ g_main_loop_run (loop);
+
+ gst_element_set_state (dat1->pipeline, GST_STATE_NULL);
+ gst_element_set_state (dat2->pipeline, GST_STATE_NULL);
+
+ cleanup_simple_conference (dat1);
+ cleanup_simple_conference (dat2);
+
+ g_main_loop_unref (loop);
}
GST_END_TEST;
static Suite *
-rawudptransmitter_suite (void)
+fsrtpconference_suite (void)
{
Suite *s = suite_create ("fsrtpconference");
TCase *tc_chain;
+ GLogLevelFlags fatal_mask;
+
+ fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
+ fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
+ g_log_set_always_fatal (fatal_mask);
tc_chain = tcase_create ("fsrtpconfence_base");
@@ -84,8 +382,14 @@ rawudptransmitter_suite (void)
suite_add_tcase (s, tc_chain);
+ tc_chain = tcase_create ("fsrtpconfence_simple");
+ tcase_set_timeout (tc_chain, 10);
+ tcase_add_test (tc_chain, test_rtpconference_simple);
+ suite_add_tcase (s, tc_chain);
+
+
return s;
}
-GST_CHECK_MAIN (rawudptransmitter);
+GST_CHECK_MAIN (fsrtpconference);
--
1.5.6.5
More information about the farsight-commits
mailing list