Major performance improvements for the GstreamerPlayer: Lag for opening/starting files has been reduced by a multitude, for all filetypes except SMIL. This has been achieved by using GStreamer's decodebin autoplugger, instead of our (very slow) custom autoplugger. For SMIL we currently still need to use the old autoplugger, so I have implemented two different codepaths.
For some hard numbers, this is an excerpt of a session with the new code: [GstreamerPlayer] BEGIN: virtual void LiveSupport::PlaylistExecutor::GstreamerPlayer::open(std::string) [GstreamerPlayer] Opening URL: file:var/test.mp3 [GstreamerPlayer] END__: virtual void LiveSupport::PlaylistExecutor::GstreamerPlayer::open(std::string) - Took 0.099144s [GstreamerPlayer] BEGIN: virtual void LiveSupport::PlaylistExecutor::GstreamerPlayer::start() [GstreamerPlayer] END__: virtual void LiveSupport::PlaylistExecutor::GstreamerPlayer::start() - Took 0.000105s Total execution time ~0.1s. Almost instant. Fixes #1904
This commit is contained in:
parent
42891b2059
commit
8ea9d9d21a
|
@ -239,6 +239,31 @@ GstreamerPlayer :: eosEventHandler(GstElement * element,
|
|||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* 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->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->audiosink) == NULL)
|
||||
gst_bin_add(GST_BIN(player->pipeline), player->audiosink);
|
||||
|
||||
gst_bin_sync_children_state(GST_BIN(player->pipeline));
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Specify which file to play
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
@ -270,31 +295,39 @@ GstreamerPlayer :: open(const std::string fileUrl)
|
|||
throw std::invalid_argument("badly formed URL or unsupported protocol");
|
||||
}
|
||||
|
||||
const bool isSmil = fileUrl.substr(fileUrl.size()-5, fileUrl.size()) == ".smil" ? true : false;
|
||||
|
||||
filesrc = gst_element_factory_make("filesrc", "file-source");
|
||||
gst_element_set(filesrc, "location", filePath.c_str(), NULL);
|
||||
|
||||
decoder = ls_gst_autoplug_plug_source(filesrc, "decoder", sinkCaps);
|
||||
|
||||
if (!decoder) {
|
||||
throw std::invalid_argument(std::string("can't open URL ") + fileUrl);
|
||||
}
|
||||
|
||||
// converts between different audio formats (e.g. bitrate)
|
||||
audioconvert = gst_element_factory_make("audioconvert", NULL);
|
||||
|
||||
// scale the sampling rate, if necessary
|
||||
audioscale = gst_element_factory_make("audioscale", NULL);
|
||||
|
||||
gst_bin_add_many(GST_BIN(pipeline), filesrc,
|
||||
decoder,
|
||||
audioconvert,
|
||||
audioscale,
|
||||
NULL);
|
||||
gst_element_link_many(decoder,
|
||||
audioconvert,
|
||||
audioscale,
|
||||
audiosink,
|
||||
NULL);
|
||||
// Using our custom autoplugger for SMIL
|
||||
if (isSmil) {
|
||||
debug() << "SMIL file detected. Using custom autoplugger." << endl;
|
||||
decoder = ls_gst_autoplug_plug_source(filesrc, "decoder", sinkCaps);
|
||||
gst_element_link(decoder,audioconvert);
|
||||
if (gst_element_get_parent(audiosink) == NULL)
|
||||
gst_bin_add(GST_BIN(pipeline), audiosink);
|
||||
}
|
||||
// Using GStreamer's decodebin autoplugger for everything else (it's much faster)
|
||||
else {
|
||||
decoder = gst_element_factory_make("decodebin", NULL);
|
||||
gst_element_link(filesrc,decoder);
|
||||
g_signal_connect(decoder, "new-decoded-pad", G_CALLBACK(newpadEventHandler), this);
|
||||
}
|
||||
|
||||
if (!decoder) {
|
||||
throw std::invalid_argument(std::string("can't open URL ") + fileUrl);
|
||||
}
|
||||
|
||||
gst_bin_add_many(GST_BIN(pipeline), filesrc, decoder, audioconvert, audioscale, NULL);
|
||||
|
||||
gst_element_link_many(audioconvert, audioscale, audiosink, NULL);
|
||||
|
||||
// connect the eos signal handler
|
||||
g_signal_connect(decoder, "eos", G_CALLBACK(eosEventHandler), this);
|
||||
|
@ -305,7 +338,6 @@ GstreamerPlayer :: open(const std::string fileUrl)
|
|||
// the audio device (as it might be blocked by an other process
|
||||
throw std::runtime_error("can't open audio device " + audioDevice);
|
||||
}
|
||||
gst_bin_sync_children_state(GST_BIN(pipeline));
|
||||
}
|
||||
|
||||
|
||||
|
@ -472,6 +504,10 @@ GstreamerPlayer :: close(void) throw (std::logic_error)
|
|||
if (filesrc) {
|
||||
gst_bin_remove(GST_BIN(pipeline), filesrc);
|
||||
}
|
||||
if (audiosink && gst_element_get_parent(audiosink) == GST_OBJECT(pipeline)) {
|
||||
gst_object_ref(GST_OBJECT(audiosink));
|
||||
gst_bin_remove(GST_BIN(pipeline), audiosink);
|
||||
}
|
||||
|
||||
filesrc = 0;
|
||||
decoder = 0;
|
||||
|
@ -518,7 +554,10 @@ GstreamerPlayer :: setAudioDevice(const std::string &deviceName)
|
|||
if (audioscale) {
|
||||
gst_element_unlink(audioscale, audiosink);
|
||||
}
|
||||
gst_bin_remove(GST_BIN(pipeline), audiosink);
|
||||
if ( gst_element_get_parent( audiosink ) == NULL )
|
||||
gst_object_unref(GST_OBJECT(audiosink));
|
||||
else
|
||||
gst_bin_remove(GST_BIN(pipeline), audiosink);
|
||||
audiosink = 0;
|
||||
}
|
||||
|
||||
|
@ -536,8 +575,6 @@ GstreamerPlayer :: setAudioDevice(const std::string &deviceName)
|
|||
if (audioscale) {
|
||||
gst_element_link_filtered(audioscale, audiosink, sinkCaps);
|
||||
}
|
||||
gst_bin_add(GST_BIN(pipeline), audiosink);
|
||||
gst_bin_sync_children_state(GST_BIN(pipeline));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -188,6 +188,16 @@ class GstreamerPlayer : virtual public Configurable,
|
|||
eosEventHandler(GstElement * element,
|
||||
gpointer self)
|
||||
throw ();
|
||||
/**
|
||||
* An 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.
|
||||
|
@ -294,6 +304,7 @@ class GstreamerPlayer : virtual public Configurable,
|
|||
setAudioDevice(const std::string &deviceName)
|
||||
throw ();
|
||||
|
||||
|
||||
/**
|
||||
* Specify which audio resource to play.
|
||||
* The file may be a playlist, referencing other files, which
|
||||
|
|
Loading…
Reference in New Issue