From d5f97fd48e14d42246b520217a9d970f4f5b87d9 Mon Sep 17 00:00:00 2001 From: nebojsa Date: Mon, 21 Jan 2008 18:14:22 +0000 Subject: [PATCH] resolved conflicts --- campcaster/bin/dist.sh | 2 +- campcaster/etc/Makefile.in | 13 +- campcaster/etc/configure.ac | 6 +- .../playlistExecutor/src/GstreamerPlayer.cxx | 510 ++++-------------- .../playlistExecutor/src/GstreamerPlayer.h | 161 +----- .../products/gLiveSupport/etc/configure.ac | 6 +- 6 files changed, 154 insertions(+), 544 deletions(-) diff --git a/campcaster/bin/dist.sh b/campcaster/bin/dist.sh index 854b5570c..80766cf6c 100755 --- a/campcaster/bin/dist.sh +++ b/campcaster/bin/dist.sh @@ -157,7 +157,7 @@ xmlrpcxx_version=xmlrpc++-20040713 xmlrpcxx_tmpdir=$tools_tmpdir/xmlrpc++ gstreamer_dir=$toolsdir/gstreamer -gstreamer_version=gstreamer-0.8.12 +gstreamer_version=gstreamer-0.10.15 gstreamer_tmpdir=$tools_tmpdir/gstreamer taglib_dir=$toolsdir/taglib diff --git a/campcaster/etc/Makefile.in b/campcaster/etc/Makefile.in index 9839486db..e53598e8f 100644 --- a/campcaster/etc/Makefile.in +++ b/campcaster/etc/Makefile.in @@ -108,7 +108,7 @@ LIBODBCXX_VERSION = libodbc++-0.2.3-20050404 XMLRPCXX_DIR = ${TOOLS_DIR}/xmlrpc++ XMLRPCXX_VERSION = xmlrpc++-20040713 GSTREAMER_DIR = ${TOOLS_DIR}/gstreamer -GSTREAMER_VERSION = gstreamer-0.8.12 +GSTREAMER_VERSION = gstreamer-0.10.15 TAGLIB_DIR = ${TOOLS_DIR}/taglib TAGLIB_VERSION = taglib-1.4 LIBSERIAL_DIR = ${TOOLS_DIR}/libserial @@ -120,7 +120,6 @@ CORE_DIR = ${MODULES_DIR}/core AUTHENTICATION_DIR = ${MODULES_DIR}/authentication DB_DIR = ${MODULES_DIR}/db STORAGE_CLIENT_DIR = ${MODULES_DIR}/storageClient -GSTREAMER_ELEMENTS_DIR = ${MODULES_DIR}/gstreamerElements PLAYLIST_EXECUTOR_DIR = ${MODULES_DIR}/playlistExecutor EVENT_SCHEDULER_DIR = ${MODULES_DIR}/eventScheduler SCHEDULER_CLIENT_DIR = ${MODULES_DIR}/schedulerClient @@ -181,8 +180,6 @@ flawfinder: ${AUTHENTICATION_DIR}/include ${AUTHENTICATION_DIR}/src \ ${DB_DIR}/include ${DB_DIR}/src \ ${STORAGE_CLIENT_DIR}/include ${STORAGE_CLIENT_DIR}/src \ - ${GSTREAMER_ELEMENTS_DIR}/include \ - ${GSTREAMER_ELEMENTS_DIR}/src \ ${PLAYLIST_EXECUTOR_DIR}/include \ ${PLAYLIST_EXECUTOR_DIR}/src \ ${EVENT_SCHEDULER_DIR}/include ${EVENT_SCHEDULER_DIR}/src \ @@ -297,9 +294,6 @@ ${TMP_DIR}/modules_setup.stamp: cd ${STORAGE_CLIENT_DIR} && \ ./configure --prefix=${prefix} --enable-debug=${DEBUG} \ PACKAGE_VERSION=${PACKAGE_VERSION} - cd ${GSTREAMER_ELEMENTS_DIR} && \ - ./configure --prefix=${prefix} --enable-debug=${DEBUG} \ - PACKAGE_VERSION=${PACKAGE_VERSION} cd ${PLAYLIST_EXECUTOR_DIR} && \ ./configure --prefix=${prefix} --enable-debug=${DEBUG} \ PACKAGE_VERSION=${PACKAGE_VERSION} @@ -352,7 +346,6 @@ modprod_distclean: ${MAKE} -C ${AUTHENTICATION_DIR} distclean ${MAKE} -C ${DB_DIR} distclean ${MAKE} -C ${STORAGE_CLIENT_DIR} distclean - ${MAKE} -C ${GSTREAMER_ELEMENTS_DIR} distclean ${MAKE} -C ${PLAYLIST_EXECUTOR_DIR} distclean ${MAKE} -C ${EVENT_SCHEDULER_DIR} distclean ${MAKE} -C ${SCHEDULER_CLIENT_DIR} distclean @@ -368,7 +361,6 @@ depclean: ${MAKE} -C ${AUTHENTICATION_DIR} depclean ${MAKE} -C ${DB_DIR} depclean ${MAKE} -C ${STORAGE_CLIENT_DIR} depclean - ${MAKE} -C ${GSTREAMER_ELEMENTS_DIR} depclean ${MAKE} -C ${PLAYLIST_EXECUTOR_DIR} depclean ${MAKE} -C ${EVENT_SCHEDULER_DIR} depclean ${MAKE} -C ${SCHEDULER_CLIENT_DIR} depclean @@ -384,7 +376,6 @@ ${TMP_DIR}/compile.stamp: ${MAKE} -C ${AUTHENTICATION_DIR} all ${MAKE} -C ${DB_DIR} all ${MAKE} -C ${STORAGE_CLIENT_DIR} all - ${MAKE} -C ${GSTREAMER_ELEMENTS_DIR} all ${MAKE} -C ${PLAYLIST_EXECUTOR_DIR} all ${MAKE} -C ${EVENT_SCHEDULER_DIR} all ${MAKE} -C ${SCHEDULER_CLIENT_DIR} all @@ -398,7 +389,6 @@ check: -${MAKE} -C ${AUTHENTICATION_DIR} check -${MAKE} -C ${DB_DIR} check -${MAKE} -C ${STORAGE_CLIENT_DIR} check - -${MAKE} -C ${GSTREAMER_ELEMENTS_DIR} check # -${MAKE} -C ${PLAYLIST_EXECUTOR_DIR} check # hangs on edge.campware.org -${MAKE} -C ${EVENT_SCHEDULER_DIR} check -${MAKE} -C ${SCHEDULER_CLIENT_DIR} check @@ -462,7 +452,6 @@ install_modules: ${MAKE} -C ${AUTHENTICATION_DIR} install ${MAKE} -C ${DB_DIR} install ${MAKE} -C ${STORAGE_CLIENT_DIR} install - ${MAKE} -C ${GSTREAMER_ELEMENTS_DIR} install ${MAKE} -C ${PLAYLIST_EXECUTOR_DIR} install ${MAKE} -C ${EVENT_SCHEDULER_DIR} install ${MAKE} -C ${SCHEDULER_CLIENT_DIR} install diff --git a/campcaster/etc/configure.ac b/campcaster/etc/configure.ac index 5e5a11e57..2aa867182 100644 --- a/campcaster/etc/configure.ac +++ b/campcaster/etc/configure.ac @@ -339,10 +339,6 @@ dnl set up the storage client module AC_CONFIG_COMMANDS([../src/modules/storageClient/tmp/configure], [../src/modules/storageClient/bin/autogen.sh]) -dnl set up the gstreamer elements module -AC_CONFIG_COMMANDS([../src/modules/gstreamerElements/tmp/configure], - [../src/modules/gstreamerElements/bin/autogen.sh]) - dnl set up the playlist executor module AC_CONFIG_COMMANDS([../src/modules/playlistExecutor/tmp/configure], [../src/modules/playlistExecutor/bin/autogen.sh]) @@ -376,7 +372,7 @@ AC_MSG_NOTICE( by Campcaster: cppunit 1.10.2 ${COMPILE_CPPUNIT} - gstreamer 0.8.12 yes + gstreamer 0.10.15 yes libodbc++ 0.2.3 yes taglib 1.4 yes xmlrpc++ 2004-07-13 yes diff --git a/campcaster/src/modules/playlistExecutor/src/GstreamerPlayer.cxx b/campcaster/src/modules/playlistExecutor/src/GstreamerPlayer.cxx index 4fba5cbff..d7d4cc34c 100644 --- a/campcaster/src/modules/playlistExecutor/src/GstreamerPlayer.cxx +++ b/campcaster/src/modules/playlistExecutor/src/GstreamerPlayer.cxx @@ -37,6 +37,7 @@ #include "LiveSupport/Core/Debug.h" #include "LiveSupport/Core/TimeConversion.h" + #include "GstreamerPlayer.h" @@ -65,6 +66,42 @@ static const std::string audioDeviceName = "audioDevice"; /* ============================================================= module code */ +static gboolean my_bus_callback (GstBus *bus, GstMessage *message, gpointer data) +{ + + GstreamerPlayer* const player = (GstreamerPlayer*) data; + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_EOS: + if(player->playNextSmil()){ + break; + } + player->close(); + // Important: We *must* use an idle function call here, so that the signal handler returns + // before fireOnStopEvent() is executed. + g_idle_add(GstreamerPlayer::fireOnStopEvent, data); + break; + case GST_MESSAGE_ERROR: + // We make sure that we don't send multiple error messages in a row to the GUI + if (!player->m_errorWasRaised) { + GError *gerror; + gchar *debug; + gst_message_parse_error (message, &gerror, &debug); + player->m_errorMessage.reset(new const Glib::ustring(gerror->message)); + player->m_errorWasRaised = true; + + std::cerr << "gstreamer error: " << gerror->message << std::endl; + g_error_free (gerror); + g_free (debug); + // Important: We *must* use an idle function call here, so that the signal handler returns + // before fireOnStopEvent() is executed. + g_idle_add(GstreamerPlayer::fireOnStopEvent, data); + } + break; + } +} + + /*------------------------------------------------------------------------------ * Configure the Audio Player. *----------------------------------------------------------------------------*/ @@ -102,65 +139,19 @@ GstreamerPlayer :: initialize(void) throw (std::exception) } // initialize the gstreamer library - if (!gst_init_check(0, 0)) { + if (!gst_init_check(0, 0, 0)) { throw std::runtime_error("couldn't initialize the gstreamer library"); } - // create the pipeline container (threaded) - m_pipeline = gst_thread_new("audio-player"); + m_playContext = new GstreamerPlayContext(); - m_filesrc = 0; - m_decoder = 0; - m_audioconvert = 0; - m_audioscale = 0; - - g_signal_connect(m_pipeline, "error", G_CALLBACK(errorHandler), this); - - // TODO: read the caps from the config file - m_sinkCaps = gst_caps_new_simple("audio/x-raw-int", - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "endiannes", G_TYPE_INT, G_BYTE_ORDER, - "channels", G_TYPE_INT, 2, - "rate", G_TYPE_INT, 44100, - NULL); - - setAudioDevice(m_audioDevice); + m_playContext->setParentData(this); // set up other variables m_initialized = true; } -/*------------------------------------------------------------------------------ - * Handler for gstreamer errors. - *----------------------------------------------------------------------------*/ -void -GstreamerPlayer :: errorHandler(GstElement * pipeline, - GstElement * source, - GError * error, - gchar * debug, - gpointer self) - throw () -{ - DEBUG_BLOCK - - GstreamerPlayer* const player = (GstreamerPlayer*) self; - - // We make sure that we don't send multiple error messages in a row to the GUI - if (!player->m_errorWasRaised) { - player->m_errorMessage.reset(new const Glib::ustring(error->message)); - player->m_errorWasRaised = true; - - std::cerr << "gstreamer error: " << error->message << std::endl; - - // Important: We *must* use an idle function call here, so that the signal handler returns - // before fireOnStopEvent() is executed. - g_idle_add(fireOnStopEvent, self); - } -} - - /*------------------------------------------------------------------------------ * De-initialize the Gstreamer Player *----------------------------------------------------------------------------*/ @@ -170,23 +161,13 @@ GstreamerPlayer :: deInitialize(void) throw () DEBUG_FUNC_INFO if (m_initialized) { - gst_element_set_state(m_pipeline, GST_STATE_NULL); - gst_bin_sync_children_state(GST_BIN(m_pipeline)); - - if (!gst_element_get_parent(m_audiosink)) { - // delete manually, if audiosink wasn't added to the pipeline - // for some reason - gst_object_unref(GST_OBJECT(m_audiosink)); - } - gst_object_unref(GST_OBJECT(m_pipeline)); - gst_caps_free(m_sinkCaps); - - m_audiosink = 0; + m_playContext->closeContext(); + delete m_playContext; + m_playContext = NULL; m_initialized = false; } } - /*------------------------------------------------------------------------------ * Attach an event listener. *----------------------------------------------------------------------------*/ @@ -224,15 +205,15 @@ GstreamerPlayer :: detachListener(AudioPlayerEventListener* eventListener) * Send the onStop event to all attached listeners. *----------------------------------------------------------------------------*/ gboolean -GstreamerPlayer :: fireOnStopEvent(gpointer self) throw () +GstreamerPlayer :: fireOnStopEvent(gpointer self) throw () { DEBUG_BLOCK + GstreamerPlayer* const player = (GstreamerPlayer*) self; ListenerVector::iterator it = player->m_listeners.begin(); ListenerVector::iterator end = player->m_listeners.end(); - while (it != end) { (*it)->onStop(player->m_errorMessage); ++it; @@ -245,51 +226,6 @@ GstreamerPlayer :: fireOnStopEvent(gpointer self) throw ( } -/*------------------------------------------------------------------------------ - * An EOS event handler, that will put the pipeline to EOS as well. - *----------------------------------------------------------------------------*/ -void -GstreamerPlayer :: eosEventHandler(GstElement * element, - gpointer self) - throw () -{ - DEBUG_BLOCK - - GstreamerPlayer* const player = (GstreamerPlayer*) self; - - gst_element_set_eos(player->m_pipeline); - - // Important: We *must* use an idle function call here, so that the signal handler returns - // before fireOnStopEvent() is executed. - g_idle_add(fireOnStopEvent, player); -} - - -/*------------------------------------------------------------------------------ - * NewPad event handler. Links the decoder after decodebin's autoplugging. - *----------------------------------------------------------------------------*/ -void -GstreamerPlayer::newpadEventHandler(GstElement*, GstPad* pad, gboolean, gpointer self) throw () -{ - DEBUG_BLOCK - - GstreamerPlayer* const player = (GstreamerPlayer*) self; - GstPad* const audiopad = gst_element_get_pad(player->m_audioconvert, "sink"); - - if (GST_PAD_IS_LINKED(audiopad)) { - debug() << "audiopad is already linked. Unlinking old pad." << endl; - gst_pad_unlink(audiopad, GST_PAD_PEER(audiopad)); - } - - gst_pad_link(pad, audiopad); - - if (gst_element_get_parent(player->m_audiosink) == NULL) - gst_bin_add(GST_BIN(player->m_pipeline), player->m_audiosink); - - gst_bin_sync_children_state(GST_BIN(player->m_pipeline)); -} - - /*------------------------------------------------------------------------------ * Preload a file, to speed up the subsequent open() call. *----------------------------------------------------------------------------*/ @@ -299,18 +235,10 @@ GstreamerPlayer :: preload(const std::string fileUrl) std::runtime_error) { DEBUG_BLOCK - - if (m_preloadThread) { - m_preloadThread->stop(); - m_preloadThread->join(); - m_preloadThread.reset(); - } - - Ptr::Ref loader; - loader.reset(new Preloader(this, fileUrl)); - - m_preloadThread.reset(new Thread(loader)); - m_preloadThread->start(); + //According to the Gstreamer documentation, stream buffering happens + //automatically when the pipeline is set to GST_STATE_PAUSED. + //As this state is now set automatically in the open function, + //we no longer have a need for preloading. } @@ -318,100 +246,61 @@ GstreamerPlayer :: preload(const std::string fileUrl) * Specify which file to play *----------------------------------------------------------------------------*/ void -GstreamerPlayer :: open(const std::string fileUrl) +GstreamerPlayer :: open(const std::string fileUri) throw (std::invalid_argument, std::runtime_error) { - // GStreamer pipeline overview: - // filesrc -> decoder -> audioconvert -> audioscale -> audiosink - DEBUG_BLOCK if (isOpen()) { close(); } + + m_smilOffset = 0L; - debug() << "Opening URL: " << fileUrl << endl; + debug() << "Opening URL: " << fileUri << endl; debug() << "Timestamp: " << *TimeConversion::now() << endl; m_errorMessage.reset(); m_errorWasRaised = false; - std::string filePath; - - if (fileUrl.find("file://") == 0) { - filePath = fileUrl.substr(7, fileUrl.size()); - } - else if (fileUrl.find("file:") == 0) { - filePath = fileUrl.substr(5, fileUrl.size()); - } - else { - throw std::invalid_argument("badly formed URL or unsupported protocol"); + m_playContext->setAudioDevice(m_audioDevice); + if (fileUri.find(std::string(".smil")) != std::string::npos) { + m_smilHandler = new SmilHandler(); + m_smilHandler->openSmilFile(fileUri.c_str()); + AudioDescription *audioDescription = m_smilHandler->getNext(); + m_open=m_playContext->openSource(audioDescription); + }else{ + m_open=m_playContext->openSource(fileUri.c_str()); } - if (m_preloadThread) { - debug() << "Waiting for Preloader thread to finish..." << endl; - m_preloadThread->join(); + if(!m_open){ + m_errorMessage.reset(new const Glib::ustring("GstreamerPlayer :: open failed! Please consult console output for details.")); + m_errorWasRaised = true; + fireOnStopEvent(this); } +} - const bool isSmil = fileUrl.substr(fileUrl.size()-5, fileUrl.size()) == ".smil" ? true : false; - const bool isPreloaded = (m_preloadUrl == fileUrl); - - if (isPreloaded) - m_filesrc = m_preloadFilesrc; - else { - m_filesrc = gst_element_factory_make("filesrc", "file-source"); - gst_element_set(m_filesrc, "location", filePath.c_str(), NULL); +bool +GstreamerPlayer :: playNextSmil(void) throw () +{ + DEBUG_BLOCK + m_currentPlayLength = m_playContext->getPosition();//this gets the length of the stream that just completed + m_playContext->closeContext(); + if(m_smilHandler == NULL){ + return false; } - - // converts between different audio formats (e.g. bitrate) - m_audioconvert = gst_element_factory_make("audioconvert", NULL); - - // scale the sampling rate, if necessary - m_audioscale = gst_element_factory_make("audioscale", NULL); - - // Due to bugs in the minimalaudiosmil element, it does not currently work with decodebin. - // Therefore we instantiate it manually if the file has the .smil extension. - if (isSmil) { - if (isPreloaded) { - debug() << "Using preloaded SMIL element instance." << endl; - m_decoder = m_preloadDecoder; - gst_element_link(m_decoder, m_audioconvert); - } - else { - debug() << "SMIL file detected." << endl; - m_stopPreloader = false; - m_decoder = gst_element_factory_make("minimalaudiosmil", NULL); - gst_element_set(m_decoder, "abort", &m_stopPreloader, NULL); - gst_element_link_many(m_filesrc, m_decoder, m_audioconvert, NULL); - } - if (gst_element_get_parent(m_audiosink) == NULL) - gst_bin_add(GST_BIN(m_pipeline), m_audiosink); + AudioDescription *audioDescription = m_smilHandler->getNext(); + if(audioDescription == NULL){//no more audio entries to play + delete m_smilHandler; + m_smilHandler = NULL; + return false; } - // Using GStreamer's decodebin autoplugger for everything else - else { - m_decoder = gst_element_factory_make("decodebin", NULL); - gst_element_link(m_filesrc, m_decoder); - g_signal_connect(m_decoder, "new-decoded-pad", G_CALLBACK(newpadEventHandler), this); - } - - if (!m_decoder) { - throw std::runtime_error("GstreamerPlayer: could not create decoder"); - } - - gst_bin_add_many(GST_BIN(m_pipeline), m_filesrc, m_decoder, m_audioconvert, m_audioscale, NULL); - - gst_element_link_many(m_audioconvert, m_audioscale, m_audiosink, NULL); - - // connect the eos signal handler - g_signal_connect(m_decoder, "eos", G_CALLBACK(eosEventHandler), this); - - m_preloadUrl.clear(); - - if (gst_element_set_state(m_pipeline,GST_STATE_PAUSED) == GST_STATE_FAILURE) { - close(); - throw std::runtime_error("GstreamerPlayer: could not open file"); + if(!m_playContext->openSource(audioDescription)){ + return false; } + m_smilOffset += m_currentPlayLength; + m_playContext->playContext(); } @@ -421,34 +310,30 @@ GstreamerPlayer :: open(const std::string fileUrl) bool GstreamerPlayer :: isOpen(void) throw () { - return m_decoder != 0; + return m_open; } /*------------------------------------------------------------------------------ * Get the length of the current audio clip. + * Currently not used by the Studio, but may be used later on. *----------------------------------------------------------------------------*/ Ptr::Ref GstreamerPlayer :: getPlaylength(void) throw (std::logic_error) { - Ptr::Ref length; - gint64 ns; - GstFormat format = GST_FORMAT_TIME; - + DEBUG_BLOCK + if (!isOpen()) { throw std::logic_error("player not open"); } + + Ptr::Ref length; + + gint64 ns = m_playContext->getPlayLength(); + + length.reset(new time_duration(microsec(ns / 1000LL))); - if (m_decoder - && gst_element_query(m_decoder, GST_QUERY_TOTAL, &format, &ns) - && format == GST_FORMAT_TIME) { - - // use microsec, as nanosec() is not found by the compiler (?) - length.reset(new time_duration(microsec(ns / 1000LL))); - } else { - length.reset(new time_duration(microsec(0LL))); - } - + debug() << length << endl; return length; } @@ -460,16 +345,14 @@ Ptr::Ref GstreamerPlayer :: getPosition(void) throw (std::logic_error) { Ptr::Ref length; - gint64 ns = 0; if (!isOpen()) { throw std::logic_error("player not open"); } - - GstFormat fmt = GST_FORMAT_TIME; - gst_element_query(m_audiosink, GST_QUERY_POSITION, &fmt, &ns); - - length.reset(new time_duration(microseconds(ns / 1000LL))); + + gint64 ns = m_playContext->getPosition(); + + length.reset(new time_duration(microseconds((m_smilOffset + ns) / 1000LL))); return length; } @@ -488,7 +371,9 @@ GstreamerPlayer :: start(void) throw (std::logic_error) } if (!isPlaying()) { - gst_element_set_state(m_pipeline, GST_STATE_PLAYING); + m_playContext->playContext(); + }else{ + error() << "Already playing!" << endl; } } @@ -499,8 +384,10 @@ GstreamerPlayer :: start(void) throw (std::logic_error) void GstreamerPlayer :: pause(void) throw (std::logic_error) { + DEBUG_BLOCK + if (isPlaying()) { - gst_element_set_state(m_pipeline, GST_STATE_PAUSED); + m_playContext->pauseContext(); } } @@ -511,7 +398,7 @@ GstreamerPlayer :: pause(void) throw (std::logic_error) bool GstreamerPlayer :: isPlaying(void) throw () { - return gst_element_get_state(m_pipeline) == GST_STATE_PLAYING; + return m_playContext->isPlaying(); } @@ -521,12 +408,14 @@ GstreamerPlayer :: isPlaying(void) throw () void GstreamerPlayer :: stop(void) throw (std::logic_error) { + DEBUG_BLOCK + if (!isOpen()) { throw std::logic_error("GstreamerPlayer not opened yet"); } if (isPlaying()) { - gst_element_set_state(m_pipeline, GST_STATE_READY); + m_playContext->stopContext(); } } @@ -539,48 +428,14 @@ GstreamerPlayer :: close(void) throw (std::logic_error) { DEBUG_BLOCK - if (isPlaying()) { - stop(); + m_playContext->stopContext(); + m_playContext->closeContext(); + if(m_smilHandler != NULL){ + delete m_smilHandler; + m_smilHandler = NULL; } - gst_element_set_state(m_pipeline, GST_STATE_NULL); - - // Unlink elements: - if (m_filesrc && m_decoder) { - gst_element_unlink(m_filesrc, m_decoder); - } - if (m_decoder && m_audioconvert) { - gst_element_unlink(m_decoder, m_audioconvert); - } - if (m_audioconvert && m_audioscale ) { - gst_element_unlink(m_audioconvert, m_audioscale); - } - if (m_audioscale && m_audiosink) { - gst_element_unlink(m_audioscale, m_audiosink); - } - - // Remove elements from pipeline: - if (m_audioscale) { - gst_bin_remove(GST_BIN(m_pipeline), m_audioscale); - } - if (m_audioconvert) { - gst_bin_remove(GST_BIN(m_pipeline), m_audioconvert); - } - if (m_decoder) { - gst_bin_remove(GST_BIN(m_pipeline), m_decoder); - } - if (m_filesrc) { - gst_bin_remove(GST_BIN(m_pipeline), m_filesrc); - } - if (m_audiosink && gst_element_get_parent(m_audiosink) == GST_OBJECT(m_pipeline)) { - gst_object_ref(GST_OBJECT(m_audiosink)); - gst_bin_remove(GST_BIN(m_pipeline), m_audiosink); - } - - m_filesrc = 0; - m_decoder = 0; - m_audioconvert = 0; - m_audioscale = 0; + m_open = false; } @@ -611,145 +466,14 @@ GstreamerPlayer :: setAudioDevice(const std::string &deviceName) { DEBUG_BLOCK + debug() << "Using device: " << deviceName << endl; + if (deviceName.size() == 0) { return false; } - const bool oss = deviceName.find("/dev") == 0; - - if (m_audiosink) { - debug() << "Destroying old sink." << endl; - if (m_audioscale) { - gst_element_unlink(m_audioscale, m_audiosink); - } - if (gst_element_get_parent(m_audiosink) == NULL) - gst_object_unref(GST_OBJECT(m_audiosink)); - else - gst_bin_remove(GST_BIN(m_pipeline), m_audiosink); - m_audiosink = 0; - } - - if (!m_audiosink) { - m_audiosink = (oss ? gst_element_factory_make("osssink", "osssink") - : gst_element_factory_make("alsasink", "alsasink")); - } - if (!m_audiosink) { - return false; - } - - // it's the same property, "device" for both alsasink and osssink - gst_element_set(m_audiosink, "device", deviceName.c_str(), NULL); - - if (m_audioscale) { - gst_element_link_filtered(m_audioscale, m_audiosink, m_sinkCaps); - } + m_playContext->setAudioDevice(deviceName); return true; } - - -////////////////////////////////////////////////////////////////////////////// -// CLASS Preloader -////////////////////////////////////////////////////////////////////////////// - -Preloader::Preloader(GstreamerPlayer* player, const std::string url) throw() - : RunnableInterface() - , m_player(player) - , m_fileUrl(url) -{ - DEBUG_FUNC_INFO - - player->m_stopPreloader = false; -} - - -Preloader::~Preloader() throw() -{ - DEBUG_FUNC_INFO -} - - -void Preloader::run() throw() -{ - DEBUG_BLOCK - - GstreamerPlayer* const p = m_player; - const std::string fileUrl(m_fileUrl); - - const bool isSmil = fileUrl.substr(fileUrl.size()-5, fileUrl.size()) == ".smil" ? true : false; - if (!isSmil) - return; - - debug() << "Preloading SMIL file: " << fileUrl << endl; - - std::string filePath; - - if (fileUrl.find("file://") == 0) { - filePath = fileUrl.substr(7, fileUrl.size()); - } - else if (fileUrl.find("file:") == 0) { - filePath = fileUrl.substr(5, fileUrl.size()); - } - else { - return; - } - - if (!p->m_preloadUrl.empty()) { - p->m_preloadUrl.clear(); - g_object_unref(G_OBJECT(p->m_preloadFilesrc)); - g_object_unref(G_OBJECT(p->m_preloadDecoder)); - } - - p->m_preloadFilesrc = gst_element_factory_make("filesrc", NULL); - gst_element_set(p->m_preloadFilesrc, "location", filePath.c_str(), NULL); - - p->m_preloadDecoder = gst_element_factory_make("minimalaudiosmil", NULL); - gst_element_set(p->m_preloadDecoder, "abort", &p->m_stopPreloader, NULL); - - GstElement* pipe = gst_pipeline_new("pipe"); - GstElement* fakesink = gst_element_factory_make("fakesink", "fakesink"); - gst_element_link_many(p->m_preloadFilesrc, p->m_preloadDecoder, fakesink, NULL); - gst_bin_add_many(GST_BIN(pipe), p->m_preloadFilesrc, p->m_preloadDecoder, fakesink, NULL); - - gst_element_set_state(pipe, GST_STATE_PLAYING); - - gint64 position = 0LL; - while (position == 0LL && !p->m_stopPreloader && gst_bin_iterate(GST_BIN(pipe))) { - GstFormat format = GST_FORMAT_DEFAULT; - gst_element_query(fakesink, GST_QUERY_POSITION, &format, &position); - } - - gst_element_set_state(pipe, GST_STATE_PAUSED); - - if (p->m_stopPreloader) { - debug() << "Aborting preloader, per request." << endl; - g_object_unref(G_OBJECT(p->m_preloadFilesrc)); - g_object_unref(G_OBJECT(p->m_preloadDecoder)); - return; - } - - g_object_ref(G_OBJECT(p->m_preloadFilesrc)); - g_object_ref(G_OBJECT(p->m_preloadDecoder)); - gst_bin_remove_many(GST_BIN(pipe), p->m_preloadFilesrc, p->m_preloadDecoder, NULL); - gst_element_unlink(p->m_preloadFilesrc, fakesink); - gst_object_unref(GST_OBJECT(pipe)); - - p->m_preloadUrl = fileUrl; - - p->m_preloadThread.reset(); -} - - -void Preloader::signal(int) throw() -{} - - -void Preloader::stop() throw() -{ - DEBUG_FUNC_INFO - - m_player->m_stopPreloader = true; -} - - diff --git a/campcaster/src/modules/playlistExecutor/src/GstreamerPlayer.h b/campcaster/src/modules/playlistExecutor/src/GstreamerPlayer.h index 5bd18e647..6b0e49d43 100644 --- a/campcaster/src/modules/playlistExecutor/src/GstreamerPlayer.h +++ b/campcaster/src/modules/playlistExecutor/src/GstreamerPlayer.h @@ -50,6 +50,7 @@ #include "LiveSupport/Core/Playlist.h" +#include "GstreamerPlayContext.h" namespace LiveSupport { namespace PlaylistExecutor { @@ -92,7 +93,6 @@ using namespace LiveSupport::Core; class GstreamerPlayer : virtual public Configurable, virtual public AudioPlayerInterface { - friend class Preloader; private: /** @@ -103,37 +103,9 @@ class GstreamerPlayer : virtual public Configurable, /** * The pipeline inside the player */ - GstElement * m_pipeline; + GstreamerPlayContext *m_playContext; + SmilHandler *m_smilHandler; - /** - * The file source element. - */ - GstElement * m_filesrc; - - /** - * The decoder element. - */ - GstElement * m_decoder; - - /** - * The audioconvert element. - */ - GstElement * m_audioconvert; - - /** - * The audioscale element. - */ - GstElement * m_audioscale; - - /** - * The desired capabilities of the audio sink. - */ - GstCaps * m_sinkCaps; - - /** - * The audio sink - */ - GstElement * m_audiosink; /** * The URL to play. @@ -144,12 +116,23 @@ class GstreamerPlayer : virtual public Configurable, * Flag to indicate if this object has been initialized. */ bool m_initialized; + bool m_open; /** * The audio device to play on. */ std::string m_audioDevice; + /** + * The URL of the preloaded file. Empty if nothing is preloaded. + */ + std::string m_preloadUrl; + + gint64 m_smilOffset; + gint64 m_currentPlayLength; + +public: + /** * Contains runtime error messages from GStreamer. */ @@ -160,32 +143,6 @@ class GstreamerPlayer : virtual public Configurable, */ bool m_errorWasRaised; - /** - * The URL of the preloaded file. Empty if nothing is preloaded. - */ - std::string m_preloadUrl; - - /** - * The filesrc element created by the preloader. - */ - GstElement * m_preloadFilesrc; - - /** - * The decoder element created by the preloader - */ - GstElement * m_preloadDecoder; - - /** - * The thread that runs the preloader instance. - */ - Ptr::Ref m_preloadThread; - - /** - * Flag that indicates that the preloader should abort. - */ - - gboolean m_stopPreloader; - /** * The type for the vector of listeners. * Just a shorthand notation, to make reference to the type @@ -200,49 +157,12 @@ class GstreamerPlayer : virtual public Configurable, */ ListenerVector m_listeners; - /** - * Handler to recieve errors from gstreamer. - * - * @param pipeline the pipeline generating the error - * @param source the source of the error - * @param error the error itself - * @param debug debug info - * @param self pointer to the associated GsreamerPlayer object. - */ - static void - errorHandler(GstElement * pipeline, - GstElement * source, - GError * error, - gchar * debug, - gpointer self) throw (); - - /** - * An end-of-stream event handler, that will notify our pipeline, - * that it's all over. - * - * @param element the element emitting the eos signal - * @param self a pointer to the associated GstreamerPlayer object. - */ - static void - eosEventHandler(GstElement * element, - gpointer self) - throw (); - /** - * A newpad event handler, that will link the decoder after - * decodebin's autoplugging. - * - * @param element the element emitting the eos signal - * @param self a pointer to the associated GstreamerPlayer object. - */ - static void - newpadEventHandler(GstElement*, GstPad*, gboolean, gpointer self) throw(); - /** * Send the onStop event to all attached listeners. */ static gboolean - fireOnStopEvent(gpointer self) throw (); + fireOnStopEvent(gpointer self) throw (); public: @@ -251,11 +171,12 @@ class GstreamerPlayer : virtual public Configurable, */ GstreamerPlayer(void) throw () { - m_pipeline = 0; - m_filesrc = 0; - m_decoder = 0; - m_audiosink = 0; + m_playContext = 0; + m_open = false; m_initialized = false; + m_smilHandler = NULL; + m_smilOffset = 0L; + m_currentPlayLength = 0L; } /** @@ -377,6 +298,15 @@ class GstreamerPlayer : virtual public Configurable, virtual bool isOpen(void) throw (); + /** + * Plays next audio from current smil sequence + * + * + * @return true if next smil is available, false otherwise. + */ + virtual bool + playNextSmil(void) throw (); + /** * Close an audio source that was opened. * @@ -468,39 +398,6 @@ class GstreamerPlayer : virtual public Configurable, -/** - * A class for preloading GStreamer SMIL decoder instances. - * - * Preloading initializes the decoder element in a helper thread, so - * that most of the initialization overhead is eleminated when playback - * is started. - * - * @author $Author$ - * @version $Revision$ - */ -class Preloader : public RunnableInterface -{ - public: - Preloader(GstreamerPlayer*, const std::string) throw(); - ~Preloader() throw(); - - void run() throw(); - void signal(int) throw(); - void stop() throw(); - - private: - /** - * Pointer to GstreamerPlayer class instance. - */ - GstreamerPlayer* m_player; - - /** - * The URL of the file to be preloaded. - */ - std::string m_fileUrl; -}; - - /* ================================================= external data structures */ diff --git a/campcaster/src/products/gLiveSupport/etc/configure.ac b/campcaster/src/products/gLiveSupport/etc/configure.ac index 2b0881436..006c92195 100644 --- a/campcaster/src/products/gLiveSupport/etc/configure.ac +++ b/campcaster/src/products/gLiveSupport/etc/configure.ac @@ -105,10 +105,14 @@ PKG_CHECK_MODULES(LIBGLADEMM,[libglademm-2.4 >= 2.6.2]) AC_SUBST(LIBGLADEMM_CFLAGS) AC_SUBST(LIBGLADEMM_LIBS) -PKG_CHECK_MODULES(GSTREAMER,[gstreamer-0.8 >= 0.8]) +PKG_CHECK_MODULES(GSTREAMER,[gstreamer-0.10 >= 0.10]) AC_SUBST(GSTREAMER_CFLAGS) AC_SUBST(GSTREAMER_LIBS) +PKG_CHECK_MODULES(GSTCONTROLLER,[gstreamer-controller-0.10 >= 0.10]) +AC_SUBST(GSTCONTROLLER_CFLAGS) +AC_SUBST(GSTCONTROLLER_LIBS) + AC_CHECK_CURL(7.12.3) AC_SUBST(CURL_CFLAGS) AC_SUBST(CURL_LIBS)