added autoplugging capability
This commit is contained in:
parent
70a2c6bb64
commit
c63c290d68
6 changed files with 1047 additions and 25 deletions
|
@ -21,7 +21,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Author : $Author: maroy $
|
# Author : $Author: maroy $
|
||||||
# Version : $Revision: 1.4 $
|
# Version : $Revision: 1.5 $
|
||||||
# Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/etc/Makefile.in,v $
|
# Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/etc/Makefile.in,v $
|
||||||
#
|
#
|
||||||
# @configure_input@
|
# @configure_input@
|
||||||
|
@ -76,6 +76,9 @@ TEST_RESULTS = ${DOC_DIR}/testResults.xml
|
||||||
# the text result XSLT has to be relative to the test result file, e.g. TMP_DIR
|
# the text result XSLT has to be relative to the test result file, e.g. TMP_DIR
|
||||||
TEST_XSLT = ../etc/testResultToHtml.xsl
|
TEST_XSLT = ../etc/testResultToHtml.xsl
|
||||||
|
|
||||||
|
GSTREAMER_ELEMENTS_LIB = livesupport_gstreamerelements
|
||||||
|
GSTREAMER_ELEMENTS_LIB_FILE = ${LIB_DIR}/lib${GSTREAMER_ELEMENTS_LIB}.a
|
||||||
|
|
||||||
ONESHOT_READER_LIB = livesupport_oneshotreader
|
ONESHOT_READER_LIB = livesupport_oneshotreader
|
||||||
ONESHOT_READER_LIB_FILE = ${LIB_DIR}/lib${ONESHOT_READER_LIB}.so
|
ONESHOT_READER_LIB_FILE = ${LIB_DIR}/lib${ONESHOT_READER_LIB}.so
|
||||||
MINIMAL_AUDIO_SMIL_LIB = livesupport_minimalaudiosmil
|
MINIMAL_AUDIO_SMIL_LIB = livesupport_minimalaudiosmil
|
||||||
|
@ -122,26 +125,22 @@ LDFLAGS = @LDFLAGS@ ${GSTREAMER_LIBS} \
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Dependencies
|
# Dependencies
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
GSTREAMER_ELEMENTS_LIB_OBJS = ${TMP_DIR}/seek.o \
|
||||||
|
${TMP_DIR}/util.o \
|
||||||
|
${TMP_DIR}/seek-pack.o \
|
||||||
|
${TMP_DIR}/autoplug.o \
|
||||||
|
${TMP_DIR}/smil-util.o
|
||||||
|
|
||||||
ONESHOT_READER_LIB_OBJS = ${TMP_DIR}/oneshot-reader.o
|
ONESHOT_READER_LIB_OBJS = ${TMP_DIR}/oneshot-reader.o
|
||||||
|
|
||||||
MINIMAL_AUDIO_SMIL_LIB_OBJS = ${TMP_DIR}/seek.o \
|
MINIMAL_AUDIO_SMIL_LIB_OBJS = ${TMP_DIR}/minimal-audio-smil.o
|
||||||
${TMP_DIR}/util.o \
|
|
||||||
${TMP_DIR}/seek-pack.o \
|
|
||||||
${TMP_DIR}/minimal-audio-smil.o
|
|
||||||
|
|
||||||
PARTIAL_PLAY_LIB_OBJS = ${TMP_DIR}/seek.o \
|
PARTIAL_PLAY_LIB_OBJS = ${TMP_DIR}/partial-play.o
|
||||||
${TMP_DIR}/util.o \
|
|
||||||
${TMP_DIR}/seek-pack.o \
|
|
||||||
${TMP_DIR}/smil-util.o \
|
|
||||||
${TMP_DIR}/partial-play.o
|
|
||||||
|
|
||||||
SWITCHER_LIB_OBJS = ${TMP_DIR}/smil-util.o \
|
SWITCHER_LIB_OBJS = ${TMP_DIR}/switcher.o
|
||||||
${TMP_DIR}/switcher.o
|
|
||||||
|
|
||||||
TEST_RUNNER_OBJS = ${TMP_DIR}/TestRunner.o \
|
TEST_RUNNER_OBJS = ${TMP_DIR}/TestRunner.o \
|
||||||
${TMP_DIR}/seek.o \
|
${TMP_DIR}/AutoplugTest.o \
|
||||||
${TMP_DIR}/util.o \
|
|
||||||
${TMP_DIR}/seek-pack.o \
|
|
||||||
${TMP_DIR}/SeekTest.o \
|
${TMP_DIR}/SeekTest.o \
|
||||||
${TMP_DIR}/SwitcherTest.o \
|
${TMP_DIR}/SwitcherTest.o \
|
||||||
${TMP_DIR}/SeekPackTest.o \
|
${TMP_DIR}/SeekPackTest.o \
|
||||||
|
@ -149,7 +148,8 @@ TEST_RUNNER_OBJS = ${TMP_DIR}/TestRunner.o \
|
||||||
${TMP_DIR}/OneshotReaderTest.o \
|
${TMP_DIR}/OneshotReaderTest.o \
|
||||||
${TMP_DIR}/MinimalAudioSmilTest.o
|
${TMP_DIR}/MinimalAudioSmilTest.o
|
||||||
|
|
||||||
TEST_RUNNER_LIBS = -l${CORE_LIB} -lcppunit -ldl -lxmlrpc++
|
TEST_RUNNER_LIBS = -l${GSTREAMER_ELEMENTS_LIB} -l${CORE_LIB} \
|
||||||
|
-lcppunit -ldl -lxmlrpc++
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
@ -157,7 +157,8 @@ TEST_RUNNER_LIBS = -l${CORE_LIB} -lcppunit -ldl -lxmlrpc++
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
.PHONY: all dir_setup doc clean docclean depclean distclean
|
.PHONY: all dir_setup doc clean docclean depclean distclean
|
||||||
|
|
||||||
all: dir_setup ${ONESHOT_READER_LIB_FILE} \
|
all: dir_setup ${GSTREAMER_ELEMENTS_LIB_FILE} \
|
||||||
|
${ONESHOT_READER_LIB_FILE} \
|
||||||
${MINIMAL_AUDIO_SMIL_LIB_FILE} \
|
${MINIMAL_AUDIO_SMIL_LIB_FILE} \
|
||||||
${PARTIAL_PLAY_LIB_FILE} \
|
${PARTIAL_PLAY_LIB_FILE} \
|
||||||
${SWITCHER_LIB_FILE} \
|
${SWITCHER_LIB_FILE} \
|
||||||
|
@ -172,6 +173,7 @@ doc:
|
||||||
${DOXYGEN} ${DOXYGEN_CONFIG}
|
${DOXYGEN} ${DOXYGEN_CONFIG}
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
${RM} ${GSTREAMER_ELEMENTS_LIB_OBJS} ${GSTREAMER_ELEMENTS_LIB_FILE}
|
||||||
${RM} ${ONESHOT_READER_LIB_OBJS} ${ONESHOT_READER_LIB_FILE}
|
${RM} ${ONESHOT_READER_LIB_OBJS} ${ONESHOT_READER_LIB_FILE}
|
||||||
${RM} ${MINIMAL_AUDIO_SMIL_LIB_OBJS} ${MINIMAL_AUDIO_SMIL_LIB_FILE}
|
${RM} ${MINIMAL_AUDIO_SMIL_LIB_OBJS} ${MINIMAL_AUDIO_SMIL_LIB_FILE}
|
||||||
${RM} ${PARTIAL_PLAY_LIB_OBJS} ${PARTIAL_PLAY_LIB_FILE}
|
${RM} ${PARTIAL_PLAY_LIB_OBJS} ${PARTIAL_PLAY_LIB_FILE}
|
||||||
|
@ -196,17 +198,24 @@ check: all ${TEST_RUNNER}
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Specific targets
|
# Specific targets
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
${ONESHOT_READER_LIB_FILE}: ${ONESHOT_READER_LIB_OBJS}
|
${GSTREAMER_ELEMENTS_LIB_FILE}: ${GSTREAMER_ELEMENTS_LIB_OBJS}
|
||||||
|
${AR} crus $@ $^
|
||||||
|
|
||||||
|
${ONESHOT_READER_LIB_FILE}: ${GSTREAMER_ELEMENTS_LIB_FILE} \
|
||||||
|
${ONESHOT_READER_LIB_OBJS}
|
||||||
${CC} -shared -o $@ $^ ${GST_LDFLAGS}
|
${CC} -shared -o $@ $^ ${GST_LDFLAGS}
|
||||||
|
|
||||||
${MINIMAL_AUDIO_SMIL_LIB_FILE}: ${MINIMAL_AUDIO_SMIL_LIB_OBJS}
|
${MINIMAL_AUDIO_SMIL_LIB_FILE}: ${GSTREAMER_ELEMENTS_LIB_FILE} \
|
||||||
${CC} -shared ${GST_LDFLAGS} -o $@ $^
|
${MINIMAL_AUDIO_SMIL_LIB_OBJS}
|
||||||
|
${CC} -shared -o $@ $^ ${GST_LDFLAGS}
|
||||||
|
|
||||||
${PARTIAL_PLAY_LIB_FILE}: ${PARTIAL_PLAY_LIB_OBJS}
|
${PARTIAL_PLAY_LIB_FILE}: ${GSTREAMER_ELEMENTS_LIB_FILE} \
|
||||||
${CC} -shared ${GST_LDFLAGS} -o $@ $^
|
${PARTIAL_PLAY_LIB_OBJS}
|
||||||
|
${CC} -shared -o $@ $^ ${GST_LDFLAGS}
|
||||||
|
|
||||||
${SWITCHER_LIB_FILE}: ${SWITCHER_LIB_OBJS}
|
${SWITCHER_LIB_FILE}: ${SWITCHER_LIB_OBJS} \
|
||||||
${CC} -shared ${GST_LDFLAGS} -o $@ $^
|
${GSTREAMER_ELEMENTS_LIB_FILE}
|
||||||
|
${CC} -shared -o $@ $^ ${GST_LDFLAGS}
|
||||||
|
|
||||||
${TMP_DIR}:
|
${TMP_DIR}:
|
||||||
${MKDIR} ${TMP_DIR}
|
${MKDIR} ${TMP_DIR}
|
||||||
|
@ -214,7 +223,8 @@ ${TMP_DIR}:
|
||||||
${DOXYGEN_DIR}:
|
${DOXYGEN_DIR}:
|
||||||
${MKDIR} ${DOXYGEN_DIR}
|
${MKDIR} ${DOXYGEN_DIR}
|
||||||
|
|
||||||
${TEST_RUNNER}: ${CORE_LIB_FILE} ${TEST_RUNNER_OBJS}
|
${TEST_RUNNER}: ${CORE_LIB_FILE} ${GSTREAMER_ELEMENTS_LIB_FILE} \
|
||||||
|
${TEST_RUNNER_OBJS}
|
||||||
${CXX} ${LDFLAGS} -o $@ ${TEST_RUNNER_OBJS} ${TEST_RUNNER_LIBS}
|
${CXX} ${LDFLAGS} -o $@ ${TEST_RUNNER_OBJS} ${TEST_RUNNER_LIBS}
|
||||||
|
|
||||||
${CORE_LIB_FILE}:
|
${CORE_LIB_FILE}:
|
||||||
|
|
169
livesupport/modules/gstreamerElements/src/AutoplugTest.cxx
Normal file
169
livesupport/modules/gstreamerElements/src/AutoplugTest.cxx
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2004 Media Development Loan Fund
|
||||||
|
|
||||||
|
This file is part of the LiveSupport project.
|
||||||
|
http://livesupport.campware.org/
|
||||||
|
To report bugs, send an e-mail to bugs@campware.org
|
||||||
|
|
||||||
|
LiveSupport is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
LiveSupport 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with LiveSupport; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Author : $Author: maroy $
|
||||||
|
Version : $Revision: 1.1 $
|
||||||
|
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/src/AutoplugTest.cxx,v $
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ============================================================ include files */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "configure.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include "autoplug.h"
|
||||||
|
#include "AutoplugTest.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace LiveSupport::GstreamerElements;
|
||||||
|
|
||||||
|
/* =================================================== local data structures */
|
||||||
|
|
||||||
|
|
||||||
|
/* ================================================ local constants & macros */
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(AutoplugTest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An mp3 test file.
|
||||||
|
*/
|
||||||
|
static const char * mp3TestFile = "var/5seccounter.mp3";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An ogg vorbis test file.
|
||||||
|
*/
|
||||||
|
static const char * oggTestFile = "var/5seccounter.ogg";
|
||||||
|
|
||||||
|
|
||||||
|
/* =============================================== local function prototypes */
|
||||||
|
|
||||||
|
|
||||||
|
/* ============================================================= module code */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Set up the test environment
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
AutoplugTest :: setUp(void) throw ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Clean up the test environment
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
AutoplugTest :: tearDown(void) throw ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Play an audio file
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
gint64
|
||||||
|
AutoplugTest :: playFile(const char * audioFile)
|
||||||
|
throw (CPPUNIT_NS::Exception)
|
||||||
|
{
|
||||||
|
GstElement * pipeline;
|
||||||
|
GstElement * source;
|
||||||
|
GstElement * decoder;
|
||||||
|
GstElement * sink;
|
||||||
|
GstFormat format;
|
||||||
|
gint64 timePlayed;
|
||||||
|
|
||||||
|
/* initialize GStreamer */
|
||||||
|
gst_init(0, 0);
|
||||||
|
|
||||||
|
/* create elements */
|
||||||
|
pipeline = gst_pipeline_new("audio-player");
|
||||||
|
source = gst_element_factory_make("filesrc", "source");
|
||||||
|
sink = gst_element_factory_make("alsasink", "alsa-output");
|
||||||
|
|
||||||
|
g_object_set(G_OBJECT(source), "location", audioFile, NULL);
|
||||||
|
|
||||||
|
decoder = autoplug_plug_source(source);
|
||||||
|
|
||||||
|
gst_element_link(decoder, sink);
|
||||||
|
gst_bin_add_many(GST_BIN(pipeline), source, decoder, sink, NULL);
|
||||||
|
|
||||||
|
gst_element_set_state(source, GST_STATE_PAUSED);
|
||||||
|
gst_element_set_state(decoder, GST_STATE_PAUSED);
|
||||||
|
gst_element_set_state(sink, GST_STATE_PAUSED);
|
||||||
|
gst_element_set_state(pipeline, GST_STATE_PLAYING);
|
||||||
|
gst_bin_sync_children_state(GST_BIN(pipeline));
|
||||||
|
|
||||||
|
// iterate until playTo is reached
|
||||||
|
while (gst_bin_iterate(GST_BIN(pipeline)));
|
||||||
|
|
||||||
|
format = GST_FORMAT_TIME;
|
||||||
|
gst_element_query(sink, GST_QUERY_POSITION, &format, &timePlayed);
|
||||||
|
|
||||||
|
/* clean up nicely */
|
||||||
|
gst_element_set_state(pipeline, GST_STATE_NULL);
|
||||||
|
gst_object_unref(GST_OBJECT (pipeline));
|
||||||
|
|
||||||
|
return timePlayed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* A simple smoke test.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
AutoplugTest :: firstTest(void)
|
||||||
|
throw (CPPUNIT_NS::Exception)
|
||||||
|
{
|
||||||
|
gint64 timePlayed;
|
||||||
|
char str[256];
|
||||||
|
|
||||||
|
timePlayed = playFile(mp3TestFile);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* An ogg vorbis test.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
AutoplugTest :: oggVorbisTest(void)
|
||||||
|
throw (CPPUNIT_NS::Exception)
|
||||||
|
{
|
||||||
|
gint64 timePlayed;
|
||||||
|
char str[256];
|
||||||
|
|
||||||
|
timePlayed = playFile(oggTestFile);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
129
livesupport/modules/gstreamerElements/src/AutoplugTest.h
Normal file
129
livesupport/modules/gstreamerElements/src/AutoplugTest.h
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2004 Media Development Loan Fund
|
||||||
|
|
||||||
|
This file is part of the LiveSupport project.
|
||||||
|
http://livesupport.campware.org/
|
||||||
|
To report bugs, send an e-mail to bugs@campware.org
|
||||||
|
|
||||||
|
LiveSupport is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
LiveSupport 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with LiveSupport; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Author : $Author: maroy $
|
||||||
|
Version : $Revision: 1.1 $
|
||||||
|
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/src/AutoplugTest.h,v $
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
#ifndef AutoplugTest_h
|
||||||
|
#define AutoplugTest_h
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#error This is a C++ include file
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ============================================================ include files */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "configure.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace LiveSupport {
|
||||||
|
namespace GstreamerElements {
|
||||||
|
|
||||||
|
/* ================================================================ constants */
|
||||||
|
|
||||||
|
|
||||||
|
/* =================================================================== macros */
|
||||||
|
|
||||||
|
|
||||||
|
/* =============================================================== data types */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit test for the partialplay gstreamer element.
|
||||||
|
*
|
||||||
|
* @author $Author: maroy $
|
||||||
|
* @version $Revision: 1.1 $
|
||||||
|
*/
|
||||||
|
class AutoplugTest : public CPPUNIT_NS::TestFixture
|
||||||
|
{
|
||||||
|
CPPUNIT_TEST_SUITE(AutoplugTest);
|
||||||
|
CPPUNIT_TEST(firstTest);
|
||||||
|
CPPUNIT_TEST(oggVorbisTest);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Play a specific file, from and until a specific timepoint.
|
||||||
|
*
|
||||||
|
* @param audioFile the audio file to play.
|
||||||
|
* @return the number of milliseconds played.
|
||||||
|
* @exception CPPUNIT_NS::Exception on test failures.
|
||||||
|
*/
|
||||||
|
gint64
|
||||||
|
playFile(const char * audioFile)
|
||||||
|
throw (CPPUNIT_NS::Exception);
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple smoke test.
|
||||||
|
*
|
||||||
|
* @exception CPPUNIT_NS::Exception on test failures.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
firstTest(void) throw (CPPUNIT_NS::Exception);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test an Ogg Vorbis file.
|
||||||
|
*
|
||||||
|
* @exception CPPUNIT_NS::Exception on test failures.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
oggVorbisTest(void) throw (CPPUNIT_NS::Exception);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the environment for the test case.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
setUp(void) throw ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up the environment after the test case.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
tearDown(void) throw ();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* ================================================= external data structures */
|
||||||
|
|
||||||
|
|
||||||
|
/* ====================================================== function prototypes */
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace GstreamerElements
|
||||||
|
} // namespace LiveSupport
|
||||||
|
|
||||||
|
#endif // AutoplugTest_h
|
||||||
|
|
634
livesupport/modules/gstreamerElements/src/autoplug.c
Normal file
634
livesupport/modules/gstreamerElements/src/autoplug.c
Normal file
|
@ -0,0 +1,634 @@
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2004 Media Development Loan Fund
|
||||||
|
|
||||||
|
This file is part of the LiveSupport project.
|
||||||
|
http://livesupport.campware.org/
|
||||||
|
To report bugs, send an e-mail to bugs@campware.org
|
||||||
|
|
||||||
|
LiveSupport is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
LiveSupport 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with LiveSupport; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
This code is based on the examples/manual/dynamic.c sample file
|
||||||
|
provided in the gstreamer-0.8.10 source tarball, which is published
|
||||||
|
under the GNU LGPL license.
|
||||||
|
|
||||||
|
|
||||||
|
Author : $Author: maroy $
|
||||||
|
Version : $Revision: 1.1 $
|
||||||
|
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/src/autoplug.c,v $
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ============================================================ include files */
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include "autoplug.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* =================================================== local data structures */
|
||||||
|
|
||||||
|
typedef struct _Typefind Typefind;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data structure to hold information related to typefindinf.
|
||||||
|
*/
|
||||||
|
struct _Typefind {
|
||||||
|
GList * factories;
|
||||||
|
|
||||||
|
GstElement * pipeline;
|
||||||
|
GstElement * bin;
|
||||||
|
GstElement * source;
|
||||||
|
GstElement * typefind;
|
||||||
|
GstElement * audiosink;
|
||||||
|
GstElement * sink;
|
||||||
|
|
||||||
|
gulong typefindSignal;
|
||||||
|
|
||||||
|
gboolean done;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* ================================================ local constants & macros */
|
||||||
|
|
||||||
|
|
||||||
|
/* =============================================== local function prototypes */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle typefinding error.
|
||||||
|
*
|
||||||
|
* @param pipeline the pipeline generating the error.
|
||||||
|
* @param source the source element with the error
|
||||||
|
* @param error the error itself.
|
||||||
|
* @param message the error message.
|
||||||
|
* @param userData user-specific data.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
autoplug_error_handler(GstElement * pipeline,
|
||||||
|
GstElement * source,
|
||||||
|
GError * error,
|
||||||
|
gchar * message,
|
||||||
|
gpointer userData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle event of the typefinder finding a type.
|
||||||
|
*
|
||||||
|
* @param typefind the typefind element that found the type.
|
||||||
|
* @param probability the probability of the find.
|
||||||
|
* @param caps the found capabilities.
|
||||||
|
* @param userData user-specific data, a pointer to a related Typefind
|
||||||
|
* structure.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
autoplug_typefound_handler(GstElement * typefind,
|
||||||
|
gint probability,
|
||||||
|
GstCaps * caps,
|
||||||
|
gpointer userData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a typefind object.
|
||||||
|
*
|
||||||
|
* @param typefind the Typefind structure to init.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
autoplug_init(Typefind * typefind);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A filter specifying the kind of factories we're interested in.
|
||||||
|
*
|
||||||
|
* @param feature the feature to test
|
||||||
|
* @param userData user-specific data
|
||||||
|
* @return TRUE if we're interested in the supplied feature, FALSE otherwise
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
autoplug_feature_filter(GstPluginFeature * feature,
|
||||||
|
gpointer userData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A comparison function based on the ranks of two features.
|
||||||
|
*
|
||||||
|
* @param feature1 one of the features to compare.
|
||||||
|
* @param feature2 the other feature to compare.
|
||||||
|
* @return 0 if the two features match in terms of their ranks,
|
||||||
|
* <0 if feature1 is higher, >0 if feature2 is higher in
|
||||||
|
* their ranks.
|
||||||
|
*/
|
||||||
|
static gint
|
||||||
|
autoplug_compare_ranks(GstPluginFeature * feature1,
|
||||||
|
GstPluginFeature * feature2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type to plug an appropriate element to a pad, according to the specified
|
||||||
|
* capabilities.
|
||||||
|
*
|
||||||
|
* @param typefind the Typefind structure to do the plugging for
|
||||||
|
* @param pad the pad to plug.
|
||||||
|
* @param caps the capabilities to plug with.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
autoplug_try_to_plug(Typefind * typefind,
|
||||||
|
GstPad * pad,
|
||||||
|
const GstCaps * caps);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close a found link.
|
||||||
|
*
|
||||||
|
* @param typefind the Typefind structure to do close the link for.
|
||||||
|
* @param srcpad the source pad to close linking for.
|
||||||
|
* @param sinkelement the sink element to link the src pad to.
|
||||||
|
* @param padname the name of sink pad in sinkelement to link srcpad to.
|
||||||
|
* @param templlist a pad template list (TODO: what's this for?)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
autoplug_close_link(Typefind * typefind,
|
||||||
|
GstPad * srcpad,
|
||||||
|
GstElement * sinkelement,
|
||||||
|
const gchar * padname,
|
||||||
|
const GList * templlist);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event of new pads created on elements with dynamic pads.
|
||||||
|
*
|
||||||
|
* @param element the element that the new pad was created on.
|
||||||
|
* @param pad the new pad.
|
||||||
|
* @param userData user-specific data.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
autoplug_newpad(GstElement * element,
|
||||||
|
GstPad * pad,
|
||||||
|
gpointer data);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @param bin the bin to remove the typefind elements from.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
autoplug_remove_typefind_elements(GstBin * bin);
|
||||||
|
|
||||||
|
|
||||||
|
/* ============================================================= module code */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Filter the features that we're interested in.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
static gboolean
|
||||||
|
autoplug_feature_filter(GstPluginFeature * feature,
|
||||||
|
gpointer userData)
|
||||||
|
{
|
||||||
|
const gchar * klass;
|
||||||
|
guint rank;
|
||||||
|
|
||||||
|
/* we only care about element factories */
|
||||||
|
if (!GST_IS_ELEMENT_FACTORY(feature)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only parsers, demuxers and decoders */
|
||||||
|
klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
|
||||||
|
if (g_strrstr(klass, "Demux") == NULL &&
|
||||||
|
g_strrstr(klass, "Decoder") == NULL &&
|
||||||
|
g_strrstr(klass, "Parse") == NULL) {
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only select elements with autoplugging rank */
|
||||||
|
rank = gst_plugin_feature_get_rank(feature);
|
||||||
|
if (rank < GST_RANK_MARGINAL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Compare the ranks of two features.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
static gint
|
||||||
|
autoplug_compare_ranks(GstPluginFeature * feature1,
|
||||||
|
GstPluginFeature * feature2)
|
||||||
|
{
|
||||||
|
return gst_plugin_feature_get_rank(feature2)
|
||||||
|
- gst_plugin_feature_get_rank(feature1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Initialize a Typefind object, like the factories that we care about.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
autoplug_init(Typefind * typefind)
|
||||||
|
{
|
||||||
|
/* first filter out the interesting element factories */
|
||||||
|
typefind->factories = gst_registry_pool_feature_filter(
|
||||||
|
(GstPluginFeatureFilter) autoplug_feature_filter,
|
||||||
|
FALSE, NULL);
|
||||||
|
|
||||||
|
/* sort them according to their ranks */
|
||||||
|
typefind->factories = g_list_sort(typefind->factories,
|
||||||
|
(GCompareFunc) autoplug_compare_ranks);
|
||||||
|
|
||||||
|
typefind->pipeline = gst_pipeline_new("pipeline");
|
||||||
|
typefind->bin = gst_bin_new("bin");
|
||||||
|
typefind->typefind = gst_element_factory_make("typefind", "tf");
|
||||||
|
typefind->audiosink = gst_element_factory_make("audioconvert", "audiosink");
|
||||||
|
typefind->sink = gst_element_factory_make("fakesink", "fakesink");
|
||||||
|
|
||||||
|
gst_element_add_ghost_pad(typefind->bin,
|
||||||
|
gst_element_get_pad(typefind->typefind, "sink"),
|
||||||
|
"sink");
|
||||||
|
gst_bin_add_many(GST_BIN(typefind->bin),
|
||||||
|
typefind->typefind,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_signal_connect(typefind->bin,
|
||||||
|
"error",
|
||||||
|
G_CALLBACK(autoplug_error_handler),
|
||||||
|
NULL);
|
||||||
|
typefind->typefindSignal = g_signal_connect(typefind->typefind,
|
||||||
|
"have-type",
|
||||||
|
G_CALLBACK(autoplug_typefound_handler),
|
||||||
|
typefind);
|
||||||
|
|
||||||
|
gst_element_link(typefind->source, typefind->bin);
|
||||||
|
gst_bin_add_many(GST_BIN(typefind->pipeline),
|
||||||
|
typefind->source,
|
||||||
|
typefind->bin,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
typefind->done = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Handle the event of a new pad being created on an element with
|
||||||
|
* request pads.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
autoplug_newpad(GstElement * element,
|
||||||
|
GstPad * pad,
|
||||||
|
gpointer userData)
|
||||||
|
{
|
||||||
|
GstCaps * caps;
|
||||||
|
Typefind * typefind = (Typefind*) userData;
|
||||||
|
|
||||||
|
g_return_if_fail(typefind != NULL);
|
||||||
|
|
||||||
|
GST_DEBUG("created new pad %s for element %s",
|
||||||
|
gst_pad_get_name(pad), gst_element_get_name(element));
|
||||||
|
caps = gst_pad_get_caps(pad);
|
||||||
|
autoplug_try_to_plug(typefind, pad, caps);
|
||||||
|
gst_caps_free(caps);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Close the link.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
autoplug_close_link(Typefind * typefind,
|
||||||
|
GstPad * srcpad,
|
||||||
|
GstElement * sinkelement,
|
||||||
|
const gchar * padname,
|
||||||
|
const GList * templlist)
|
||||||
|
{
|
||||||
|
GstPad * pad;
|
||||||
|
gboolean has_dynamic_pads = FALSE;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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));
|
||||||
|
|
||||||
|
/* if we have static source pads, link those. If we have dynamic
|
||||||
|
* source pads, listen for new-pad signals on the element */
|
||||||
|
for ( ; templlist != NULL; templlist = templlist->next) {
|
||||||
|
GstPadTemplate *templ = GST_PAD_TEMPLATE (templlist->data);
|
||||||
|
|
||||||
|
/* only sourcepads, no request pads */
|
||||||
|
if (templ->direction != GST_PAD_SRC ||
|
||||||
|
templ->presence == GST_PAD_REQUEST) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (templ->presence) {
|
||||||
|
case GST_PAD_ALWAYS: {
|
||||||
|
GstPad * pad = gst_element_get_pad(sinkelement,
|
||||||
|
templ->name_template);
|
||||||
|
GstCaps * caps = gst_pad_get_caps(pad);
|
||||||
|
|
||||||
|
/* link */
|
||||||
|
autoplug_try_to_plug(typefind, pad, caps);
|
||||||
|
gst_caps_free(caps);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case GST_PAD_SOMETIMES:
|
||||||
|
has_dynamic_pads = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* listen for newly created pads if this element supports that */
|
||||||
|
if (has_dynamic_pads) {
|
||||||
|
g_signal_connect(sinkelement,
|
||||||
|
"new-pad",
|
||||||
|
G_CALLBACK(autoplug_newpad),
|
||||||
|
typefind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Try to plug a pad with the specified capabilities.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
autoplug_try_to_plug(Typefind * typefind,
|
||||||
|
GstPad * pad,
|
||||||
|
const GstCaps * caps)
|
||||||
|
{
|
||||||
|
GstObject * parent = GST_OBJECT(gst_pad_get_parent(pad));
|
||||||
|
const gchar * mime;
|
||||||
|
const GList * item;
|
||||||
|
GstCaps * res;
|
||||||
|
GstCaps * audiocaps;
|
||||||
|
|
||||||
|
g_return_if_fail(typefind != NULL);
|
||||||
|
|
||||||
|
/* don't plug if we're already plugged */
|
||||||
|
if (GST_PAD_IS_LINKED(gst_element_get_pad(typefind->audiosink, "sink"))) {
|
||||||
|
GST_DEBUG("Omitting link for pad %s:%s because we're already linked",
|
||||||
|
gst_object_get_name (parent), gst_pad_get_name (pad));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* as said above, we only try to plug audio... Omit video */
|
||||||
|
mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
|
||||||
|
if (g_strrstr(mime, "video")) {
|
||||||
|
GST_DEBUG("Omitting link for pad %s:%s because "
|
||||||
|
"mimetype %s is non-audio\n",
|
||||||
|
gst_object_get_name (parent), gst_pad_get_name (pad), mime);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* can it link to the audiopad? */
|
||||||
|
audiocaps = gst_pad_get_caps(gst_element_get_pad(typefind->audiosink,
|
||||||
|
"sink"));
|
||||||
|
res = gst_caps_intersect(caps, audiocaps);
|
||||||
|
if (res && !gst_caps_is_empty(res)) {
|
||||||
|
GST_DEBUG("Found pad to link to audiosink - plugging is now done");
|
||||||
|
typefind->done = TRUE;
|
||||||
|
|
||||||
|
autoplug_close_link(typefind, pad, typefind->audiosink, "sink", NULL);
|
||||||
|
|
||||||
|
gst_element_add_ghost_pad(typefind->bin,
|
||||||
|
gst_element_get_pad(typefind->audiosink, "src"),
|
||||||
|
"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);
|
||||||
|
gst_caps_free (res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gst_caps_free (audiocaps);
|
||||||
|
gst_caps_free (res);
|
||||||
|
|
||||||
|
/* try to plug from our list */
|
||||||
|
for (item = typefind->factories; item != NULL; item = item->next) {
|
||||||
|
GstElementFactory * factory = GST_ELEMENT_FACTORY(item->data);
|
||||||
|
const GList * pads;
|
||||||
|
|
||||||
|
for (pads = gst_element_factory_get_pad_templates(factory);
|
||||||
|
pads != NULL;
|
||||||
|
pads = pads->next) {
|
||||||
|
GstPadTemplate * templ = GST_PAD_TEMPLATE(pads->data);
|
||||||
|
|
||||||
|
if (!GST_IS_PAD_TEMPLATE(templ)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* find the sink template - need an always pad*/
|
||||||
|
if (templ->direction != GST_PAD_SINK ||
|
||||||
|
templ->presence != GST_PAD_ALWAYS) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* can it link? */
|
||||||
|
res = gst_caps_intersect(caps, templ->caps);
|
||||||
|
if (res && !gst_caps_is_empty(res)) {
|
||||||
|
GstElement * element;
|
||||||
|
const GList * padTemplates;
|
||||||
|
|
||||||
|
/* close link and return */
|
||||||
|
gst_caps_free(res);
|
||||||
|
element = gst_element_factory_create(factory, NULL);
|
||||||
|
padTemplates = gst_element_factory_get_pad_templates(factory);
|
||||||
|
autoplug_close_link(typefind,
|
||||||
|
pad,
|
||||||
|
element,
|
||||||
|
templ->name_template,
|
||||||
|
padTemplates);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gst_caps_free (res);
|
||||||
|
|
||||||
|
/* we only check one sink template per factory, so move on to the
|
||||||
|
* next factory now */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we get here, no item was found */
|
||||||
|
GST_DEBUG("No compatible pad found to decode %s on %s:%s",
|
||||||
|
mime, gst_object_get_name(parent), gst_pad_get_name(pad));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Handle the event when a new type was found.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
autoplug_typefound_handler(GstElement * typefind,
|
||||||
|
gint probability,
|
||||||
|
GstCaps * caps,
|
||||||
|
gpointer userData)
|
||||||
|
{
|
||||||
|
gchar * str;
|
||||||
|
Typefind * tf = (Typefind*) userData;
|
||||||
|
|
||||||
|
g_return_if_fail(tf != NULL);
|
||||||
|
|
||||||
|
str = gst_caps_to_string(caps);
|
||||||
|
GST_DEBUG("Detected media type %s", str);
|
||||||
|
g_free(str);
|
||||||
|
|
||||||
|
/* actually plug now */
|
||||||
|
autoplug_try_to_plug(tf, gst_element_get_pad(typefind, "src"), caps);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Filter the features that we're interested in.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
autoplug_error_handler(GstElement * pipeline,
|
||||||
|
GstElement * source,
|
||||||
|
GError * error,
|
||||||
|
gchar * message,
|
||||||
|
gpointer userData)
|
||||||
|
{
|
||||||
|
/* TODO: handle error somehow */
|
||||||
|
GST_DEBUG("error: %s", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Remove all typefind elements inside the bin, traversing to lower binds
|
||||||
|
* if necessary. The pads linked to the removed typefind elements are
|
||||||
|
* linked directly instead.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
autoplug_remove_typefind_elements(GstBin * bin)
|
||||||
|
{
|
||||||
|
GstElement * element;
|
||||||
|
const GList * elements;
|
||||||
|
|
||||||
|
elements = gst_bin_get_list(GST_BIN(bin));
|
||||||
|
while (elements) {
|
||||||
|
GstElementFactory * factory;
|
||||||
|
GType type;
|
||||||
|
|
||||||
|
element = (GstElement*) elements->data;
|
||||||
|
factory = gst_element_get_factory(element);
|
||||||
|
type = gst_element_factory_get_element_type(factory);
|
||||||
|
|
||||||
|
GST_DEBUG("found factory: %s of type %s, is bin: %d",
|
||||||
|
gst_element_factory_get_longname(factory),
|
||||||
|
g_type_name(type),
|
||||||
|
g_type_is_a(type, GST_TYPE_BIN));
|
||||||
|
|
||||||
|
if (GST_IS_BIN(element)) {
|
||||||
|
autoplug_remove_typefind_elements(GST_BIN(element));
|
||||||
|
} else if (g_strrstr(gst_element_factory_get_longname(factory),
|
||||||
|
"TypeFind")) {
|
||||||
|
GstPad * tfSinkPad;
|
||||||
|
GstPad * tfSrcPad;
|
||||||
|
GstPad * sinkPad;
|
||||||
|
GstElement * sinkElement;
|
||||||
|
GstPad * srcPad;
|
||||||
|
GstElement * srcElement;
|
||||||
|
GstElement * parent;
|
||||||
|
GstPad * parentSrcPad;
|
||||||
|
GstPad * parentSinkPad;
|
||||||
|
|
||||||
|
tfSinkPad = gst_element_get_pad(element, "sink");
|
||||||
|
tfSrcPad = gst_element_get_pad(element, "src");
|
||||||
|
sinkPad = gst_pad_get_peer(tfSrcPad);
|
||||||
|
sinkElement = gst_pad_get_parent(sinkPad);
|
||||||
|
srcPad = gst_pad_get_peer(tfSinkPad);
|
||||||
|
srcElement = gst_pad_get_parent(srcPad);
|
||||||
|
parent = (GstElement*) gst_element_get_parent(element);
|
||||||
|
parentSrcPad = gst_element_get_pad(parent, "src");
|
||||||
|
parentSinkPad = gst_element_get_pad(parent, "sink");
|
||||||
|
|
||||||
|
gst_element_unlink(srcElement, element);
|
||||||
|
gst_element_unlink(element, sinkElement);
|
||||||
|
|
||||||
|
if (GST_PAD_REALIZE(parentSrcPad) == (GstRealPad*) tfSrcPad) {
|
||||||
|
/* if the pad we want to relink is ghosted by the container */
|
||||||
|
gst_element_remove_pad(parent, parentSrcPad);
|
||||||
|
gst_element_add_ghost_pad(parent, srcPad, "src");
|
||||||
|
gst_element_link(parent, sinkElement);
|
||||||
|
} else if (GST_PAD_REALIZE(parentSinkPad) ==
|
||||||
|
(GstRealPad*) tfSinkPad) {
|
||||||
|
/* if the pad we want to relink is ghosted by the container */
|
||||||
|
gst_element_remove_pad(parent, parentSinkPad);
|
||||||
|
gst_element_add_ghost_pad(parent, sinkPad, "sink");
|
||||||
|
gst_element_link(srcElement, parent);
|
||||||
|
} else {
|
||||||
|
gst_element_link(srcElement, sinkElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_bin_remove(bin, element);
|
||||||
|
|
||||||
|
/* 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));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
elements = elements->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Filter the features that we're interested in.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
GstElement *
|
||||||
|
autoplug_plug_source(GstElement * source)
|
||||||
|
{
|
||||||
|
Typefind typefind;
|
||||||
|
|
||||||
|
typefind.source = source;
|
||||||
|
autoplug_init(&typefind);
|
||||||
|
|
||||||
|
gst_element_set_state(typefind.audiosink, GST_STATE_PAUSED);
|
||||||
|
gst_element_set_state(typefind.sink, GST_STATE_PAUSED);
|
||||||
|
gst_element_set_state(typefind.bin, GST_STATE_PLAYING);
|
||||||
|
gst_element_set_state(typefind.pipeline, GST_STATE_PLAYING);
|
||||||
|
|
||||||
|
/* run */
|
||||||
|
while (!typefind.done && gst_bin_iterate(GST_BIN(typefind.pipeline)));
|
||||||
|
|
||||||
|
/* remove the sink element */
|
||||||
|
gst_element_unlink(typefind.bin, typefind.sink);
|
||||||
|
gst_bin_remove(GST_BIN(typefind.pipeline), typefind.sink);
|
||||||
|
|
||||||
|
/* 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));
|
||||||
|
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));
|
||||||
|
|
||||||
|
return typefind.bin;
|
||||||
|
}
|
||||||
|
|
80
livesupport/modules/gstreamerElements/src/autoplug.h
Normal file
80
livesupport/modules/gstreamerElements/src/autoplug.h
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2004 Media Development Loan Fund
|
||||||
|
|
||||||
|
This file is part of the LiveSupport project.
|
||||||
|
http://livesupport.campware.org/
|
||||||
|
To report bugs, send an e-mail to bugs@campware.org
|
||||||
|
|
||||||
|
LiveSupport is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
LiveSupport 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with LiveSupport; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Author : $Author: maroy $
|
||||||
|
Version : $Revision: 1.1 $
|
||||||
|
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/src/Attic/autoplug.h,v $
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
#ifndef Audioplug_h
|
||||||
|
#define Audioplug_h
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Functions for autoplugging gstreamer elements based on their MIME types.
|
||||||
|
*
|
||||||
|
* @author $Author: maroy $
|
||||||
|
* @version $Revision: 1.1 $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ============================================================ include files */
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* ================================================================ constants */
|
||||||
|
|
||||||
|
|
||||||
|
/* =================================================================== macros */
|
||||||
|
|
||||||
|
|
||||||
|
/* =============================================================== data types */
|
||||||
|
|
||||||
|
|
||||||
|
/* ====================================================== function prototypes */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Autoplug a source element, that contains some form of audio.
|
||||||
|
* The result will be a gstreamer element, that is linked with
|
||||||
|
* source, and produces raw audio on its src pad as it output.
|
||||||
|
*
|
||||||
|
* @param source the source to autoplug.
|
||||||
|
* @return a gstreamer element already linked to source, that produces
|
||||||
|
* the audio provided by source in audio/x-raw-int or
|
||||||
|
* audio/x-raw-float format, as needed.
|
||||||
|
*/
|
||||||
|
GstElement *
|
||||||
|
autoplug_plug_source(GstElement * source);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* Audioplug_h */
|
||||||
|
|
BIN
livesupport/modules/gstreamerElements/var/5seccounter.ogg
Normal file
BIN
livesupport/modules/gstreamerElements/var/5seccounter.ogg
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue