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 */
|
||||
|
||||
|
||||
enum {
|
||||
ARG_0,
|
||||
ARG_ABORT
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ElementFactory information
|
||||
*/
|
||||
|
@ -89,6 +96,7 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE (
|
|||
"rate = (int) [ 8000, 96000 ]"));
|
||||
|
||||
|
||||
|
||||
/* ================================================ local constants & macros */
|
||||
|
||||
#define NSEC_PER_SEC_FLOAT 1000000000.0
|
||||
|
@ -122,6 +130,10 @@ GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
|
|||
|
||||
/* =============================================== 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.
|
||||
*
|
||||
|
@ -272,6 +284,29 @@ livesupport_minimal_audio_smil_class_init(
|
|||
|
||||
/* ============================================================= 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.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
@ -351,7 +386,7 @@ handle_animate_element(LivesupportMinimalAudioSmil * smil,
|
|||
|
||||
/* handle the attributes */
|
||||
for (attr = ((xmlElement*)animate)->attributes;
|
||||
attr;
|
||||
attr && !(*smil->myclass->abort);
|
||||
attr = (xmlAttribute*) attr->next) {
|
||||
|
||||
xmlNode * node;
|
||||
|
@ -509,7 +544,7 @@ handle_audio_element(LivesupportMinimalAudioSmil * smil,
|
|||
|
||||
/* handle the attributes */
|
||||
for (attr = ((xmlElement*)audio)->attributes;
|
||||
attr;
|
||||
attr && !(*smil->myclass->abort);
|
||||
attr = (xmlAttribute*) attr->next) {
|
||||
|
||||
xmlNode * node;
|
||||
|
@ -584,7 +619,7 @@ handle_audio_element(LivesupportMinimalAudioSmil * smil,
|
|||
|
||||
/* now handle the possible animate elements inside this audio element */
|
||||
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) {
|
||||
GstElement * elem = 0;
|
||||
|
||||
|
@ -658,7 +693,7 @@ handle_par_element(LivesupportMinimalAudioSmil * smil,
|
|||
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) {
|
||||
GstElement * element = 0;
|
||||
|
||||
|
@ -731,7 +766,7 @@ process_smil_file(LivesupportMinimalAudioSmil * smil)
|
|||
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) {
|
||||
GstElement * element = 0;
|
||||
|
||||
|
@ -838,6 +873,10 @@ livesupport_minimal_audio_smil_dispose(GObject * object)
|
|||
static void
|
||||
livesupport_minimal_audio_smil_init(LivesupportMinimalAudioSmil * smil)
|
||||
{
|
||||
printf("INIT().\n");
|
||||
|
||||
smil->myclass = (LivesupportMinimalAudioSmilClass*) G_OBJECT_GET_CLASS(smil);
|
||||
|
||||
GValue gvalue = { 0 };
|
||||
GstPad * oneshotReaderSink;
|
||||
|
||||
|
@ -913,6 +952,8 @@ static void
|
|||
livesupport_minimal_audio_smil_class_init(
|
||||
LivesupportMinimalAudioSmilClass * klass)
|
||||
{
|
||||
printf("CLASS_INIT().\n");
|
||||
|
||||
GObjectClass * gobject_class;
|
||||
GstElementClass * gstelement_class;
|
||||
|
||||
|
@ -920,9 +961,13 @@ livesupport_minimal_audio_smil_class_init(
|
|||
gstelement_class = (GstElementClass *) klass;
|
||||
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;
|
||||
gstelement_class->change_state =
|
||||
livesupport_minimal_audio_smil_change_state;
|
||||
gobject_class->set_property = livesupport_minimal_audio_smil_set_property;
|
||||
gstelement_class->change_state = livesupport_minimal_audio_smil_change_state;
|
||||
|
||||
|
||||
/* check for the libxml version */
|
||||
LIBXML_TEST_VERSION
|
||||
|
|
|
@ -80,6 +80,7 @@ typedef struct _LivesupportMinimalAudioSmilClass
|
|||
* The MinimalAudioSmil object structure.
|
||||
*/
|
||||
struct _LivesupportMinimalAudioSmil {
|
||||
LivesupportMinimalAudioSmilClass* myclass;
|
||||
GstBin parent;
|
||||
|
||||
GstPad * sinkpad;
|
||||
|
@ -99,6 +100,8 @@ struct _LivesupportMinimalAudioSmil {
|
|||
*/
|
||||
struct _LivesupportMinimalAudioSmilClass {
|
||||
GstBinClass parent_class;
|
||||
|
||||
gboolean* abort;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -644,6 +644,8 @@ Preloader::Preloader(GstreamerPlayer* player, const std::string url) throw()
|
|||
, m_fileUrl(url)
|
||||
{
|
||||
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);
|
||||
|
||||
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");
|
||||
|
@ -697,13 +700,20 @@ void Preloader::run() throw()
|
|||
gst_element_set_state(pipe, GST_STATE_PLAYING);
|
||||
|
||||
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;
|
||||
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);
|
||||
|
@ -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()
|
||||
{}
|
||||
{
|
||||
DEBUG_FUNC_INFO
|
||||
|
||||
m_player->m_stopPreloader = true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -170,6 +170,12 @@ class GstreamerPlayer : virtual public Configurable,
|
|||
*/
|
||||
Ptr<Thread>::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
|
||||
|
|
Loading…
Reference in New Issue