diff --git a/livesupport/modules/gstreamerElements/etc/Makefile.in b/livesupport/modules/gstreamerElements/etc/Makefile.in index 35f626164..4977e6e47 100644 --- a/livesupport/modules/gstreamerElements/etc/Makefile.in +++ b/livesupport/modules/gstreamerElements/etc/Makefile.in @@ -21,7 +21,7 @@ # # # Author : $Author: maroy $ -# Version : $Revision: 1.5 $ +# Version : $Revision: 1.6 $ # Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/etc/Makefile.in,v $ # # @configure_input@ @@ -140,7 +140,7 @@ PARTIAL_PLAY_LIB_OBJS = ${TMP_DIR}/partial-play.o SWITCHER_LIB_OBJS = ${TMP_DIR}/switcher.o TEST_RUNNER_OBJS = ${TMP_DIR}/TestRunner.o \ - ${TMP_DIR}/AutoplugTest.o \ + ${TMP_DIR}/AutoplugTest.o \ ${TMP_DIR}/SeekTest.o \ ${TMP_DIR}/SwitcherTest.o \ ${TMP_DIR}/SeekPackTest.o \ @@ -201,16 +201,16 @@ check: all ${TEST_RUNNER} ${GSTREAMER_ELEMENTS_LIB_FILE}: ${GSTREAMER_ELEMENTS_LIB_OBJS} ${AR} crus $@ $^ -${ONESHOT_READER_LIB_FILE}: ${GSTREAMER_ELEMENTS_LIB_FILE} \ - ${ONESHOT_READER_LIB_OBJS} +${ONESHOT_READER_LIB_FILE}: ${ONESHOT_READER_LIB_OBJS} \ + ${GSTREAMER_ELEMENTS_LIB_FILE} ${CC} -shared -o $@ $^ ${GST_LDFLAGS} -${MINIMAL_AUDIO_SMIL_LIB_FILE}: ${GSTREAMER_ELEMENTS_LIB_FILE} \ - ${MINIMAL_AUDIO_SMIL_LIB_OBJS} +${MINIMAL_AUDIO_SMIL_LIB_FILE}: ${MINIMAL_AUDIO_SMIL_LIB_OBJS} \ + ${GSTREAMER_ELEMENTS_LIB_FILE} ${CC} -shared -o $@ $^ ${GST_LDFLAGS} -${PARTIAL_PLAY_LIB_FILE}: ${GSTREAMER_ELEMENTS_LIB_FILE} \ - ${PARTIAL_PLAY_LIB_OBJS} +${PARTIAL_PLAY_LIB_FILE}: ${PARTIAL_PLAY_LIB_OBJS} \ + ${GSTREAMER_ELEMENTS_LIB_FILE} ${CC} -shared -o $@ $^ ${GST_LDFLAGS} ${SWITCHER_LIB_FILE}: ${SWITCHER_LIB_OBJS} \ diff --git a/livesupport/modules/gstreamerElements/src/AutoplugTest.cxx b/livesupport/modules/gstreamerElements/src/AutoplugTest.cxx index ffa8215cb..d3d7f9b87 100644 --- a/livesupport/modules/gstreamerElements/src/AutoplugTest.cxx +++ b/livesupport/modules/gstreamerElements/src/AutoplugTest.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.2 $ + Version : $Revision: 1.3 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/src/AutoplugTest.cxx,v $ ------------------------------------------------------------------------------*/ @@ -61,6 +61,16 @@ static const char * mp3TestFile = "var/5seccounter.mp3"; */ static const char * oggTestFile = "var/5seccounter.ogg"; +/** + * A SMIL test file. + */ +static const char * smilTestFile = "var/simple.smil"; + +/** + * A file we can't plug. + */ +static const char * badFile = "src/AutoplugTest.cxx"; + /* =============================================== local function prototypes */ @@ -111,6 +121,14 @@ AutoplugTest :: playFile(const char * audioFile) decoder = autoplug_plug_source(source); + if (!decoder) { + gst_object_unref(GST_OBJECT(sink)); + gst_object_unref(GST_OBJECT(source)); + gst_object_unref(GST_OBJECT(pipeline)); + + return 0LL; + } + gst_element_link(decoder, sink); gst_bin_add_many(GST_BIN(pipeline), source, decoder, sink, NULL); @@ -130,7 +148,7 @@ AutoplugTest :: playFile(const char * audioFile) /* clean up nicely */ gst_element_set_state(pipeline, GST_STATE_NULL); - gst_object_unref(GST_OBJECT (pipeline)); + gst_object_unref(GST_OBJECT(pipeline)); return timePlayed; } @@ -169,3 +187,36 @@ AutoplugTest :: oggVorbisTest(void) CPPUNIT_ASSERT_MESSAGE(str, timePlayed < 5.1 * GST_SECOND); } + +/*------------------------------------------------------------------------------ + * A SMIL test. + *----------------------------------------------------------------------------*/ +void +AutoplugTest :: smilTest(void) + throw (CPPUNIT_NS::Exception) +{ + gint64 timePlayed; + char str[256]; + + timePlayed = playFile(smilTestFile); + g_snprintf(str, 256, "time played: %" G_GINT64_FORMAT, timePlayed); + CPPUNIT_ASSERT_MESSAGE(str, timePlayed > 4.9 * GST_SECOND); + CPPUNIT_ASSERT_MESSAGE(str, timePlayed < 5.1 * GST_SECOND); +} + + +/*------------------------------------------------------------------------------ + * Test somethign we can't plug. + *----------------------------------------------------------------------------*/ +void +AutoplugTest :: negativeTest(void) + throw (CPPUNIT_NS::Exception) +{ + gint64 timePlayed; + char str[256]; + + timePlayed = playFile(badFile); + g_snprintf(str, 256, "time played: %" G_GINT64_FORMAT, timePlayed); + CPPUNIT_ASSERT_MESSAGE(str, timePlayed == 0LL); +} + diff --git a/livesupport/modules/gstreamerElements/src/AutoplugTest.h b/livesupport/modules/gstreamerElements/src/AutoplugTest.h index e65a8450e..2ae74652e 100644 --- a/livesupport/modules/gstreamerElements/src/AutoplugTest.h +++ b/livesupport/modules/gstreamerElements/src/AutoplugTest.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/src/AutoplugTest.h,v $ ------------------------------------------------------------------------------*/ @@ -58,13 +58,15 @@ namespace GstreamerElements { * Unit test for the partialplay gstreamer element. * * @author $Author: maroy $ - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ class AutoplugTest : public CPPUNIT_NS::TestFixture { CPPUNIT_TEST_SUITE(AutoplugTest); CPPUNIT_TEST(firstTest); CPPUNIT_TEST(oggVorbisTest); + CPPUNIT_TEST(smilTest); + CPPUNIT_TEST(negativeTest); CPPUNIT_TEST_SUITE_END(); private: @@ -99,6 +101,22 @@ class AutoplugTest : public CPPUNIT_NS::TestFixture void oggVorbisTest(void) throw (CPPUNIT_NS::Exception); + /** + * Test a SMIL file. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + smilTest(void) throw (CPPUNIT_NS::Exception); + + /** + * A negative test. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + negativeTest(void) throw (CPPUNIT_NS::Exception); + public: diff --git a/livesupport/modules/gstreamerElements/src/OneshotReaderTest.cxx b/livesupport/modules/gstreamerElements/src/OneshotReaderTest.cxx index 09652c41c..39f879464 100644 --- a/livesupport/modules/gstreamerElements/src/OneshotReaderTest.cxx +++ b/livesupport/modules/gstreamerElements/src/OneshotReaderTest.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/src/OneshotReaderTest.cxx,v $ ------------------------------------------------------------------------------*/ @@ -125,7 +125,7 @@ OneshotReaderTest :: firstTest(void) gst_element_set_state(pipeline, GST_STATE_PLAYING); // well, actually don't run, by setting to state PLAYING, // we already have what we're looking for. - //while (gst_bin_iterate (GST_BIN (pipeline))); + while (gst_bin_iterate(GST_BIN(pipeline))); g_object_get(G_OBJECT(oneshot), "contents", &contents, NULL); g_object_get(G_OBJECT(oneshot), "length", &length, NULL); @@ -135,7 +135,6 @@ OneshotReaderTest :: firstTest(void) verifyContents = new char[length]; ifs.open(testFile); CPPUNIT_ASSERT(ifs.good()); - // read length - 1, as oneshotreader appends an extra NULL character ifs.read(verifyContents, length); CPPUNIT_ASSERT(!memcmp(contents, verifyContents, length)); diff --git a/livesupport/modules/gstreamerElements/src/autoplug.c b/livesupport/modules/gstreamerElements/src/autoplug.c index 496585289..877466cf7 100644 --- a/livesupport/modules/gstreamerElements/src/autoplug.c +++ b/livesupport/modules/gstreamerElements/src/autoplug.c @@ -27,7 +27,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/src/autoplug.c,v $ ------------------------------------------------------------------------------*/ @@ -106,6 +106,14 @@ autoplug_typefound_handler(GstElement * typefind, static void autoplug_init(Typefind * typefind); +/** + * De-initialize a typefind object. + * + * @param typefind the Typefind structure to de-init. + */ +static void +autoplug_deinit(Typefind * typefind); + /** * A filter specifying the kind of factories we're interested in. * @@ -176,11 +184,15 @@ autoplug_newpad(GstElement * element, * Remove all typefind elements inside the bin, traversing to lower binds * if necessary. The pads linked through the removed typefind elements are * linked directly instead. + * The typefind member of the supplied Typefind object is also removed, + * and changed to NULL. * + * @param typefind the typefind object to work on. * @param bin the bin to remove the typefind elements from. */ static void -autoplug_remove_typefind_elements(GstBin * bin); +autoplug_remove_typefind_elements(Typefind * typefind, + GstBin * bin); /* ============================================================= module code */ @@ -277,6 +289,28 @@ autoplug_init(Typefind * typefind) typefind->done = FALSE; } +/*------------------------------------------------------------------------------ + * De-initialize a Typefind object. + *----------------------------------------------------------------------------*/ +static void +autoplug_deinit(Typefind * typefind) +{ + g_list_free(typefind->factories); + + if (typefind->typefind) { + g_signal_handler_disconnect(typefind->typefind, + typefind->typefindSignal); + } + + if (typefind->audiosink && !gst_element_get_parent(typefind->audiosink)) { + gst_object_unref(GST_OBJECT(typefind->audiosink)); + } + if (typefind->sink && !gst_element_get_parent(typefind->sink)) { + gst_object_unref(GST_OBJECT(typefind->sink)); + } + gst_object_unref(GST_OBJECT(typefind->pipeline)); +} + /*------------------------------------------------------------------------------ * Handle the event of a new pad being created on an element with @@ -311,20 +345,37 @@ autoplug_close_link(Typefind * typefind, const gchar * padname, const GList * templlist) { - GstPad * pad; - gboolean has_dynamic_pads = FALSE; + GstPad * pad; + gboolean has_dynamic_pads = FALSE; + GstElement * srcelement; + + srcelement = GST_ELEMENT(gst_pad_get_parent(srcpad)); GST_DEBUG("Plugging pad %s:%s to newly created %s:%s", - gst_object_get_name (GST_OBJECT (gst_pad_get_parent (srcpad))), - gst_pad_get_name (srcpad), - gst_object_get_name (GST_OBJECT (sinkelement)), padname); + gst_object_get_name(GST_OBJECT(srcelement)), + gst_pad_get_name(srcpad), + gst_object_get_name(GST_OBJECT(sinkelement)), padname); /* add the element to the pipeline and set correct state */ - gst_element_set_state(sinkelement, GST_STATE_PAUSED); gst_bin_add(GST_BIN(typefind->bin), sinkelement); pad = gst_element_get_pad(sinkelement, padname); gst_pad_link(srcpad, pad); - gst_bin_sync_children_state(GST_BIN(typefind->bin)); + /* FIXME: this is a nasty workaround for lack of time + * the minimalaudiosmil will try to read the input immediately + * from it sink pad as its set to PLAYING state, + * but that will result in a zillion such gstreamer warnings: + * "deadlock detected, disabling group 0xXXXXXX" + * but for example the vorbis demuxer needs to be in PLAYING + * state so that it can dynamically connect its request pads. + * fix this as soon as possible! + */ + if (!(g_strrstr(gst_object_get_name(GST_OBJECT(srcelement)), + "minimalaudiosmil") + || g_strrstr(gst_object_get_name(GST_OBJECT(sinkelement)), + "minimalaudiosmil"))) { + + gst_bin_sync_children_state(GST_BIN(typefind->bin)); + } /* if we have static source pads, link those. If we have dynamic * source pads, listen for new-pad signals on the element */ @@ -414,7 +465,6 @@ autoplug_try_to_plug(Typefind * typefind, "src"); gst_element_link(typefind->bin, typefind->sink); gst_bin_add(GST_BIN(typefind->pipeline), typefind->sink); - gst_bin_sync_children_state(GST_BIN(typefind->bin)); gst_bin_sync_children_state(GST_BIN(typefind->pipeline)); gst_caps_free (audiocaps); @@ -448,19 +498,22 @@ autoplug_try_to_plug(Typefind * typefind, if (res && !gst_caps_is_empty(res)) { GstElement * element; const GList * padTemplates; + gchar * templateName; /* close link and return */ gst_caps_free(res); + templateName = g_strdup(templ->name_template); element = gst_element_factory_create(factory, NULL); padTemplates = gst_element_factory_get_pad_templates(factory); autoplug_close_link(typefind, pad, element, - templ->name_template, + templateName, padTemplates); + g_free(templateName); return; } - gst_caps_free (res); + gst_caps_free(res); /* we only check one sink template per factory, so move on to the * next factory now */ @@ -518,7 +571,8 @@ autoplug_error_handler(GstElement * pipeline, * linked directly instead. *----------------------------------------------------------------------------*/ static void -autoplug_remove_typefind_elements(GstBin * bin) +autoplug_remove_typefind_elements(Typefind * typefind, + GstBin * bin) { GstElement * element; const GList * elements; @@ -538,7 +592,7 @@ autoplug_remove_typefind_elements(GstBin * bin) g_type_is_a(type, GST_TYPE_BIN)); if (GST_IS_BIN(element)) { - autoplug_remove_typefind_elements(GST_BIN(element)); + autoplug_remove_typefind_elements(typefind, GST_BIN(element)); } else if (g_strrstr(gst_element_factory_get_longname(factory), "TypeFind")) { GstPad * tfSinkPad; @@ -581,6 +635,10 @@ autoplug_remove_typefind_elements(GstBin * bin) gst_bin_remove(bin, element); + if (element == typefind->typefind) { + typefind->typefind = NULL; + } + /* start iteration from the beginning, as probably the element * list is invalidated with us removing the typefind element */ elements = gst_bin_get_list(GST_BIN(bin)); @@ -599,6 +657,11 @@ GstElement * autoplug_plug_source(GstElement * source) { Typefind typefind; + GstElement * bin; + + /* add an additional ref on the source, as we'll put it in a bin + * and remove it from the bin later, which will decrease the ref by one */ + g_object_ref(source); typefind.source = source; autoplug_init(&typefind); @@ -611,24 +674,31 @@ autoplug_plug_source(GstElement * source) /* run */ while (!typefind.done && gst_bin_iterate(GST_BIN(typefind.pipeline))); + if (!typefind.done) { + autoplug_deinit(&typefind); + return NULL; + } + /* remove the sink element */ gst_element_unlink(typefind.bin, typefind.sink); gst_bin_remove(GST_BIN(typefind.pipeline), typefind.sink); + typefind.sink = NULL; /* remove the typefind elements, and re-link with the source */ - g_signal_handler_disconnect(typefind.typefind, typefind.typefindSignal); - autoplug_remove_typefind_elements(GST_BIN(typefind.bin)); + autoplug_remove_typefind_elements(&typefind, GST_BIN(typefind.bin)); gst_element_link(typefind.source, typefind.bin); /* destory the pipeline, but keep source and bin */ - g_object_ref(typefind.source); g_object_ref(typefind.bin); gst_bin_remove(GST_BIN(typefind.pipeline), typefind.bin); - gst_object_unref(GST_OBJECT(typefind.pipeline)); - gst_element_set_state(typefind.bin, GST_STATE_PAUSED); - gst_bin_sync_children_state(GST_BIN(typefind.bin)); + bin = typefind.bin; - return typefind.bin; + autoplug_deinit(&typefind); + + gst_element_set_state(bin, GST_STATE_PAUSED); + gst_bin_sync_children_state(GST_BIN(bin)); + + return bin; } diff --git a/livesupport/modules/gstreamerElements/src/minimal-audio-smil.c b/livesupport/modules/gstreamerElements/src/minimal-audio-smil.c index d218e41fe..5453220a2 100644 --- a/livesupport/modules/gstreamerElements/src/minimal-audio-smil.c +++ b/livesupport/modules/gstreamerElements/src/minimal-audio-smil.c @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/src/minimal-audio-smil.c,v $ ------------------------------------------------------------------------------*/ @@ -55,8 +55,8 @@ */ static GstElementDetails livesupport_minimal_audio_smil_details = GST_ELEMENT_DETAILS("MinimalAudioSmil", - "Generic", - "A minimal SMIL payer, supporting only audio", + "Parse/Smil", + "A minimal SMIL player, supporting only audio", "Akos Maroy "); /** @@ -110,7 +110,7 @@ GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, "minimalaudiosmil", "Minimal Audio-only SMIL", plugin_init, - "$Revision: 1.1 $", + "$Revision: 1.2 $", "GPL", "LiveSupport", "http://livesupport.campware.org/") @@ -242,7 +242,9 @@ read_stream_into_memory(LivesupportMinimalAudioSmil * smil, *outlength = 0; oldState = gst_element_get_state(smil->oneshotReader); - gst_element_set_state(smil->oneshotReader, GST_STATE_PLAYING); + if (oldState != GST_STATE_PLAYING) { + gst_element_set_state(smil->oneshotReader, GST_STATE_PLAYING); + } g_object_get(G_OBJECT(smil->oneshotReader), "length", &length, NULL); g_object_get(G_OBJECT(smil->oneshotReader), "contents", &buffer, NULL); @@ -438,6 +440,10 @@ process_smil_file(LivesupportMinimalAudioSmil * smil) xmlDocPtr document; xmlNode * node; + if (!GST_PAD_IS_LINKED(smil->sinkpad)) { + return FALSE; + } + /* read the source document into memory */ read_stream_into_memory(smil, &buffer, &length); if (!buffer) { @@ -493,15 +499,22 @@ static GstElementStateReturn livesupport_minimal_audio_smil_change_state(GstElement * element) { LivesupportMinimalAudioSmil * smil; + GstElementState transition = GST_STATE_TRANSITION(element); smil = LIVESUPPORT_MINIMAL_AUDIO_SMIL(element); - switch (GST_STATE_TRANSITION (element)) { + switch (transition) { case GST_STATE_NULL_TO_READY: gst_element_set_state(GST_ELEMENT(smil->bin), GST_STATE_READY); break; case GST_STATE_READY_TO_PAUSED: + gst_element_set_state(GST_ELEMENT(smil->bin), GST_STATE_PAUSED); + break; + + case GST_STATE_PAUSED_TO_PLAYING: + gst_element_set_state(GST_ELEMENT(smil->bin), GST_STATE_PLAYING); + if (!smil->fileProcessed) { /* set to true, in case of multiple change events */ smil->fileProcessed = TRUE; @@ -513,11 +526,7 @@ livesupport_minimal_audio_smil_change_state(GstElement * element) (NULL)); } } - gst_element_set_state(GST_ELEMENT(smil->bin), GST_STATE_PAUSED); - break; - case GST_STATE_PAUSED_TO_PLAYING: - gst_element_set_state(GST_ELEMENT(smil->bin), GST_STATE_PLAYING); break; case GST_STATE_PLAYING_TO_PAUSED: @@ -680,7 +689,7 @@ plugin_init (GstPlugin * plugin) { return gst_element_register(plugin, "minimalaudiosmil", - GST_RANK_NONE, + GST_RANK_SECONDARY, LIVESUPPORT_TYPE_MINIMAL_AUDIO_SMIL); } diff --git a/livesupport/modules/gstreamerElements/src/oneshot-reader.c b/livesupport/modules/gstreamerElements/src/oneshot-reader.c index 9af8a2aa9..3434b64db 100644 --- a/livesupport/modules/gstreamerElements/src/oneshot-reader.c +++ b/livesupport/modules/gstreamerElements/src/oneshot-reader.c @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/src/oneshot-reader.c,v $ ------------------------------------------------------------------------------*/ @@ -93,7 +93,7 @@ GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, "oneshotreaderplugin", "A reader that reads all of the input on one go", plugin_init, - "$Revision: 1.1 $", + "$Revision: 1.2 $", "GPL", "LiveSupport", "http://livesupport.campware.org/") @@ -283,6 +283,7 @@ static void livesupport_one_shot_reader_loop(GstElement * element) { LivesupportOneShotReader * reader; + GstData * data; g_return_if_fail(element != NULL); g_return_if_fail(GST_IS_ONE_SHOT_READER(element)); @@ -302,6 +303,9 @@ livesupport_one_shot_reader_loop(GstElement * element) reader->processed = TRUE; } + /* just pull the data from the source and don't care about it */ + data = gst_pad_pull(reader->sinkpad); + gst_element_set_eos(element); } diff --git a/livesupport/modules/gstreamerElements/src/switcher.c b/livesupport/modules/gstreamerElements/src/switcher.c index 88bbb5249..04dc2057e 100644 --- a/livesupport/modules/gstreamerElements/src/switcher.c +++ b/livesupport/modules/gstreamerElements/src/switcher.c @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.4 $ + Version : $Revision: 1.5 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/src/switcher.c,v $ ------------------------------------------------------------------------------*/ @@ -64,7 +64,7 @@ GST_PLUGIN_DEFINE ( "switcher", "A filter that connects to a swtich, and changes its source", plugin_init, - "$Revision: 1.4 $", + "$Revision: 1.5 $", "GPL", "LiveSupport", "http://livesupport.campware.org/" @@ -449,7 +449,7 @@ switch_to_next_source(LivesupportSwitcher * switcher) /*------------------------------------------------------------------------------ - * The main chain function. + * The main loop function. *----------------------------------------------------------------------------*/ static void livesupport_switcher_loop(GstElement * element)