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 $
|
||||
# Version : $Revision: 1.4 $
|
||||
# Version : $Revision: 1.5 $
|
||||
# Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/gstreamerElements/etc/Makefile.in,v $
|
||||
#
|
||||
# @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
|
||||
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_FILE = ${LIB_DIR}/lib${ONESHOT_READER_LIB}.so
|
||||
MINIMAL_AUDIO_SMIL_LIB = livesupport_minimalaudiosmil
|
||||
|
@ -122,26 +125,22 @@ LDFLAGS = @LDFLAGS@ ${GSTREAMER_LIBS} \
|
|||
#-------------------------------------------------------------------------------
|
||||
# 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
|
||||
|
||||
MINIMAL_AUDIO_SMIL_LIB_OBJS = ${TMP_DIR}/seek.o \
|
||||
${TMP_DIR}/util.o \
|
||||
${TMP_DIR}/seek-pack.o \
|
||||
${TMP_DIR}/minimal-audio-smil.o
|
||||
MINIMAL_AUDIO_SMIL_LIB_OBJS = ${TMP_DIR}/minimal-audio-smil.o
|
||||
|
||||
PARTIAL_PLAY_LIB_OBJS = ${TMP_DIR}/seek.o \
|
||||
${TMP_DIR}/util.o \
|
||||
${TMP_DIR}/seek-pack.o \
|
||||
${TMP_DIR}/smil-util.o \
|
||||
${TMP_DIR}/partial-play.o
|
||||
PARTIAL_PLAY_LIB_OBJS = ${TMP_DIR}/partial-play.o
|
||||
|
||||
SWITCHER_LIB_OBJS = ${TMP_DIR}/smil-util.o \
|
||||
${TMP_DIR}/switcher.o
|
||||
SWITCHER_LIB_OBJS = ${TMP_DIR}/switcher.o
|
||||
|
||||
TEST_RUNNER_OBJS = ${TMP_DIR}/TestRunner.o \
|
||||
${TMP_DIR}/seek.o \
|
||||
${TMP_DIR}/util.o \
|
||||
${TMP_DIR}/seek-pack.o \
|
||||
${TMP_DIR}/AutoplugTest.o \
|
||||
${TMP_DIR}/SeekTest.o \
|
||||
${TMP_DIR}/SwitcherTest.o \
|
||||
${TMP_DIR}/SeekPackTest.o \
|
||||
|
@ -149,7 +148,8 @@ TEST_RUNNER_OBJS = ${TMP_DIR}/TestRunner.o \
|
|||
${TMP_DIR}/OneshotReaderTest.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
|
||||
|
||||
all: dir_setup ${ONESHOT_READER_LIB_FILE} \
|
||||
all: dir_setup ${GSTREAMER_ELEMENTS_LIB_FILE} \
|
||||
${ONESHOT_READER_LIB_FILE} \
|
||||
${MINIMAL_AUDIO_SMIL_LIB_FILE} \
|
||||
${PARTIAL_PLAY_LIB_FILE} \
|
||||
${SWITCHER_LIB_FILE} \
|
||||
|
@ -172,6 +173,7 @@ doc:
|
|||
${DOXYGEN} ${DOXYGEN_CONFIG}
|
||||
|
||||
clean:
|
||||
${RM} ${GSTREAMER_ELEMENTS_LIB_OBJS} ${GSTREAMER_ELEMENTS_LIB_FILE}
|
||||
${RM} ${ONESHOT_READER_LIB_OBJS} ${ONESHOT_READER_LIB_FILE}
|
||||
${RM} ${MINIMAL_AUDIO_SMIL_LIB_OBJS} ${MINIMAL_AUDIO_SMIL_LIB_FILE}
|
||||
${RM} ${PARTIAL_PLAY_LIB_OBJS} ${PARTIAL_PLAY_LIB_FILE}
|
||||
|
@ -196,17 +198,24 @@ check: all ${TEST_RUNNER}
|
|||
#-------------------------------------------------------------------------------
|
||||
# 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}
|
||||
|
||||
${MINIMAL_AUDIO_SMIL_LIB_FILE}: ${MINIMAL_AUDIO_SMIL_LIB_OBJS}
|
||||
${CC} -shared ${GST_LDFLAGS} -o $@ $^
|
||||
${MINIMAL_AUDIO_SMIL_LIB_FILE}: ${GSTREAMER_ELEMENTS_LIB_FILE} \
|
||||
${MINIMAL_AUDIO_SMIL_LIB_OBJS}
|
||||
${CC} -shared -o $@ $^ ${GST_LDFLAGS}
|
||||
|
||||
${PARTIAL_PLAY_LIB_FILE}: ${PARTIAL_PLAY_LIB_OBJS}
|
||||
${CC} -shared ${GST_LDFLAGS} -o $@ $^
|
||||
${PARTIAL_PLAY_LIB_FILE}: ${GSTREAMER_ELEMENTS_LIB_FILE} \
|
||||
${PARTIAL_PLAY_LIB_OBJS}
|
||||
${CC} -shared -o $@ $^ ${GST_LDFLAGS}
|
||||
|
||||
${SWITCHER_LIB_FILE}: ${SWITCHER_LIB_OBJS}
|
||||
${CC} -shared ${GST_LDFLAGS} -o $@ $^
|
||||
${SWITCHER_LIB_FILE}: ${SWITCHER_LIB_OBJS} \
|
||||
${GSTREAMER_ELEMENTS_LIB_FILE}
|
||||
${CC} -shared -o $@ $^ ${GST_LDFLAGS}
|
||||
|
||||
${TMP_DIR}:
|
||||
${MKDIR} ${TMP_DIR}
|
||||
|
@ -214,7 +223,8 @@ ${TMP_DIR}:
|
|||
${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}
|
||||
|
||||
${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