Improvement for the preloading system: Now it is possible to abort running Preloader instances. This helps greatly with the Live Mode, when items are reshuffled before playing.
Took a bit longer than expected, since it was more complicated to implement than I had originally thought. On the upside, I've learned more tricks about GStreamer, which is a good thing (tm). Fixes #2087
This commit is contained in:
parent
e169e5df5c
commit
12cfe650b9
|
@ -51,6 +51,13 @@
|
||||||
|
|
||||||
/* =================================================== local data structures */
|
/* =================================================== local data structures */
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ARG_0,
|
||||||
|
ARG_ABORT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ElementFactory information
|
* ElementFactory information
|
||||||
*/
|
*/
|
||||||
|
@ -89,6 +96,7 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE (
|
||||||
"rate = (int) [ 8000, 96000 ]"));
|
"rate = (int) [ 8000, 96000 ]"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ================================================ local constants & macros */
|
/* ================================================ local constants & macros */
|
||||||
|
|
||||||
#define NSEC_PER_SEC_FLOAT 1000000000.0
|
#define NSEC_PER_SEC_FLOAT 1000000000.0
|
||||||
|
@ -122,6 +130,10 @@ GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
|
||||||
|
|
||||||
/* =============================================== local function prototypes */
|
/* =============================================== local function prototypes */
|
||||||
|
|
||||||
|
static void
|
||||||
|
livesupport_minimal_audio_smil_set_property( GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the sink stream into memory, using a oneshotreader element.
|
* Read the sink stream into memory, using a oneshotreader element.
|
||||||
*
|
*
|
||||||
|
@ -272,6 +284,29 @@ livesupport_minimal_audio_smil_class_init(
|
||||||
|
|
||||||
/* ============================================================= module code */
|
/* ============================================================= module code */
|
||||||
|
|
||||||
|
static void
|
||||||
|
livesupport_minimal_audio_smil_set_property( GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec )
|
||||||
|
{
|
||||||
|
LivesupportMinimalAudioSmil* smil;
|
||||||
|
|
||||||
|
/* it's not null if we got it, but it might not be ours */
|
||||||
|
g_return_if_fail(LIVESUPPORT_IS_MINIMAL_AUDIO_SMIL(object));
|
||||||
|
|
||||||
|
smil = LIVESUPPORT_MINIMAL_AUDIO_SMIL(object);
|
||||||
|
|
||||||
|
switch ( prop_id )
|
||||||
|
{
|
||||||
|
case ARG_ABORT:
|
||||||
|
smil->myclass->abort = g_value_get_pointer (value);
|
||||||
|
printf("SETTING ABORT POINTER: %d\n", smil->myclass->abort);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, prop_id, pspec );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
* Read the sink stream into memory, using a oneshotreader element.
|
* Read the sink stream into memory, using a oneshotreader element.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
@ -351,7 +386,7 @@ handle_animate_element(LivesupportMinimalAudioSmil * smil,
|
||||||
|
|
||||||
/* handle the attributes */
|
/* handle the attributes */
|
||||||
for (attr = ((xmlElement*)animate)->attributes;
|
for (attr = ((xmlElement*)animate)->attributes;
|
||||||
attr;
|
attr && !(*smil->myclass->abort);
|
||||||
attr = (xmlAttribute*) attr->next) {
|
attr = (xmlAttribute*) attr->next) {
|
||||||
|
|
||||||
xmlNode * node;
|
xmlNode * node;
|
||||||
|
@ -509,7 +544,7 @@ handle_audio_element(LivesupportMinimalAudioSmil * smil,
|
||||||
|
|
||||||
/* handle the attributes */
|
/* handle the attributes */
|
||||||
for (attr = ((xmlElement*)audio)->attributes;
|
for (attr = ((xmlElement*)audio)->attributes;
|
||||||
attr;
|
attr && !(*smil->myclass->abort);
|
||||||
attr = (xmlAttribute*) attr->next) {
|
attr = (xmlAttribute*) attr->next) {
|
||||||
|
|
||||||
xmlNode * node;
|
xmlNode * node;
|
||||||
|
@ -584,7 +619,7 @@ handle_audio_element(LivesupportMinimalAudioSmil * smil,
|
||||||
|
|
||||||
/* now handle the possible animate elements inside this audio element */
|
/* now handle the possible animate elements inside this audio element */
|
||||||
element = pplay;
|
element = pplay;
|
||||||
for (ix = 0, node = audio->children; node; node = node->next, ++ix) {
|
for (ix = 0, node = audio->children; node && !(*smil->myclass->abort); node = node->next, ++ix) {
|
||||||
if (node->type == XML_ELEMENT_NODE) {
|
if (node->type == XML_ELEMENT_NODE) {
|
||||||
GstElement * elem = 0;
|
GstElement * elem = 0;
|
||||||
|
|
||||||
|
@ -658,7 +693,7 @@ handle_par_element(LivesupportMinimalAudioSmil * smil,
|
||||||
g_value_unset(&gvalue);
|
g_value_unset(&gvalue);
|
||||||
|
|
||||||
|
|
||||||
for (index = 0, node = par->children; node; node = node->next, ++index) {
|
for (index = 0, node = par->children; node && !(*smil->myclass->abort); node = node->next, ++index) {
|
||||||
if (node->type == XML_ELEMENT_NODE) {
|
if (node->type == XML_ELEMENT_NODE) {
|
||||||
GstElement * element = 0;
|
GstElement * element = 0;
|
||||||
|
|
||||||
|
@ -731,7 +766,7 @@ process_smil_file(LivesupportMinimalAudioSmil * smil)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (node = node->children; node; node = node->next) {
|
for (node = node->children; node && !(*smil->myclass->abort); node = node->next) {
|
||||||
if (node->type == XML_ELEMENT_NODE) {
|
if (node->type == XML_ELEMENT_NODE) {
|
||||||
GstElement * element = 0;
|
GstElement * element = 0;
|
||||||
|
|
||||||
|
@ -838,6 +873,10 @@ livesupport_minimal_audio_smil_dispose(GObject * object)
|
||||||
static void
|
static void
|
||||||
livesupport_minimal_audio_smil_init(LivesupportMinimalAudioSmil * smil)
|
livesupport_minimal_audio_smil_init(LivesupportMinimalAudioSmil * smil)
|
||||||
{
|
{
|
||||||
|
printf("INIT().\n");
|
||||||
|
|
||||||
|
smil->myclass = (LivesupportMinimalAudioSmilClass*) G_OBJECT_GET_CLASS(smil);
|
||||||
|
|
||||||
GValue gvalue = { 0 };
|
GValue gvalue = { 0 };
|
||||||
GstPad * oneshotReaderSink;
|
GstPad * oneshotReaderSink;
|
||||||
|
|
||||||
|
@ -913,6 +952,8 @@ static void
|
||||||
livesupport_minimal_audio_smil_class_init(
|
livesupport_minimal_audio_smil_class_init(
|
||||||
LivesupportMinimalAudioSmilClass * klass)
|
LivesupportMinimalAudioSmilClass * klass)
|
||||||
{
|
{
|
||||||
|
printf("CLASS_INIT().\n");
|
||||||
|
|
||||||
GObjectClass * gobject_class;
|
GObjectClass * gobject_class;
|
||||||
GstElementClass * gstelement_class;
|
GstElementClass * gstelement_class;
|
||||||
|
|
||||||
|
@ -920,9 +961,13 @@ livesupport_minimal_audio_smil_class_init(
|
||||||
gstelement_class = (GstElementClass *) klass;
|
gstelement_class = (GstElementClass *) klass;
|
||||||
parent_class = (GstBinClass*)g_type_class_ref(GST_TYPE_BIN);
|
parent_class = (GstBinClass*)g_type_class_ref(GST_TYPE_BIN);
|
||||||
|
|
||||||
|
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ABORT, g_param_spec_pointer
|
||||||
|
("abort", "abort", "abort", (GParamFlags)G_PARAM_WRITABLE));
|
||||||
|
|
||||||
gobject_class->dispose = livesupport_minimal_audio_smil_dispose;
|
gobject_class->dispose = livesupport_minimal_audio_smil_dispose;
|
||||||
gstelement_class->change_state =
|
gobject_class->set_property = livesupport_minimal_audio_smil_set_property;
|
||||||
livesupport_minimal_audio_smil_change_state;
|
gstelement_class->change_state = livesupport_minimal_audio_smil_change_state;
|
||||||
|
|
||||||
|
|
||||||
/* check for the libxml version */
|
/* check for the libxml version */
|
||||||
LIBXML_TEST_VERSION
|
LIBXML_TEST_VERSION
|
||||||
|
|
|
@ -80,6 +80,7 @@ typedef struct _LivesupportMinimalAudioSmilClass
|
||||||
* The MinimalAudioSmil object structure.
|
* The MinimalAudioSmil object structure.
|
||||||
*/
|
*/
|
||||||
struct _LivesupportMinimalAudioSmil {
|
struct _LivesupportMinimalAudioSmil {
|
||||||
|
LivesupportMinimalAudioSmilClass* myclass;
|
||||||
GstBin parent;
|
GstBin parent;
|
||||||
|
|
||||||
GstPad * sinkpad;
|
GstPad * sinkpad;
|
||||||
|
@ -99,6 +100,8 @@ struct _LivesupportMinimalAudioSmil {
|
||||||
*/
|
*/
|
||||||
struct _LivesupportMinimalAudioSmilClass {
|
struct _LivesupportMinimalAudioSmilClass {
|
||||||
GstBinClass parent_class;
|
GstBinClass parent_class;
|
||||||
|
|
||||||
|
gboolean* abort;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -644,6 +644,8 @@ Preloader::Preloader(GstreamerPlayer* player, const std::string url) throw()
|
||||||
, m_fileUrl(url)
|
, m_fileUrl(url)
|
||||||
{
|
{
|
||||||
DEBUG_FUNC_INFO
|
DEBUG_FUNC_INFO
|
||||||
|
|
||||||
|
player->m_stopPreloader = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -688,6 +690,7 @@ void Preloader::run() throw()
|
||||||
gst_element_set(p->m_preloadFilesrc, "location", filePath.c_str(), NULL);
|
gst_element_set(p->m_preloadFilesrc, "location", filePath.c_str(), NULL);
|
||||||
|
|
||||||
p->m_preloadDecoder = gst_element_factory_make("minimalaudiosmil", 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* pipe = gst_pipeline_new("pipe");
|
||||||
GstElement* fakesink = gst_element_factory_make("fakesink", "fakesink");
|
GstElement* fakesink = gst_element_factory_make("fakesink", "fakesink");
|
||||||
|
@ -697,13 +700,20 @@ void Preloader::run() throw()
|
||||||
gst_element_set_state(pipe, GST_STATE_PLAYING);
|
gst_element_set_state(pipe, GST_STATE_PLAYING);
|
||||||
|
|
||||||
gint64 position = 0LL;
|
gint64 position = 0LL;
|
||||||
while (position == 0LL && gst_bin_iterate(GST_BIN(pipe))) {
|
while (position == 0LL && !p->m_stopPreloader && gst_bin_iterate(GST_BIN(pipe))) {
|
||||||
GstFormat format = GST_FORMAT_DEFAULT;
|
GstFormat format = GST_FORMAT_DEFAULT;
|
||||||
gst_element_query(fakesink, GST_QUERY_POSITION, &format, &position);
|
gst_element_query(fakesink, GST_QUERY_POSITION, &format, &position);
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_element_set_state(pipe, GST_STATE_PAUSED);
|
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_preloadFilesrc));
|
||||||
g_object_ref(G_OBJECT(p->m_preloadDecoder));
|
g_object_ref(G_OBJECT(p->m_preloadDecoder));
|
||||||
gst_bin_remove_many(GST_BIN(pipe), p->m_preloadFilesrc, p->m_preloadDecoder, NULL);
|
gst_bin_remove_many(GST_BIN(pipe), p->m_preloadFilesrc, p->m_preloadDecoder, NULL);
|
||||||
|
@ -720,8 +730,11 @@ void Preloader::signal(int) throw()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
// TODO This should be implemented by adding a "abort" property to the minimalaudiosmil element.
|
|
||||||
void Preloader::stop() throw()
|
void Preloader::stop() throw()
|
||||||
{}
|
{
|
||||||
|
DEBUG_FUNC_INFO
|
||||||
|
|
||||||
|
m_player->m_stopPreloader = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -170,6 +170,12 @@ class GstreamerPlayer : virtual public Configurable,
|
||||||
*/
|
*/
|
||||||
Ptr<Thread>::Ref m_preloadThread;
|
Ptr<Thread>::Ref m_preloadThread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag that indicates that the preloader should abort.
|
||||||
|
*/
|
||||||
|
|
||||||
|
gboolean m_stopPreloader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type for the vector of listeners.
|
* The type for the vector of listeners.
|
||||||
* Just a shorthand notation, to make reference to the type
|
* Just a shorthand notation, to make reference to the type
|
||||||
|
|
Loading…
Reference in New Issue