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:
mark 2006-12-14 11:59:00 +00:00
parent e169e5df5c
commit 12cfe650b9
4 changed files with 77 additions and 10 deletions

View File

@ -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

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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