mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 03:01:03 +00:00
gst-indent run on core
Original commit message from CVS: gst-indent run on core
This commit is contained in:
parent
b8edc59edb
commit
a967370df5
446 changed files with 24365 additions and 23891 deletions
|
@ -1,3 +1,7 @@
|
|||
2004-03-13 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* *.c, *.h: commit of gst-indent run on core
|
||||
|
||||
2004-03-13 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* tools/gst-indent:
|
||||
|
|
|
@ -38,11 +38,12 @@ static BonoboGenericFactory *factory = NULL;
|
|||
/*
|
||||
* BonoboControl data
|
||||
*/
|
||||
typedef struct {
|
||||
BonoboControl *bonobo_object;
|
||||
BonoboUIComponent *uic;
|
||||
typedef struct
|
||||
{
|
||||
BonoboControl *bonobo_object;
|
||||
BonoboUIComponent *uic;
|
||||
|
||||
GstPlay *play;
|
||||
GstPlay *play;
|
||||
} control_data_t;
|
||||
|
||||
/*
|
||||
|
@ -50,20 +51,20 @@ typedef struct {
|
|||
* encounters a fatal CORBA exception.
|
||||
*/
|
||||
static void
|
||||
control_system_exception_cb (BonoboControl *control, CORBA_Object corba_object,
|
||||
CORBA_Environment *ev, gpointer data)
|
||||
control_system_exception_cb (BonoboControl * control, CORBA_Object corba_object,
|
||||
CORBA_Environment * ev, gpointer data)
|
||||
{
|
||||
bonobo_object_unref (BONOBO_OBJECT (control));
|
||||
}
|
||||
|
||||
static void
|
||||
control_update (control_data_t *control_data)
|
||||
control_update (control_data_t * control_data)
|
||||
{
|
||||
gtk_widget_queue_draw (GTK_WIDGET (control_data->play));
|
||||
}
|
||||
|
||||
static void
|
||||
verb_Play_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
||||
verb_Play_cb (BonoboUIComponent * uic, gpointer user_data, const char *cname)
|
||||
{
|
||||
control_data_t *control_data = (control_data_t *) user_data;
|
||||
|
||||
|
@ -72,7 +73,7 @@ verb_Play_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
|||
}
|
||||
|
||||
static void
|
||||
verb_Pause_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
||||
verb_Pause_cb (BonoboUIComponent * uic, gpointer user_data, const char *cname)
|
||||
{
|
||||
control_data_t *control_data = (control_data_t *) user_data;
|
||||
|
||||
|
@ -81,7 +82,7 @@ verb_Pause_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
|||
}
|
||||
|
||||
static void
|
||||
verb_Stop_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
||||
verb_Stop_cb (BonoboUIComponent * uic, gpointer user_data, const char *cname)
|
||||
{
|
||||
control_data_t *control_data = (control_data_t *) user_data;
|
||||
|
||||
|
@ -89,51 +90,53 @@ verb_Stop_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
|||
control_update (control_data);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
control_data_t *control_data;
|
||||
GtkFileSelection *selector;
|
||||
} file_select_struct;
|
||||
|
||||
static void
|
||||
filename_selected (GtkButton *ok, gpointer user_data)
|
||||
|
||||
static void
|
||||
filename_selected (GtkButton * ok, gpointer user_data)
|
||||
{
|
||||
file_select_struct *select = (file_select_struct *) user_data;
|
||||
|
||||
gchar *selected_filename;
|
||||
|
||||
selected_filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION(select->selector));
|
||||
|
||||
selected_filename =
|
||||
gtk_file_selection_get_filename (GTK_FILE_SELECTION (select->selector));
|
||||
|
||||
gst_play_set_uri (select->control_data->play, selected_filename);
|
||||
|
||||
gst_play_play (select->control_data->play);
|
||||
control_update (select->control_data);
|
||||
|
||||
g_free(select);
|
||||
g_free (select);
|
||||
}
|
||||
|
||||
static void
|
||||
verb_Open_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
||||
verb_Open_cb (BonoboUIComponent * uic, gpointer user_data, const char *cname)
|
||||
{
|
||||
control_data_t *control_data = (control_data_t *) user_data;
|
||||
file_select_struct *data = g_new0(file_select_struct, 1);
|
||||
file_select_struct *data = g_new0 (file_select_struct, 1);
|
||||
GtkWidget *file_selector;
|
||||
|
||||
file_selector = gtk_file_selection_new("Select a media file");
|
||||
|
||||
file_selector = gtk_file_selection_new ("Select a media file");
|
||||
|
||||
data->selector = GTK_FILE_SELECTION (file_selector);
|
||||
data->control_data = control_data;
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(file_selector)->ok_button),
|
||||
"clicked", GTK_SIGNAL_FUNC (filename_selected), data);
|
||||
|
||||
gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(file_selector)->ok_button),
|
||||
"clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
|
||||
(gpointer) file_selector);
|
||||
|
||||
gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(file_selector)->cancel_button),
|
||||
"clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
|
||||
(gpointer) file_selector);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_selector)->
|
||||
ok_button), "clicked", GTK_SIGNAL_FUNC (filename_selected), data);
|
||||
|
||||
gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (file_selector)->
|
||||
ok_button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
|
||||
(gpointer) file_selector);
|
||||
|
||||
gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (file_selector)->
|
||||
cancel_button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
|
||||
(gpointer) file_selector);
|
||||
|
||||
gtk_widget_show (file_selector);
|
||||
}
|
||||
|
||||
|
@ -142,37 +145,36 @@ verb_Open_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
|||
* in with our container's menus.
|
||||
*/
|
||||
static void
|
||||
control_create_menus (control_data_t *control_data)
|
||||
control_create_menus (control_data_t * control_data)
|
||||
{
|
||||
BonoboControl *control = control_data->bonobo_object;
|
||||
Bonobo_UIContainer remote_uic;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
static char ui [] =
|
||||
"<Root>"
|
||||
" <commands>"
|
||||
" <cmd name=\"Play\" _label=\"Play\" _tip=\"Play\"/>"
|
||||
" <cmd name=\"Pause\" _label=\"Pause\" _tip=\"Pause\"/>"
|
||||
" <cmd name=\"Stop\" _label=\"Stop\" _tip=\"Stop\"/>"
|
||||
" <cmd name=\"Open\" _label=\"Open Media\" _tip=\"Open a media stream\"/>"
|
||||
" </commands>"
|
||||
" <menu>"
|
||||
" <submenu name=\"Player\" _label=\"_Player\">"
|
||||
" <menuitem name=\"Open\" pixtype=\"stock\" pixname=\"Open\" verb=\"\"/>"
|
||||
" <separator/>"
|
||||
" <menuitem name=\"Play\" verb=\"\"/>"
|
||||
" <menuitem name=\"Pause\" verb=\"\"/>"
|
||||
" <menuitem name=\"Stop\" verb=\"\"/>"
|
||||
" </submenu>"
|
||||
" </menu>"
|
||||
" <dockitem name=\"GstMediaPlay\">"
|
||||
" <toolitem name=\"Play\" type=\"toggle\" verb=\"\"/>"
|
||||
" <toolitem name=\"Pause\" type=\"toggle\" verb=\"\"/>"
|
||||
" <toolitem name=\"Stop\" type=\"toggle\" verb=\"\"/>"
|
||||
" </dockitem>"
|
||||
"</Root>";
|
||||
static char ui[] =
|
||||
"<Root>"
|
||||
" <commands>"
|
||||
" <cmd name=\"Play\" _label=\"Play\" _tip=\"Play\"/>"
|
||||
" <cmd name=\"Pause\" _label=\"Pause\" _tip=\"Pause\"/>"
|
||||
" <cmd name=\"Stop\" _label=\"Stop\" _tip=\"Stop\"/>"
|
||||
" <cmd name=\"Open\" _label=\"Open Media\" _tip=\"Open a media stream\"/>"
|
||||
" </commands>"
|
||||
" <menu>"
|
||||
" <submenu name=\"Player\" _label=\"_Player\">"
|
||||
" <menuitem name=\"Open\" pixtype=\"stock\" pixname=\"Open\" verb=\"\"/>"
|
||||
" <separator/>"
|
||||
" <menuitem name=\"Play\" verb=\"\"/>"
|
||||
" <menuitem name=\"Pause\" verb=\"\"/>"
|
||||
" <menuitem name=\"Stop\" verb=\"\"/>"
|
||||
" </submenu>"
|
||||
" </menu>"
|
||||
" <dockitem name=\"GstMediaPlay\">"
|
||||
" <toolitem name=\"Play\" type=\"toggle\" verb=\"\"/>"
|
||||
" <toolitem name=\"Pause\" type=\"toggle\" verb=\"\"/>"
|
||||
" <toolitem name=\"Stop\" type=\"toggle\" verb=\"\"/>"
|
||||
" </dockitem>" "</Root>";
|
||||
|
||||
g_print("create menu\n");
|
||||
g_print ("create menu\n");
|
||||
/*
|
||||
* Get our container's UIContainer server.
|
||||
*/
|
||||
|
@ -206,8 +208,8 @@ control_create_menus (control_data_t *control_data)
|
|||
node = bonobo_ui_node_from_string (ui);
|
||||
bonobo_ui_util_translate_ui (node);
|
||||
bonobo_ui_util_fixup_help (control_data->uic, node,
|
||||
DATADIR, "gstmediaplay");
|
||||
|
||||
DATADIR, "gstmediaplay");
|
||||
|
||||
bonobo_ui_component_set_tree (control_data->uic, "/", node, NULL);
|
||||
|
||||
bonobo_ui_node_free (node);
|
||||
|
@ -225,11 +227,11 @@ control_create_menus (control_data_t *control_data)
|
|||
bonobo_ui_util_set_pixbuf (control_data->uic, "/commands/Stop", pixbuf);
|
||||
gdk_pixbuf_unref (pixbuf);
|
||||
|
||||
g_print("create menu done\n");
|
||||
g_print ("create menu done\n");
|
||||
}
|
||||
|
||||
static void
|
||||
control_remove_menus (control_data_t *control_data)
|
||||
control_remove_menus (control_data_t * control_data)
|
||||
{
|
||||
bonobo_ui_component_unset_container (control_data->uic);
|
||||
}
|
||||
|
@ -238,18 +240,18 @@ control_remove_menus (control_data_t *control_data)
|
|||
* Clean up our supplementary BonoboControl data sturctures.
|
||||
*/
|
||||
static void
|
||||
control_destroy_cb (BonoboControl *control, gpointer data)
|
||||
control_destroy_cb (BonoboControl * control, gpointer data)
|
||||
{
|
||||
control_data_t *control_data = (control_data_t *) data;
|
||||
|
||||
control_data->play = NULL;
|
||||
|
||||
g_free (control_data);
|
||||
|
||||
g_free (control_data);
|
||||
|
||||
running_objects--;
|
||||
if (running_objects > 0)
|
||||
return;
|
||||
|
||||
|
||||
/*
|
||||
* When the last object has gone, unref the factory & quit.
|
||||
*/
|
||||
|
@ -258,7 +260,7 @@ control_destroy_cb (BonoboControl *control, gpointer data)
|
|||
}
|
||||
|
||||
static void
|
||||
control_activate_cb (BonoboControl *control, gboolean activate, gpointer data)
|
||||
control_activate_cb (BonoboControl * control, gboolean activate, gpointer data)
|
||||
{
|
||||
control_data_t *control_data = (control_data_t *) data;
|
||||
|
||||
|
@ -284,17 +286,17 @@ control_activate_cb (BonoboControl *control, gboolean activate, gpointer data)
|
|||
}
|
||||
|
||||
static void
|
||||
control_set_frame_cb (BonoboControl *control, gpointer data)
|
||||
control_set_frame_cb (BonoboControl * control, gpointer data)
|
||||
{
|
||||
control_create_menus ((control_data_t *) data);
|
||||
}
|
||||
|
||||
static BonoboObject *
|
||||
bonobo_gstmediaplay_factory (BonoboGenericFactory *this, void *data)
|
||||
bonobo_gstmediaplay_factory (BonoboGenericFactory * this, void *data)
|
||||
{
|
||||
BonoboControl *bonobo_object;
|
||||
control_data_t *control_data;
|
||||
GtkWidget *vbox;
|
||||
BonoboControl *bonobo_object;
|
||||
control_data_t *control_data;
|
||||
GtkWidget *vbox;
|
||||
|
||||
gst_init (NULL, NULL);
|
||||
/*
|
||||
|
@ -311,7 +313,7 @@ bonobo_gstmediaplay_factory (BonoboGenericFactory *this, void *data)
|
|||
vbox = gtk_vbox_new (TRUE, 0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (control_data->play),
|
||||
TRUE, TRUE, 0);
|
||||
TRUE, TRUE, 0);
|
||||
gtk_widget_show_all (vbox);
|
||||
|
||||
gst_play_set_uri (control_data->play, "/opt/data/armageddon1.mpg");
|
||||
|
@ -337,39 +339,39 @@ bonobo_gstmediaplay_factory (BonoboGenericFactory *this, void *data)
|
|||
* the "activate" signal.
|
||||
*/
|
||||
gtk_signal_connect (GTK_OBJECT (bonobo_object), "activate",
|
||||
GTK_SIGNAL_FUNC (control_activate_cb), control_data);
|
||||
GTK_SIGNAL_FUNC (control_activate_cb), control_data);
|
||||
gtk_signal_connect (GTK_OBJECT (bonobo_object), "set_frame",
|
||||
GTK_SIGNAL_FUNC (control_set_frame_cb), control_data);
|
||||
GTK_SIGNAL_FUNC (control_set_frame_cb), control_data);
|
||||
|
||||
/*
|
||||
* The "system_exception" signal is raised when the BonoboControl
|
||||
* encounters a fatal CORBA exception.
|
||||
*/
|
||||
gtk_signal_connect (GTK_OBJECT (bonobo_object), "system_exception",
|
||||
GTK_SIGNAL_FUNC (control_system_exception_cb), control_data);
|
||||
GTK_SIGNAL_FUNC (control_system_exception_cb), control_data);
|
||||
|
||||
/*
|
||||
* We'll need to be able to cleanup when this control gets
|
||||
* destroyed.
|
||||
*/
|
||||
gtk_signal_connect (GTK_OBJECT (bonobo_object), "destroy",
|
||||
GTK_SIGNAL_FUNC (control_destroy_cb), control_data);
|
||||
GTK_SIGNAL_FUNC (control_destroy_cb), control_data);
|
||||
|
||||
bonobo_ui_component_add_verb (control_data->uic, "Play",
|
||||
verb_Play_cb, control_data);
|
||||
verb_Play_cb, control_data);
|
||||
bonobo_ui_component_add_verb (control_data->uic, "Pause",
|
||||
verb_Pause_cb, control_data);
|
||||
verb_Pause_cb, control_data);
|
||||
bonobo_ui_component_add_verb (control_data->uic, "Stop",
|
||||
verb_Stop_cb, control_data);
|
||||
verb_Stop_cb, control_data);
|
||||
|
||||
bonobo_ui_component_add_verb (control_data->uic, "Open",
|
||||
verb_Open_cb, control_data);
|
||||
verb_Open_cb, control_data);
|
||||
|
||||
/*
|
||||
* Count the new running object
|
||||
*/
|
||||
running_objects++;
|
||||
g_print("running objects: %d\n", running_objects);
|
||||
g_print ("running objects: %d\n", running_objects);
|
||||
|
||||
return BONOBO_OBJECT (bonobo_object);
|
||||
}
|
||||
|
@ -377,9 +379,10 @@ bonobo_gstmediaplay_factory (BonoboGenericFactory *this, void *data)
|
|||
static void
|
||||
init_gstmediaplay_factory (void)
|
||||
{
|
||||
factory = bonobo_generic_factory_new (
|
||||
"OAFIID:bonobo_gstmediaplay_factory:420f20ca-55d7-4a33-b327-0b246136db18",
|
||||
bonobo_gstmediaplay_factory, NULL);
|
||||
factory =
|
||||
bonobo_generic_factory_new
|
||||
("OAFIID:bonobo_gstmediaplay_factory:420f20ca-55d7-4a33-b327-0b246136db18",
|
||||
bonobo_gstmediaplay_factory, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -393,9 +396,8 @@ init_server_factory (int argc, char **argv)
|
|||
|
||||
CORBA_exception_init (&ev);
|
||||
|
||||
gnome_init_with_popt_table("bonobo-gstmediaplay", VERSION,
|
||||
argc, argv,
|
||||
oaf_popt_options, 0, NULL);
|
||||
gnome_init_with_popt_table ("bonobo-gstmediaplay", VERSION,
|
||||
argc, argv, oaf_popt_options, 0, NULL);
|
||||
orb = oaf_init (argc, argv);
|
||||
|
||||
if (bonobo_init (orb, NULL, NULL) == FALSE)
|
||||
|
@ -403,7 +405,7 @@ init_server_factory (int argc, char **argv)
|
|||
|
||||
CORBA_exception_free (&ev);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
|
|
|
@ -27,48 +27,48 @@
|
|||
#include <gst/gst.h>
|
||||
#include <config.h>
|
||||
|
||||
static BonoboObject* gstreamer_factory (BonoboGenericFactory *factory,
|
||||
gpointer user_data)
|
||||
static BonoboObject *
|
||||
gstreamer_factory (BonoboGenericFactory * factory, gpointer user_data)
|
||||
{
|
||||
return BONOBO_OBJECT (bonobo_media_gstreamer_new ());
|
||||
return BONOBO_OBJECT (bonobo_media_gstreamer_new ());
|
||||
}
|
||||
|
||||
static void init_bonobo (int argc, char **argv)
|
||||
static void
|
||||
init_bonobo (int argc, char **argv)
|
||||
{
|
||||
CORBA_ORB orb;
|
||||
CORBA_ORB orb;
|
||||
|
||||
gnome_init_with_popt_table ("bonobo-media-gstreamer", VERSION,
|
||||
argc, argv,
|
||||
oaf_popt_options, 0, NULL);
|
||||
gnome_init_with_popt_table ("bonobo-media-gstreamer", VERSION,
|
||||
argc, argv, oaf_popt_options, 0, NULL);
|
||||
|
||||
orb = oaf_init (argc, argv);
|
||||
orb = oaf_init (argc, argv);
|
||||
|
||||
if (bonobo_init (orb, NULL, NULL) == FALSE)
|
||||
g_error ("Could not initialize Bonobo");
|
||||
if (bonobo_init (orb, NULL, NULL) == FALSE)
|
||||
g_error ("Could not initialize Bonobo");
|
||||
}
|
||||
|
||||
static void last_unref_cb (BonoboObject *bonobo_object,
|
||||
BonoboGenericFactory *factory)
|
||||
static void
|
||||
last_unref_cb (BonoboObject * bonobo_object, BonoboGenericFactory * factory)
|
||||
{
|
||||
bonobo_object_unref (BONOBO_OBJECT (factory));
|
||||
gtk_main_quit ();
|
||||
bonobo_object_unref (BONOBO_OBJECT (factory));
|
||||
gtk_main_quit ();
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
BonoboGenericFactory *factory;
|
||||
BonoboGenericFactory *factory;
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
init_bonobo (argc, argv);
|
||||
gst_init (&argc, &argv);
|
||||
init_bonobo (argc, argv);
|
||||
|
||||
factory = bonobo_generic_factory_new (
|
||||
"OAFIID:Bonobo_Media_GStreamer_Factory",
|
||||
gstreamer_factory, NULL);
|
||||
factory = bonobo_generic_factory_new ("OAFIID:Bonobo_Media_GStreamer_Factory",
|
||||
gstreamer_factory, NULL);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (bonobo_context_running_get ()), "last_unref",
|
||||
GTK_SIGNAL_FUNC (last_unref_cb), factory);
|
||||
gtk_signal_connect (GTK_OBJECT (bonobo_context_running_get ()), "last_unref",
|
||||
GTK_SIGNAL_FUNC (last_unref_cb), factory);
|
||||
|
||||
bonobo_main ();
|
||||
bonobo_main ();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -174,12 +174,6 @@ pipeline</ulink> and Microsoft's DirectShow for some background.
|
|||
@use_threads:
|
||||
|
||||
|
||||
<!-- ##### VARIABLE g_log_domain_gstreamer ##### -->
|
||||
<para>
|
||||
The variable that holds the GStreamer log domain
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_VERSION_MAJOR ##### -->
|
||||
<para>
|
||||
The major version of GStreamer at compile time
|
||||
|
|
|
@ -72,6 +72,34 @@ The GstBin object
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstBin::element-added ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstbin: the object which received the signal.
|
||||
@arg1: the element that was added to the bin
|
||||
|
||||
<!-- ##### SIGNAL GstBin::element-removed ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstbin: the object which received the signal.
|
||||
@arg1: the element that was removed from the bin
|
||||
|
||||
<!-- ##### SIGNAL GstBin::iterate ##### -->
|
||||
<para>
|
||||
This signal is emitted when a bin iterates, either automatically or
|
||||
due to a #gst_bin_iterate() call. The return value is used to
|
||||
determine if the object method handler processed any data.
|
||||
In most normal cases, a user-provided signal handler should return
|
||||
FALSE.
|
||||
</para>
|
||||
|
||||
@gstbin: the object which received the signal.
|
||||
@Returns: TRUE if the state of the bin was advanced.
|
||||
|
||||
<!-- ##### USER_FUNCTION GstBinPrePostIterateFunction ##### -->
|
||||
<para>
|
||||
The signature of the callback for the post and pre iterate function as set with
|
||||
|
@ -224,31 +252,3 @@ gst_bin_set_pre_iterate_function() and gst_bin_set_post_iterate_function().
|
|||
@clock:
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstBin::element-added ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstbin: the object which received the signal.
|
||||
@arg1: the element that was added to the bin
|
||||
|
||||
<!-- ##### SIGNAL GstBin::element-removed ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstbin: the object which received the signal.
|
||||
@arg1: the element that was removed from the bin
|
||||
|
||||
<!-- ##### SIGNAL GstBin::iterate ##### -->
|
||||
<para>
|
||||
This signal is emitted when a bin iterates, either automatically or
|
||||
due to a #gst_bin_iterate() call. The return value is used to
|
||||
determine if the object method handler processed any data.
|
||||
In most normal cases, a user-provided signal handler should return
|
||||
FALSE.
|
||||
</para>
|
||||
|
||||
@gstbin: the object which received the signal.
|
||||
@Returns: TRUE if the state of the bin was advanced.
|
||||
|
||||
|
|
|
@ -235,6 +235,21 @@ Get the clock flags
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### ARG GstClock:event-diff ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### ARG GstClock:max-diff ##### -->
|
||||
<para>
|
||||
Maximum allowed diff for clock sync requests against the real time.
|
||||
</para>
|
||||
|
||||
<!-- ##### ARG GstClock:stats ##### -->
|
||||
<para>
|
||||
Boolean property to activate stat generation on the clock.
|
||||
</para>
|
||||
|
||||
<!-- ##### FUNCTION gst_clock_set_speed ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -402,18 +417,3 @@ Get the clock flags
|
|||
@id:
|
||||
|
||||
|
||||
<!-- ##### ARG GstClock:event-diff ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### ARG GstClock:max-diff ##### -->
|
||||
<para>
|
||||
Maximum allowed diff for clock sync requests against the real time.
|
||||
</para>
|
||||
|
||||
<!-- ##### ARG GstClock:stats ##### -->
|
||||
<para>
|
||||
Boolean property to activate stat generation on the clock.
|
||||
</para>
|
||||
|
||||
|
|
|
@ -20,16 +20,6 @@ You'll get a bitmask of flags with gst_cpu_get_flags().
|
|||
|
||||
</para>
|
||||
|
||||
<!-- ##### ENUM GstCPUFlags ##### -->
|
||||
<para>
|
||||
Flags that represent cpu capabilities
|
||||
</para>
|
||||
|
||||
@GST_CPU_FLAG_MMX: The cpu is mmx enabled
|
||||
@GST_CPU_FLAG_SSE: The cpu is sse enabled
|
||||
@GST_CPU_FLAG_MMXEXT: The cpu has extended mmx instructions
|
||||
@GST_CPU_FLAG_3DNOW: The cpu is 3DNOW enabled
|
||||
|
||||
<!-- ##### FUNCTION gst_cpu_get_flags ##### -->
|
||||
<para>
|
||||
Request a set of bits specifiying the features of the CPU.
|
||||
|
|
|
@ -71,6 +71,59 @@ The element object
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstElement::eos ##### -->
|
||||
<para>
|
||||
Signal emited when the element goes to PAUSED due to an end-of-stream
|
||||
condition.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
|
||||
<!-- ##### SIGNAL GstElement::error ##### -->
|
||||
<para>
|
||||
This signal is emitted when an element has encountered an error that caused
|
||||
it to fail performing its function.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: the original #GstElement that generated the error.
|
||||
@arg2: a #GError containing the translated error message.
|
||||
@arg3: a debug string providing additional untranslated debug information, or NULL.
|
||||
|
||||
<!-- ##### SIGNAL GstElement::found-tag ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1:
|
||||
@arg2:
|
||||
|
||||
<!-- ##### SIGNAL GstElement::new-pad ##### -->
|
||||
<para>
|
||||
Is triggered whenever a new pad is added to an element.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: the new pad that was added
|
||||
|
||||
<!-- ##### SIGNAL GstElement::pad-removed ##### -->
|
||||
<para>
|
||||
Is triggered whenever a pad has been removed from the element.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: The pad that was removed.
|
||||
|
||||
<!-- ##### SIGNAL GstElement::state-change ##### -->
|
||||
<para>
|
||||
Is triggered whenever the state of an element changes.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: the new state of the object
|
||||
@arg2:
|
||||
|
||||
<!-- ##### MACRO gst_element_get_name ##### -->
|
||||
<para>
|
||||
Gets the name of the element.
|
||||
|
@ -966,56 +1019,3 @@ Helper macro to create query type functions
|
|||
@...: list of query types.
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstElement::eos ##### -->
|
||||
<para>
|
||||
Signal emited when the element goes to PAUSED due to an end-of-stream
|
||||
condition.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
|
||||
<!-- ##### SIGNAL GstElement::error ##### -->
|
||||
<para>
|
||||
This signal is emitted when an element has encountered an error that caused
|
||||
it to fail performing its function.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: the original #GstElement that generated the error.
|
||||
@arg2: a #GError containing the translated error message.
|
||||
@arg3: a debug string providing additional untranslated debug information, or NULL.
|
||||
|
||||
<!-- ##### SIGNAL GstElement::found-tag ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1:
|
||||
@arg2:
|
||||
|
||||
<!-- ##### SIGNAL GstElement::new-pad ##### -->
|
||||
<para>
|
||||
Is triggered whenever a new pad is added to an element.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: the new pad that was added
|
||||
|
||||
<!-- ##### SIGNAL GstElement::pad-removed ##### -->
|
||||
<para>
|
||||
Is triggered whenever a pad has been removed from the element.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: The pad that was removed.
|
||||
|
||||
<!-- ##### SIGNAL GstElement::state-change ##### -->
|
||||
<para>
|
||||
Is triggered whenever the state of an element changes.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: the new state of the object
|
||||
@arg2:
|
||||
|
||||
|
|
|
@ -15,18 +15,6 @@ formats can be used to perform seeking or conversions/query operations.
|
|||
#GstPad, #GstElement
|
||||
</para>
|
||||
|
||||
<!-- ##### ENUM GstFormat ##### -->
|
||||
<para>
|
||||
Standard predefined formats
|
||||
</para>
|
||||
|
||||
@GST_FORMAT_UNDEFINED: undefined format
|
||||
@GST_FORMAT_DEFAULT: the default format of the pad/element
|
||||
@GST_FORMAT_BYTES: bytes
|
||||
@GST_FORMAT_TIME: time in nanoseconds
|
||||
@GST_FORMAT_BUFFERS: buffers
|
||||
@GST_FORMAT_PERCENT: percentage of stream
|
||||
|
||||
<!-- ##### MACRO GST_FORMAT_PERCENT_MAX ##### -->
|
||||
<para>
|
||||
The PERCENT format is between 0 and this value
|
||||
|
|
|
@ -209,6 +209,19 @@ The GstIndex object
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstIndex::entry-added ##### -->
|
||||
<para>
|
||||
Is emited when a new entry is added to the index.
|
||||
</para>
|
||||
|
||||
@gstindex: the object which received the signal.
|
||||
@arg1: The entry added to the index.
|
||||
|
||||
<!-- ##### ARG GstIndex:resolver ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### FUNCTION gst_index_new ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -401,16 +414,3 @@ The GstIndex object
|
|||
@id:
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstIndex::entry-added ##### -->
|
||||
<para>
|
||||
Is emited when a new entry is added to the index.
|
||||
</para>
|
||||
|
||||
@gstindex: the object which received the signal.
|
||||
@arg1: The entry added to the index.
|
||||
|
||||
<!-- ##### ARG GstIndex:resolver ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
|
|
@ -21,12 +21,6 @@ The GstMemChunk is used to allocate critical resources for #GstBuffer and
|
|||
#GstAtomic, #GstBuffer, #GstEvent, #GstData
|
||||
</para>
|
||||
|
||||
<!-- ##### STRUCT GstMemChunk ##### -->
|
||||
<para>
|
||||
The memchunk structure
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_mem_chunk_new ##### -->
|
||||
<para>
|
||||
|
||||
|
|
|
@ -40,6 +40,47 @@ The GstObject
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstObject::deep-notify ##### -->
|
||||
<para>
|
||||
The deep notify signal is used to be notified of property changes.
|
||||
it is typically attached to the toplevel bin to receive notifications
|
||||
from all the elements contained in that bin.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the object that originated the signal
|
||||
@arg2: the property that changed
|
||||
|
||||
<!-- ##### SIGNAL GstObject::object-saved ##### -->
|
||||
<para>
|
||||
Is trigered whenever a new object is saved to XML. You can connect to
|
||||
this signal to insert custom XML tags into the core XML.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the xmlNodePtr of the parent node
|
||||
|
||||
<!-- ##### SIGNAL GstObject::parent-set ##### -->
|
||||
<para>
|
||||
Is emitted when the parent of an object is set.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the new parent
|
||||
|
||||
<!-- ##### SIGNAL GstObject::parent-unset ##### -->
|
||||
<para>
|
||||
Is emitted when the parent of an object is unset.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the old parent
|
||||
|
||||
<!-- ##### ARG GstObject:name ##### -->
|
||||
<para>
|
||||
The name of the object
|
||||
</para>
|
||||
|
||||
<!-- ##### MACRO GST_FLAGS ##### -->
|
||||
<para>
|
||||
This macro returns the entire set of flags for the object.
|
||||
|
@ -290,44 +331,3 @@ Check if the object has been destroyed.
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstObject::deep-notify ##### -->
|
||||
<para>
|
||||
The deep notify signal is used to be notified of property changes.
|
||||
it is typically attached to the toplevel bin to receive notifications
|
||||
from all the elements contained in that bin.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the object that originated the signal
|
||||
@arg2: the property that changed
|
||||
|
||||
<!-- ##### SIGNAL GstObject::object-saved ##### -->
|
||||
<para>
|
||||
Is trigered whenever a new object is saved to XML. You can connect to
|
||||
this signal to insert custom XML tags into the core XML.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the xmlNodePtr of the parent node
|
||||
|
||||
<!-- ##### SIGNAL GstObject::parent-set ##### -->
|
||||
<para>
|
||||
Is emitted when the parent of an object is set.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the new parent
|
||||
|
||||
<!-- ##### SIGNAL GstObject::parent-unset ##### -->
|
||||
<para>
|
||||
Is emitted when the parent of an object is unset.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the old parent
|
||||
|
||||
<!-- ##### ARG GstObject:name ##### -->
|
||||
<para>
|
||||
The name of the object
|
||||
</para>
|
||||
|
||||
|
|
|
@ -1193,6 +1193,11 @@ The Ghostpad object
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### ARG GstGhostPad:real-pad ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### FUNCTION gst_ghost_pad_new ##### -->
|
||||
<para>
|
||||
|
||||
|
|
|
@ -86,6 +86,15 @@ The padtemplate object.
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstPadTemplate::pad-created ##### -->
|
||||
<para>
|
||||
This signal is fired when an element creates a pad from this
|
||||
template.
|
||||
</para>
|
||||
|
||||
@gstpadtemplate: the object which received the signal.
|
||||
@arg1: The pad that was created.
|
||||
|
||||
<!-- ##### ENUM GstPadTemplateFlags ##### -->
|
||||
<para>
|
||||
Flags for the padtemplate
|
||||
|
@ -167,12 +176,3 @@ Check if the properties of the padtemplate are fixed
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstPadTemplate::pad-created ##### -->
|
||||
<para>
|
||||
This signal is fired when an element creates a pad from this
|
||||
template.
|
||||
</para>
|
||||
|
||||
@gstpadtemplate: the object which received the signal.
|
||||
@arg1: The pad that was created.
|
||||
|
||||
|
|
|
@ -41,14 +41,6 @@ The error quark
|
|||
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_error_quark ##### -->
|
||||
<para>
|
||||
Get the error quark
|
||||
</para>
|
||||
|
||||
@Returns: The error quark used in GError messages
|
||||
|
||||
|
||||
<!-- ##### ENUM GstPluginError ##### -->
|
||||
<para>
|
||||
The plugin loading errors
|
||||
|
|
|
@ -15,20 +15,6 @@ Query types can be used to perform queries on pads and elements.
|
|||
#GstPad, #GstElement
|
||||
</para>
|
||||
|
||||
<!-- ##### ENUM GstQueryType ##### -->
|
||||
<para>
|
||||
Standard predefined Query types
|
||||
</para>
|
||||
|
||||
@GST_QUERY_NONE: invalid query type
|
||||
@GST_QUERY_TOTAL: total length of stream
|
||||
@GST_QUERY_POSITION: current position in stream
|
||||
@GST_QUERY_LATENCY: latency of stream
|
||||
@GST_QUERY_JITTER: current jitter of stream
|
||||
@GST_QUERY_START: start of configured segment
|
||||
@GST_QUERY_SEGMENT_END: end of configured segment
|
||||
@GST_QUERY_RATE: current rate of the stream
|
||||
|
||||
<!-- ##### MACRO GST_QUERY_TYPE_RATE_DEN ##### -->
|
||||
<para>
|
||||
Rates are relative to this value
|
||||
|
@ -89,8 +75,10 @@ Convenience function to define a function that returns an array of query types.
|
|||
|
||||
</para>
|
||||
|
||||
@type:
|
||||
@Param1:
|
||||
@Returns:
|
||||
<!-- # Unused Parameters # -->
|
||||
@type:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_query_type_get_definitions ##### -->
|
||||
|
|
|
@ -4556,6 +4556,16 @@ can perform necessary cleanup.
|
|||
@pool: The pool that is being destroyed
|
||||
@user_data: user data as set on th bufferpool
|
||||
|
||||
<!-- ##### ENUM GstCPUFlags ##### -->
|
||||
<para>
|
||||
Flags that represent cpu capabilities
|
||||
</para>
|
||||
|
||||
@GST_CPU_FLAG_MMX: The cpu is mmx enabled
|
||||
@GST_CPU_FLAG_SSE: The cpu is sse enabled
|
||||
@GST_CPU_FLAG_MMXEXT: The cpu has extended mmx instructions
|
||||
@GST_CPU_FLAG_3DNOW: The cpu is 3DNOW enabled
|
||||
|
||||
<!-- ##### STRUCT GstCacheAssociation ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -5158,6 +5168,18 @@ Indicates the mmapped area should be touched to bring it into memory.
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### ENUM GstFormat ##### -->
|
||||
<para>
|
||||
Standard predefined formats
|
||||
</para>
|
||||
|
||||
@GST_FORMAT_UNDEFINED: undefined format
|
||||
@GST_FORMAT_DEFAULT: the default format of the pad/element
|
||||
@GST_FORMAT_BYTES: bytes
|
||||
@GST_FORMAT_TIME: time in nanoseconds
|
||||
@GST_FORMAT_BUFFERS: buffers
|
||||
@GST_FORMAT_PERCENT: percentage of stream
|
||||
|
||||
<!-- ##### STRUCT GstHttpSrc ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -5275,6 +5297,12 @@ Specify the location of the file. The location must be a fully qualified URL.
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### STRUCT GstMemChunk ##### -->
|
||||
<para>
|
||||
The memchunk structure
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### STRUCT GstMemChunkElement ##### -->
|
||||
<para>
|
||||
An entry in the memchunk area
|
||||
|
@ -5505,6 +5533,20 @@ Sets the command to be executed.
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### ENUM GstQueryType ##### -->
|
||||
<para>
|
||||
Standard predefined Query types
|
||||
</para>
|
||||
|
||||
@GST_QUERY_NONE: invalid query type
|
||||
@GST_QUERY_TOTAL: total length of stream
|
||||
@GST_QUERY_POSITION: current position in stream
|
||||
@GST_QUERY_LATENCY: latency of stream
|
||||
@GST_QUERY_JITTER: current jitter of stream
|
||||
@GST_QUERY_START: start of configured segment
|
||||
@GST_QUERY_SEGMENT_END: end of configured segment
|
||||
@GST_QUERY_RATE: current rate of the stream
|
||||
|
||||
<!-- ##### STRUCT GstQueue ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -5571,6 +5613,17 @@ the region types for #gst_pad_pullregion.
|
|||
@global_reg:
|
||||
@local_reg:
|
||||
|
||||
<!-- ##### ENUM GstRegistryReturn ##### -->
|
||||
<para>
|
||||
The return value of registry operations
|
||||
</para>
|
||||
|
||||
@GST_REGISTRY_OK: The registry reported no error.
|
||||
@GST_REGISTRY_LOAD_ERROR: There was a load error
|
||||
@GST_REGISTRY_SAVE_ERROR: There was an error saving the registry
|
||||
@GST_REGISTRY_PLUGIN_LOAD_ERROR: There was an error loading a plugin
|
||||
@GST_REGISTRY_PLUGIN_SIGNATURE_ERROR: There was an error saving a plugin
|
||||
|
||||
<!-- ##### STRUCT GstRegistryWrite ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -5798,6 +5851,20 @@ Flags for the GstSrc element
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### ENUM GstTagMergeMode ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@GST_TAG_MERGE_UNDEFINED:
|
||||
@GST_TAG_MERGE_REPLACE_ALL:
|
||||
@GST_TAG_MERGE_REPLACE:
|
||||
@GST_TAG_MERGE_APPEND:
|
||||
@GST_TAG_MERGE_PREPEND:
|
||||
@GST_TAG_MERGE_KEEP:
|
||||
@GST_TAG_MERGE_KEEP_ALL:
|
||||
@GST_TAG_MERGE_COUNT:
|
||||
|
||||
<!-- ##### STRUCT GstTee ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -5921,6 +5988,15 @@ Query the element for the current mime type
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstXML::object-loaded ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstxml: the object which received the signal.
|
||||
@arg1:
|
||||
@arg2:
|
||||
|
||||
<!-- ##### USER_FUNCTION GstXMLRegistryAddPathList ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -6676,6 +6752,12 @@ must be defined to activate the tracing functionality.
|
|||
@llink:
|
||||
@Returns:
|
||||
|
||||
<!-- ##### VARIABLE g_log_domain_gstreamer ##### -->
|
||||
<para>
|
||||
The variable that holds the GStreamer log domain
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO g_object_class_find_property ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -9561,6 +9643,13 @@ Destroys the pipeline.
|
|||
|
||||
@Returns:
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_error_quark ##### -->
|
||||
<para>
|
||||
Get the error quark
|
||||
</para>
|
||||
|
||||
@Returns: The error quark used in GError messages
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_feature_get_type ##### -->
|
||||
<para>
|
||||
|
||||
|
|
|
@ -14,17 +14,6 @@ The registry holds the available plugins in the system.
|
|||
#GstPlugin, #GstPluginFeature
|
||||
</para>
|
||||
|
||||
<!-- ##### ENUM GstRegistryReturn ##### -->
|
||||
<para>
|
||||
The return value of registry operations
|
||||
</para>
|
||||
|
||||
@GST_REGISTRY_OK: The registry reported no error.
|
||||
@GST_REGISTRY_LOAD_ERROR: There was a load error
|
||||
@GST_REGISTRY_SAVE_ERROR: There was an error saving the registry
|
||||
@GST_REGISTRY_PLUGIN_LOAD_ERROR: There was an error loading a plugin
|
||||
@GST_REGISTRY_PLUGIN_SIGNATURE_ERROR: There was an error saving a plugin
|
||||
|
||||
<!-- ##### ENUM GstRegistryFlags ##### -->
|
||||
<para>
|
||||
Flags for the registry
|
||||
|
|
|
@ -14,20 +14,6 @@ GstTag
|
|||
|
||||
</para>
|
||||
|
||||
<!-- ##### ENUM GstTagMergeMode ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@GST_TAG_MERGE_UNDEFINED:
|
||||
@GST_TAG_MERGE_REPLACE_ALL:
|
||||
@GST_TAG_MERGE_REPLACE:
|
||||
@GST_TAG_MERGE_APPEND:
|
||||
@GST_TAG_MERGE_PREPEND:
|
||||
@GST_TAG_MERGE_KEEP:
|
||||
@GST_TAG_MERGE_KEEP_ALL:
|
||||
@GST_TAG_MERGE_COUNT:
|
||||
|
||||
<!-- ##### ENUM GstTagFlag ##### -->
|
||||
<para>
|
||||
|
||||
|
|
|
@ -34,15 +34,6 @@ The GstThread object
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_thread_new ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@name:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstThread::shutdown ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -55,3 +46,12 @@ The GstThread object
|
|||
The thread priority
|
||||
</para>
|
||||
|
||||
<!-- ##### FUNCTION gst_thread_new ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@name:
|
||||
@Returns:
|
||||
|
||||
|
||||
|
|
|
@ -105,25 +105,3 @@ All GstElements can be serialized to an XML presentation and subsequently loaded
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstXML::object-loaded ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@:
|
||||
@:
|
||||
@:
|
||||
|
||||
@gstxml: the object which received the signal.
|
||||
@arg1:
|
||||
@arg2:
|
||||
|
||||
<!-- ##### SIGNAL GstXML::object-loaded ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstxml: the object which received the signal.
|
||||
@arg1:
|
||||
@arg2:
|
||||
|
||||
|
|
|
@ -3,13 +3,16 @@
|
|||
static gchar *_subject, *_category;
|
||||
static gint _testnum = 0;
|
||||
static gboolean _passed;
|
||||
static gint _total_tests = 0,_passed_tests = 0;
|
||||
static gint _total_tests = 0, _passed_tests = 0;
|
||||
static gint _random_size;
|
||||
|
||||
void tabpad(gchar *str,gint width) {
|
||||
void
|
||||
tabpad (gchar * str, gint width)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<width-strlen(str);i++)
|
||||
fprintf(stderr," ");
|
||||
|
||||
for (i = 0; i < width - strlen (str); i++)
|
||||
fprintf (stderr, " ");
|
||||
}
|
||||
|
||||
#define TEST_SUBJECT(subject) fprintf(stderr,"Subject: %s\n",subject),_subject = subject
|
||||
|
@ -36,267 +39,276 @@ void tabpad(gchar *str,gint width) {
|
|||
_total_tests++; \
|
||||
}G_STMT_END;
|
||||
|
||||
void SETUP_RANDOM_SIZE(void *random,gint size) {
|
||||
void
|
||||
SETUP_RANDOM_SIZE (void *random, gint size)
|
||||
{
|
||||
int i;
|
||||
if (random) g_free(random);
|
||||
|
||||
if (random)
|
||||
g_free (random);
|
||||
_random_size = size;
|
||||
random = g_malloc(_random_size);
|
||||
for (i=0;i<_random_size;i++)
|
||||
((unsigned char *)random)[i] = i;
|
||||
random = g_malloc (_random_size);
|
||||
for (i = 0; i < _random_size; i++)
|
||||
((unsigned char *) random)[i] = i;
|
||||
}
|
||||
|
||||
#define SETUP_RANDOM(random,type) SETUP_RANDOM_SIZE(random,sizeof(type))
|
||||
|
||||
gboolean RANDOM_OK(void *random) {
|
||||
gboolean
|
||||
RANDOM_OK (void *random)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<_random_size;i++) {
|
||||
if (((unsigned char *)random)[i] != i) {
|
||||
SETUP_RANDOM_SIZE(random,_random_size);
|
||||
|
||||
for (i = 0; i < _random_size; i++) {
|
||||
if (((unsigned char *) random)[i] != i) {
|
||||
SETUP_RANDOM_SIZE (random, _random_size);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[]) {
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstObject *object;
|
||||
GstObject *parent;
|
||||
GstObject *newparent;
|
||||
GtkObject *gtkobject;
|
||||
GstObject *curparent;
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
TEST_SUBJECT("GstObject");
|
||||
TEST_SUBJECT ("GstObject");
|
||||
|
||||
|
||||
TEST_CATEGORY("Creation");
|
||||
TEST_CATEGORY ("Creation");
|
||||
|
||||
TEST("create object");
|
||||
TEST ("create object");
|
||||
/* setup */
|
||||
/* action */
|
||||
object = gst_object_new();
|
||||
object = gst_object_new ();
|
||||
/* assertions */
|
||||
ASSERT(object != NULL);
|
||||
ASSERT(GST_IS_OBJECT(object));
|
||||
ASSERT (object != NULL);
|
||||
ASSERT (GST_IS_OBJECT (object));
|
||||
/* cleanup */
|
||||
g_free(object);
|
||||
ENDTEST();
|
||||
g_free (object);
|
||||
ENDTEST ();
|
||||
|
||||
|
||||
/* new category */
|
||||
TEST_CATEGORY("Refcounting");
|
||||
TEST_CATEGORY ("Refcounting");
|
||||
/* category setup */
|
||||
object = gst_object_new();
|
||||
object = gst_object_new ();
|
||||
|
||||
TEST("new object");
|
||||
TEST ("new object");
|
||||
/* setup */
|
||||
/* action */
|
||||
/* assertions */
|
||||
ASSERT(object->refcount == 1);
|
||||
ASSERT(GTK_OBJECT_FLOATING(object) == TRUE);
|
||||
ASSERT (object->refcount == 1);
|
||||
ASSERT (GTK_OBJECT_FLOATING (object) == TRUE);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("increment refcount");
|
||||
TEST ("increment refcount");
|
||||
/* setup */
|
||||
/* action */
|
||||
gst_object_ref(object);
|
||||
gst_object_ref (object);
|
||||
/* assertions */
|
||||
ASSERT(object->refcount == 2);
|
||||
ASSERT(GTK_OBJECT_FLOATING(object) == TRUE);
|
||||
ASSERT (object->refcount == 2);
|
||||
ASSERT (GTK_OBJECT_FLOATING (object) == TRUE);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("sink object");
|
||||
TEST ("sink object");
|
||||
/* setup */
|
||||
/* action */
|
||||
gst_object_sink(object);
|
||||
gst_object_sink (object);
|
||||
/* assertions */
|
||||
ASSERT(object->refcount == 1);
|
||||
ASSERT(GTK_OBJECT_FLOATING(object) == FALSE);
|
||||
ASSERT (object->refcount == 1);
|
||||
ASSERT (GTK_OBJECT_FLOATING (object) == FALSE);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("increment refcount after sink");
|
||||
TEST ("increment refcount after sink");
|
||||
/* setup */
|
||||
/* action */
|
||||
gst_object_ref(object);
|
||||
gst_object_ref (object);
|
||||
/* assertions */
|
||||
ASSERT(object->refcount == 2);
|
||||
ASSERT(GTK_OBJECT_FLOATING(object) == FALSE);
|
||||
ASSERT (object->refcount == 2);
|
||||
ASSERT (GTK_OBJECT_FLOATING (object) == FALSE);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("decrement refcount after sink");
|
||||
TEST ("decrement refcount after sink");
|
||||
/* setup */
|
||||
/* action */
|
||||
gst_object_unref(object);
|
||||
gst_object_unref (object);
|
||||
/* assertions */
|
||||
ASSERT(object->refcount == 1);
|
||||
ASSERT(GTK_OBJECT_FLOATING(object) == FALSE);
|
||||
ASSERT (object->refcount == 1);
|
||||
ASSERT (GTK_OBJECT_FLOATING (object) == FALSE);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
/* category cleanup */
|
||||
g_free(object);
|
||||
g_free (object);
|
||||
|
||||
|
||||
|
||||
/* new category */
|
||||
TEST_CATEGORY("Parentage");
|
||||
TEST_CATEGORY ("Parentage");
|
||||
/* category setup */
|
||||
object = gst_object_new();
|
||||
parent = gst_object_new();
|
||||
newparent = gst_object_new();
|
||||
gtkobject = gtk_type_new(gtk_object_get_type());
|
||||
object = gst_object_new ();
|
||||
parent = gst_object_new ();
|
||||
newparent = gst_object_new ();
|
||||
gtkobject = gtk_type_new (gtk_object_get_type ());
|
||||
/* category assertions */
|
||||
ASSERT(object != NULL);
|
||||
ASSERT(object->refcount == 1);
|
||||
ASSERT(object->parent == NULL);
|
||||
ASSERT(parent != NULL);
|
||||
ASSERT(newparent != NULL);
|
||||
ASSERT(gtkobject != NULL);
|
||||
ASSERT(!GST_IS_OBJECT(gtkobject));
|
||||
ASSERT (object != NULL);
|
||||
ASSERT (object->refcount == 1);
|
||||
ASSERT (object->parent == NULL);
|
||||
ASSERT (parent != NULL);
|
||||
ASSERT (newparent != NULL);
|
||||
ASSERT (gtkobject != NULL);
|
||||
ASSERT (!GST_IS_OBJECT (gtkobject));
|
||||
|
||||
TEST("gst_object_set_parent: null object");
|
||||
TEST ("gst_object_set_parent: null object");
|
||||
/* setup */
|
||||
/* action */
|
||||
gst_object_set_parent(NULL,NULL);
|
||||
gst_object_set_parent (NULL, NULL);
|
||||
/* assertions */
|
||||
ASSERT(object->parent == NULL);
|
||||
ASSERT (object->parent == NULL);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("gst_object_set_parent: invalid object");
|
||||
TEST ("gst_object_set_parent: invalid object");
|
||||
/* setup */
|
||||
/* action */
|
||||
gst_object_set_parent((GstObject*)gtkobject,NULL);
|
||||
gst_object_set_parent ((GstObject *) gtkobject, NULL);
|
||||
/* assertions */
|
||||
ASSERT(object->parent == NULL);
|
||||
ASSERT (object->parent == NULL);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("gst_object_set_parent: null parent");
|
||||
TEST ("gst_object_set_parent: null parent");
|
||||
/* setup */
|
||||
/* action */
|
||||
gst_object_set_parent(object,NULL);
|
||||
gst_object_set_parent (object, NULL);
|
||||
/* assertions */
|
||||
ASSERT(object->parent == NULL);
|
||||
ASSERT (object->parent == NULL);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("gst_object_set_parent: invalid parent");
|
||||
TEST ("gst_object_set_parent: invalid parent");
|
||||
/* setup */
|
||||
/* action */
|
||||
gst_object_set_parent(object,(GstObject*)gtkobject);
|
||||
gst_object_set_parent (object, (GstObject *) gtkobject);
|
||||
/* assertions */
|
||||
ASSERT(object->parent == NULL);
|
||||
ASSERT (object->parent == NULL);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("gst_object_set_parent: valid object, parent is object");
|
||||
TEST ("gst_object_set_parent: valid object, parent is object");
|
||||
/* setup */
|
||||
/* action */
|
||||
gst_object_set_parent(object,object);
|
||||
gst_object_set_parent (object, object);
|
||||
/* assertions */
|
||||
ASSERT(object->parent == NULL);
|
||||
ASSERT (object->parent == NULL);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("gst_object_set_parent: valid object and parent");
|
||||
TEST ("gst_object_set_parent: valid object and parent");
|
||||
/* setup */
|
||||
/* action */
|
||||
gst_object_set_parent(object,parent);
|
||||
gst_object_set_parent (object, parent);
|
||||
/* assertions */
|
||||
ASSERT(object->parent == parent);
|
||||
ASSERT (object->parent == parent);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("gst_object_set_parent: parent already set");
|
||||
TEST ("gst_object_set_parent: parent already set");
|
||||
/* setup */
|
||||
/* action */
|
||||
gst_object_set_parent(object,newparent);
|
||||
gst_object_set_parent (object, newparent);
|
||||
/* assertions */
|
||||
ASSERT(object->parent != newparent);
|
||||
ASSERT(object->parent == parent);
|
||||
ASSERT (object->parent != newparent);
|
||||
ASSERT (object->parent == parent);
|
||||
/* cleanup */
|
||||
g_free(object);
|
||||
ENDTEST();
|
||||
g_free (object);
|
||||
ENDTEST ();
|
||||
|
||||
|
||||
TEST("gst_object_get_parent: null object");
|
||||
TEST ("gst_object_get_parent: null object");
|
||||
/* setup */
|
||||
/* action */
|
||||
curparent = gst_object_get_parent(NULL);
|
||||
curparent = gst_object_get_parent (NULL);
|
||||
/* assertions */
|
||||
ASSERT(curparent == NULL);
|
||||
ASSERT (curparent == NULL);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("gst_object_get_parent: invalid object");
|
||||
TEST ("gst_object_get_parent: invalid object");
|
||||
/* setup */
|
||||
/* action */
|
||||
curparent = gst_object_get_parent((GstObject*)gtkobject);
|
||||
curparent = gst_object_get_parent ((GstObject *) gtkobject);
|
||||
/* assertions */
|
||||
ASSERT(curparent == NULL);
|
||||
ASSERT (curparent == NULL);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("gst_object_get_parent: no parent");
|
||||
TEST ("gst_object_get_parent: no parent");
|
||||
/* setup */
|
||||
object = gst_object_new();
|
||||
object = gst_object_new ();
|
||||
/* action */
|
||||
curparent = gst_object_get_parent(object);
|
||||
curparent = gst_object_get_parent (object);
|
||||
/* assertions */
|
||||
ASSERT(curparent == NULL);
|
||||
ASSERT (curparent == NULL);
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("gst_object_get_parent: valid parent");
|
||||
TEST ("gst_object_get_parent: valid parent");
|
||||
/* setup */
|
||||
gst_object_set_parent(object,parent);
|
||||
gst_object_set_parent (object, parent);
|
||||
/* action */
|
||||
curparent = gst_object_get_parent(object);
|
||||
curparent = gst_object_get_parent (object);
|
||||
/* assertions */
|
||||
ASSERT(curparent == parent);
|
||||
ASSERT (curparent == parent);
|
||||
/* cleanup */
|
||||
g_free(object);
|
||||
ENDTEST();
|
||||
g_free (object);
|
||||
ENDTEST ();
|
||||
|
||||
|
||||
TEST("gst_object_unparent: null object");
|
||||
TEST ("gst_object_unparent: null object");
|
||||
/* setup */
|
||||
/* action */
|
||||
gst_object_unparent(NULL);
|
||||
gst_object_unparent (NULL);
|
||||
/* assertions */
|
||||
/* NONE - FIXME! */
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("gst_object_unparent: invalid object");
|
||||
TEST ("gst_object_unparent: invalid object");
|
||||
/* setup */
|
||||
/* action */
|
||||
gst_object_unparent((GstObject*)gtkobject);
|
||||
gst_object_unparent ((GstObject *) gtkobject);
|
||||
/* assertions */
|
||||
/* NONE - FIXME! */
|
||||
/* cleanup */
|
||||
ENDTEST();
|
||||
ENDTEST ();
|
||||
|
||||
TEST("gst_object_unparent: no parent");
|
||||
TEST ("gst_object_unparent: no parent");
|
||||
/* setup */
|
||||
object = gst_object_new();
|
||||
|
||||
object = gst_object_new ();
|
||||
|
||||
|
||||
/* category cleanup */
|
||||
g_free(object);
|
||||
g_free(parent);
|
||||
g_free(newparent);
|
||||
g_free(gtkobject);
|
||||
g_free (object);
|
||||
g_free (parent);
|
||||
g_free (newparent);
|
||||
g_free (gtkobject);
|
||||
|
||||
|
||||
|
||||
fprintf(stderr,"\n\nTotal tests:\t%d\n",_total_tests);
|
||||
fprintf(stderr,"Total passed:\t%d\n",_passed_tests);
|
||||
fprintf(stderr,"Total FAILED:\t%d\n",_total_tests-_passed_tests);
|
||||
fprintf (stderr, "\n\nTotal tests:\t%d\n", _total_tests);
|
||||
fprintf (stderr, "Total passed:\t%d\n", _passed_tests);
|
||||
fprintf (stderr, "Total FAILED:\t%d\n", _total_tests - _passed_tests);
|
||||
}
|
||||
|
|
|
@ -20,21 +20,21 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
static void
|
||||
fill_queue (GstElement *queue, gint level, GstBin *pipeline)
|
||||
fill_queue (GstElement * queue, gint level, GstBin * pipeline)
|
||||
{
|
||||
/* this needs to iterate till something is pushed
|
||||
* in the queue */
|
||||
gst_bin_iterate (pipeline);
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc, gchar *argv[])
|
||||
gint
|
||||
main (gint argc, gchar * argv[])
|
||||
{
|
||||
GstElement *queue, *src, *pipeline;
|
||||
GstBuffer *buffer;
|
||||
gboolean done = FALSE;
|
||||
GstPad *pad;
|
||||
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
queue = gst_element_factory_make ("queue", "queue");
|
||||
|
@ -50,19 +50,19 @@ main (gint argc, gchar *argv[])
|
|||
gst_element_link_many (src, queue, NULL);
|
||||
|
||||
pad = gst_element_get_pad (queue, "src");
|
||||
g_signal_connect (G_OBJECT (queue), "low_watermark", G_CALLBACK (fill_queue), pipeline);
|
||||
g_signal_connect (G_OBJECT (queue), "low_watermark", G_CALLBACK (fill_queue),
|
||||
pipeline);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
do {
|
||||
do {
|
||||
/* get buffer into the app */
|
||||
buffer = GST_RPAD_GETFUNC (pad) (pad);
|
||||
|
||||
/* just exit on any event */
|
||||
if (GST_IS_EVENT (buffer)) {
|
||||
done = TRUE;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
gst_util_dump_mem (GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
|
||||
}
|
||||
gst_data_unref (GST_DATA (buffer));
|
||||
|
@ -71,6 +71,6 @@ main (gint argc, gchar *argv[])
|
|||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
gst_object_unref (GST_OBJECT (pipeline));
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,23 +16,24 @@
|
|||
|
||||
#define DEBUG
|
||||
|
||||
gboolean playing = TRUE;
|
||||
gboolean cut_start_signalled = FALSE;
|
||||
gboolean cut_stop_signalled = FALSE;
|
||||
gboolean playing = TRUE;
|
||||
gboolean cut_start_signalled = FALSE;
|
||||
gboolean cut_stop_signalled = FALSE;
|
||||
|
||||
int id = 0; /* increment this for each new cut */
|
||||
GstElement *main_bin;
|
||||
GstElement *audiosrc;
|
||||
GstElement *queue;
|
||||
GstElement *thread;
|
||||
GstElement *cutter;
|
||||
GstElement *disksink;
|
||||
GstElement *encoder;
|
||||
char buffer[255];
|
||||
int id = 0; /* increment this for each new cut */
|
||||
GstElement *main_bin;
|
||||
GstElement *audiosrc;
|
||||
GstElement *queue;
|
||||
GstElement *thread;
|
||||
GstElement *cutter;
|
||||
GstElement *disksink;
|
||||
GstElement *encoder;
|
||||
char buffer[255];
|
||||
|
||||
/* signal callbacks */
|
||||
|
||||
void cut_start (GstElement *element)
|
||||
void
|
||||
cut_start (GstElement * element)
|
||||
{
|
||||
g_print ("\nDEBUG: main: cut start\n");
|
||||
/* we should pause the pipeline, unlink cutter and disksink
|
||||
|
@ -45,12 +46,14 @@ void cut_start (GstElement *element)
|
|||
{
|
||||
time_t seconds;
|
||||
struct tm *ct;
|
||||
|
||||
time (&seconds);
|
||||
ct = localtime (&seconds);
|
||||
/* sprintf (buffer, "/news/incoming/audio/cutter.%06d.wav", id); */
|
||||
sprintf (buffer, "/news/incoming/audio/cutter.%04d%02d%02d.%02d%02d%02d.wav",
|
||||
ct->tm_year + 1900, ct->tm_mon, ct->tm_mday,
|
||||
ct->tm_hour, ct->tm_min, ct->tm_sec);
|
||||
sprintf (buffer,
|
||||
"/news/incoming/audio/cutter.%04d%02d%02d.%02d%02d%02d.wav",
|
||||
ct->tm_year + 1900, ct->tm_mon, ct->tm_mday, ct->tm_hour, ct->tm_min,
|
||||
ct->tm_sec);
|
||||
}
|
||||
g_print ("DEBUG: cut_start: setting new location to %s\n", buffer);
|
||||
g_object_set (G_OBJECT (disksink), "location", buffer, NULL);
|
||||
|
@ -62,13 +65,15 @@ void cut_start (GstElement *element)
|
|||
return;
|
||||
}
|
||||
|
||||
void cut_start_signal (GstElement *element)
|
||||
void
|
||||
cut_start_signal (GstElement * element)
|
||||
{
|
||||
g_print ("\nDEBUG: main: cut start signal\n");
|
||||
cut_start_signalled = TRUE;
|
||||
}
|
||||
|
||||
void cut_stop (GstElement *element)
|
||||
void
|
||||
cut_stop (GstElement * element)
|
||||
{
|
||||
g_print ("\nDEBUG: main: cut stop\n");
|
||||
/* we should pause the pipeline, unlink disksink, create a fake disksink,
|
||||
|
@ -85,42 +90,41 @@ void cut_stop (GstElement *element)
|
|||
return;
|
||||
}
|
||||
|
||||
void cut_stop_signal (GstElement *element)
|
||||
void
|
||||
cut_stop_signal (GstElement * element)
|
||||
{
|
||||
g_print ("\nDEBUG: main: cut stop signal\n");
|
||||
cut_stop_signalled = TRUE;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
/*int i, j; */
|
||||
/*gboolean done; */
|
||||
|
||||
|
||||
/*char buffer[20]; */
|
||||
|
||||
|
||||
/*output_channel_t *channel_out; */
|
||||
|
||||
|
||||
GstElement *audiosrc;
|
||||
|
||||
gst_init (&argc,&argv);
|
||||
gst_init (&argc, &argv);
|
||||
/*
|
||||
if (argc == 1)
|
||||
{
|
||||
g_print("usage: %s <filename1> <filename2> <...>\n", argv[0]);
|
||||
exit(-1);
|
||||
}*/
|
||||
|
||||
|
||||
/* set up input channel and main bin */
|
||||
|
||||
g_print ("creating main bin\n");
|
||||
g_print ("creating main bin\n");
|
||||
/* create cutter */
|
||||
cutter = gst_element_factory_make ("cutter", "cutter");
|
||||
|
||||
g_object_set (G_OBJECT (cutter),
|
||||
"threshold_dB", -40.0,
|
||||
"runlength", 0.5,
|
||||
"prelength", 1.0,
|
||||
NULL);
|
||||
g_object_set (G_OBJECT (cutter),
|
||||
"threshold_dB", -40.0, "runlength", 0.5, "prelength", 1.0, NULL);
|
||||
|
||||
/* create an audio src */
|
||||
if (!(audiosrc = gst_element_factory_make ("osssrc", "audio_src")))
|
||||
|
@ -128,21 +132,20 @@ int main (int argc, char *argv[])
|
|||
|
||||
/* set params */
|
||||
|
||||
g_object_set (G_OBJECT (audiosrc), "frequency", 44100,
|
||||
"channels", 1,
|
||||
"format", 16, NULL);
|
||||
g_object_set (G_OBJECT (audiosrc), "frequency", 44100,
|
||||
"channels", 1, "format", 16, NULL);
|
||||
|
||||
if (!(encoder = gst_element_factory_make ("passthrough", "encoder")))
|
||||
g_error ("Could not create 'passthrough' element !\n");
|
||||
|
||||
|
||||
if (!(disksink = gst_element_factory_make ("afsink", "disk_sink")))
|
||||
g_error ("Could not create 'afsink' element !\n");
|
||||
|
||||
|
||||
g_object_set (G_OBJECT (disksink), "location", "/dev/null", NULL);
|
||||
|
||||
thread = gst_thread_new ("thread");
|
||||
g_assert (thread != NULL);
|
||||
|
||||
|
||||
/* create main bin */
|
||||
main_bin = gst_pipeline_new ("bin");
|
||||
g_assert (main_bin != NULL);
|
||||
|
@ -161,10 +164,10 @@ int main (int argc, char *argv[])
|
|||
|
||||
/* set signal handlers */
|
||||
g_print ("setting signal handlers\n");
|
||||
g_signal_connect (G_OBJECT(cutter), "cut_start",
|
||||
(GCallback)cut_start_signal, NULL);
|
||||
g_signal_connect (G_OBJECT(cutter), "cut_stop",
|
||||
(GCallback)cut_stop_signal, NULL);
|
||||
g_signal_connect (G_OBJECT (cutter), "cut_start",
|
||||
(GCallback) cut_start_signal, NULL);
|
||||
g_signal_connect (G_OBJECT (cutter), "cut_stop",
|
||||
(GCallback) cut_stop_signal, NULL);
|
||||
|
||||
/* start playing */
|
||||
g_print ("setting to play\n");
|
||||
|
@ -173,23 +176,20 @@ int main (int argc, char *argv[])
|
|||
g_print ("setting thread to play\n");
|
||||
gst_element_set_state (GST_ELEMENT (thread), GST_STATE_PLAYING);
|
||||
*/
|
||||
while (playing)
|
||||
{
|
||||
while (playing) {
|
||||
/* g_print ("> "); */
|
||||
gst_bin_iterate (GST_BIN (main_bin));
|
||||
gst_bin_iterate (GST_BIN (main_bin));
|
||||
/* g_print (" <"); */
|
||||
if (cut_start_signalled)
|
||||
{
|
||||
g_print ("\nDEBUG: main: cut_start_signalled true !\n");
|
||||
cut_start (cutter);
|
||||
cut_start_signalled = FALSE;
|
||||
}
|
||||
if (cut_stop_signalled)
|
||||
{
|
||||
g_print ("\nDEBUG: main: cut_stop_signalled true !\n");
|
||||
cut_stop (cutter);
|
||||
cut_stop_signalled = FALSE;
|
||||
}
|
||||
if (cut_start_signalled) {
|
||||
g_print ("\nDEBUG: main: cut_start_signalled true !\n");
|
||||
cut_start (cutter);
|
||||
cut_start_signalled = FALSE;
|
||||
}
|
||||
if (cut_stop_signalled) {
|
||||
g_print ("\nDEBUG: main: cut_stop_signalled true !\n");
|
||||
cut_stop (cutter);
|
||||
cut_stop_signalled = FALSE;
|
||||
}
|
||||
}
|
||||
g_print ("we're done iterating.\n");
|
||||
/* stop the bin */
|
||||
|
@ -199,5 +199,5 @@ int main (int argc, char *argv[])
|
|||
gst_object_unref (GST_OBJECT (disksink));
|
||||
gst_object_unref (GST_OBJECT (main_bin));
|
||||
|
||||
exit(0);
|
||||
exit (0);
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
* thomas@apestaart.org
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
GstElement *pipe;
|
||||
GstElement *disksink;
|
||||
GstElement *audiosink;
|
||||
|
||||
|
||||
char *location;
|
||||
int channel_id;
|
||||
} output_channel_t;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *bin, *filesrc, *decoder, *osssink;
|
||||
|
||||
|
@ -36,7 +37,7 @@ int main (int argc, char *argv[])
|
|||
|
||||
/* link the elements */
|
||||
gst_element_link_many (filesrc, decoder, osssink, NULL);
|
||||
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state (bin, GST_STATE_PLAYING);
|
||||
|
||||
|
@ -47,4 +48,3 @@ int main (int argc, char *argv[])
|
|||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
static void
|
||||
gst_play_have_type (GstElement *typefind, GstCaps *caps, GstElement *pipeline)
|
||||
gst_play_have_type (GstElement * typefind, GstCaps * caps,
|
||||
GstElement * pipeline)
|
||||
{
|
||||
GstElement *osssink;
|
||||
GstElement *new_element;
|
||||
|
@ -21,18 +22,15 @@ gst_play_have_type (GstElement *typefind, GstCaps *caps, GstElement *pipeline)
|
|||
/* unlink_pads the typefind from the pipeline and remove it */
|
||||
gst_element_unlink_pads (cache, "src", typefind, "sink");
|
||||
gst_bin_remove (GST_BIN (autobin), typefind);
|
||||
|
||||
|
||||
/* and an audio sink */
|
||||
osssink = gst_element_factory_make("osssink", "play_audio");
|
||||
g_assert(osssink != NULL);
|
||||
osssink = gst_element_factory_make ("osssink", "play_audio");
|
||||
g_assert (osssink != NULL);
|
||||
|
||||
autoplug = gst_autoplug_factory_make ("staticrender");
|
||||
g_assert (autoplug != NULL);
|
||||
|
||||
new_element = gst_autoplug_to_renderers (autoplug,
|
||||
caps,
|
||||
osssink,
|
||||
NULL);
|
||||
new_element = gst_autoplug_to_renderers (autoplug, caps, osssink, NULL);
|
||||
|
||||
if (!new_element) {
|
||||
g_print ("could not autoplug, no suitable codecs found...\n");
|
||||
|
@ -51,7 +49,7 @@ gst_play_have_type (GstElement *typefind, GstCaps *caps, GstElement *pipeline)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_play_cache_empty (GstElement *element, GstElement *pipeline)
|
||||
gst_play_cache_empty (GstElement * element, GstElement * pipeline)
|
||||
{
|
||||
GstElement *autobin;
|
||||
GstElement *filesrc;
|
||||
|
@ -77,8 +75,8 @@ gst_play_cache_empty (GstElement *element, GstElement *pipeline)
|
|||
fprintf (stderr, "done with cache_empty\n");
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *filesrc;
|
||||
GstElement *pipeline;
|
||||
|
@ -105,23 +103,24 @@ main (int argc, char *argv[])
|
|||
|
||||
autobin = gst_bin_new ("autobin");
|
||||
cache = gst_element_factory_make ("autoplugcache", "cache");
|
||||
g_signal_connect (G_OBJECT (cache), "cache_empty",
|
||||
G_CALLBACK (gst_play_cache_empty), pipeline);
|
||||
g_signal_connect (G_OBJECT (cache), "cache_empty",
|
||||
G_CALLBACK (gst_play_cache_empty), pipeline);
|
||||
|
||||
typefind = gst_element_factory_make ("typefind", "typefind");
|
||||
g_signal_connect (G_OBJECT (typefind), "have_type",
|
||||
G_CALLBACK (gst_play_have_type), pipeline);
|
||||
g_signal_connect (G_OBJECT (typefind), "have_type",
|
||||
G_CALLBACK (gst_play_have_type), pipeline);
|
||||
gst_bin_add (GST_BIN (autobin), cache);
|
||||
gst_bin_add (GST_BIN (autobin), typefind);
|
||||
|
||||
gst_element_link_pads (cache, "src", typefind, "sink");
|
||||
gst_element_add_ghost_pad (autobin, gst_element_get_pad (cache, "sink"), "sink");
|
||||
gst_element_add_ghost_pad (autobin, gst_element_get_pad (cache, "sink"),
|
||||
"sink");
|
||||
|
||||
gst_bin_add (GST_BIN( pipeline), autobin);
|
||||
gst_bin_add (GST_BIN (pipeline), autobin);
|
||||
gst_element_link_pads (filesrc, "src", autobin, "sink");
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state( GST_ELEMENT (pipeline), GST_STATE_PLAYING);
|
||||
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
|
||||
|
||||
while (gst_bin_iterate (GST_BIN (pipeline)));
|
||||
|
||||
|
@ -130,6 +129,5 @@ main (int argc, char *argv[])
|
|||
|
||||
gst_object_unref (GST_OBJECT (pipeline));
|
||||
|
||||
exit(0);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *pipeline;
|
||||
GstElement *filesrc;
|
||||
|
@ -15,20 +15,22 @@ main (int argc, char *argv[])
|
|||
return -1;
|
||||
}
|
||||
|
||||
pipeline = (GstElement*) gst_parse_launch ("filesrc name=my_filesrc ! mad ! osssink", &error);
|
||||
pipeline =
|
||||
(GstElement *)
|
||||
gst_parse_launch ("filesrc name=my_filesrc ! mad ! osssink", &error);
|
||||
if (!pipeline) {
|
||||
fprintf (stderr, "Parse error: %s", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
filesrc = gst_bin_get_by_name (GST_BIN (pipeline), "my_filesrc");
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
while (gst_bin_iterate (GST_BIN (pipeline)));
|
||||
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -24,88 +24,90 @@
|
|||
/*#define AUTOPLUG * define if you want autoplugging of input channels * */
|
||||
/* function prototypes */
|
||||
|
||||
input_channel_t* create_input_channel (int id, char* location);
|
||||
void destroy_input_channel (input_channel_t *pipe);
|
||||
void env_register_cp (GstElement *volenv, double cp_time, double cp_level);
|
||||
input_channel_t *create_input_channel (int id, char *location);
|
||||
void destroy_input_channel (input_channel_t * pipe);
|
||||
void env_register_cp (GstElement * volenv, double cp_time, double cp_level);
|
||||
|
||||
|
||||
gboolean playing;
|
||||
|
||||
|
||||
/* eos will be called when the src element has an end of stream */
|
||||
void eos(GstElement *element)
|
||||
void
|
||||
eos (GstElement * element)
|
||||
{
|
||||
g_print("have eos, quitting ?\n");
|
||||
g_print ("have eos, quitting ?\n");
|
||||
|
||||
/* playing = FALSE; */
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static GstCaps*
|
||||
gst_play_type_find (GstBin *bin, GstElement *element)
|
||||
G_GNUC_UNUSED static GstCaps *
|
||||
gst_play_type_find (GstBin * bin, GstElement * element)
|
||||
{
|
||||
GstElement *typefind;
|
||||
GstElement *pipeline;
|
||||
GstCaps *caps = NULL;
|
||||
|
||||
GST_DEBUG ("GstPipeline: typefind for element \"%s\"",
|
||||
GST_ELEMENT_NAME(element));
|
||||
GST_ELEMENT_NAME (element));
|
||||
|
||||
pipeline = gst_pipeline_new ("autoplug_pipeline");
|
||||
|
||||
|
||||
typefind = gst_element_factory_make ("typefind", "typefind");
|
||||
g_return_val_if_fail (typefind != NULL, FALSE);
|
||||
|
||||
gst_pad_link (gst_element_get_pad (element, "src"),
|
||||
gst_element_get_pad (typefind, "sink"));
|
||||
gst_element_get_pad (typefind, "sink"));
|
||||
gst_bin_add (bin, typefind);
|
||||
gst_bin_add (GST_BIN (pipeline), GST_ELEMENT (bin));
|
||||
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
|
||||
/* push a buffer... the have_type signal handler will set the found flag */
|
||||
gst_bin_iterate (GST_BIN (pipeline));
|
||||
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
|
||||
caps = gst_pad_get_caps (gst_element_get_pad (element, "src"));
|
||||
|
||||
gst_pad_unlink (gst_element_get_pad (element, "src"),
|
||||
gst_element_get_pad (typefind, "sink"));
|
||||
gst_element_get_pad (typefind, "sink"));
|
||||
gst_bin_remove (bin, typefind);
|
||||
gst_bin_remove (GST_BIN (pipeline), GST_ELEMENT (bin));
|
||||
gst_object_unref (GST_OBJECT (typefind));
|
||||
gst_object_unref (GST_OBJECT (pipeline));
|
||||
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int i, j;
|
||||
int num_channels;
|
||||
|
||||
|
||||
char buffer[20];
|
||||
|
||||
GList *input_channels; /* structure holding all the input channels */
|
||||
|
||||
|
||||
GList *input_channels; /* structure holding all the input channels */
|
||||
|
||||
input_channel_t *channel_in;
|
||||
|
||||
|
||||
GstElement *main_bin;
|
||||
GstElement *adder;
|
||||
GstElement *audiosink;
|
||||
|
||||
GstPad *pad; /* to request pads for the adder */
|
||||
GstPad *pad; /* to request pads for the adder */
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
if (argc == 1) {
|
||||
g_print("usage: %s <filename1> <filename2> <...>\n", argv[0]);
|
||||
exit(-1);
|
||||
g_print ("usage: %s <filename1> <filename2> <...>\n", argv[0]);
|
||||
exit (-1);
|
||||
}
|
||||
num_channels = argc - 1;
|
||||
|
||||
|
||||
/* set up output channel and main bin */
|
||||
|
||||
|
||||
/* create adder */
|
||||
adder = gst_element_factory_make ("adder", "adderel");
|
||||
|
||||
|
@ -113,33 +115,33 @@ int main(int argc,char *argv[])
|
|||
audiosink = gst_element_factory_make ("esdsink", "play_audio");
|
||||
|
||||
/* create main bin */
|
||||
main_bin = gst_pipeline_new("bin");
|
||||
main_bin = gst_pipeline_new ("bin");
|
||||
|
||||
/* link adder and output to bin */
|
||||
GST_INFO ( "main: adding adder to bin");
|
||||
gst_bin_add (GST_BIN(main_bin), adder);
|
||||
GST_INFO ( "main: adding audiosink to bin");
|
||||
gst_bin_add (GST_BIN(main_bin), audiosink);
|
||||
GST_INFO ("main: adding adder to bin");
|
||||
gst_bin_add (GST_BIN (main_bin), adder);
|
||||
GST_INFO ("main: adding audiosink to bin");
|
||||
gst_bin_add (GST_BIN (main_bin), audiosink);
|
||||
|
||||
/* link adder and audiosink */
|
||||
|
||||
gst_pad_link(gst_element_get_pad(adder,"src"),
|
||||
gst_element_get_pad(audiosink,"sink"));
|
||||
|
||||
gst_pad_link (gst_element_get_pad (adder, "src"),
|
||||
gst_element_get_pad (audiosink, "sink"));
|
||||
|
||||
/* start looping */
|
||||
input_channels = NULL;
|
||||
|
||||
for (i = 1; i < argc; ++i)
|
||||
{
|
||||
|
||||
for (i = 1; i < argc; ++i) {
|
||||
printf ("Opening channel %d from file %s...\n", i, argv[i]);
|
||||
channel_in = create_input_channel (i, argv[i]);
|
||||
input_channels = g_list_append (input_channels, channel_in);
|
||||
|
||||
if (i > 1) gst_element_set_state (main_bin, GST_STATE_PAUSED);
|
||||
gst_bin_add (GST_BIN(main_bin), channel_in->pipe);
|
||||
if (i > 1)
|
||||
gst_element_set_state (main_bin, GST_STATE_PAUSED);
|
||||
gst_bin_add (GST_BIN (main_bin), channel_in->pipe);
|
||||
|
||||
/* request pads and link to adder */
|
||||
GST_INFO ( "requesting pad\n");
|
||||
GST_INFO ("requesting pad\n");
|
||||
pad = gst_element_get_request_pad (adder, "sink%d");
|
||||
printf ("\tGot new adder sink pad %s\n", gst_pad_get_name (pad));
|
||||
sprintf (buffer, "channel%d", i);
|
||||
|
@ -155,78 +157,71 @@ int main(int argc,char *argv[])
|
|||
* at a level ensuring no distortion
|
||||
* example for three songs :
|
||||
* song1 : starts at full level, plays 5 seconds, faded out at 10 seconds,
|
||||
* sleep until 25, fade to end level at 30
|
||||
* sleep until 25, fade to end level at 30
|
||||
* song2 : starts silent, fades in at 5 seconds, full blast at 10 seconds,
|
||||
* full level until 15, faded out at 20, sleep until 25, fade to end at 30
|
||||
* full level until 15, faded out at 20, sleep until 25, fade to end at 30
|
||||
* song3 : starts muted, fades in from 15, full at 20, until 25, fade to end level
|
||||
*/
|
||||
|
||||
if (i == 1)
|
||||
{
|
||||
if (i == 1) {
|
||||
/* first song gets special treatment for end style */
|
||||
env_register_cp (channel_in->volenv, 0.0, 1.0);
|
||||
env_register_cp (channel_in->volenv, 0.0, 1.0);
|
||||
} else {
|
||||
env_register_cp (channel_in->volenv, 0.0, 0.0000001); /* start muted */
|
||||
env_register_cp (channel_in->volenv, i * 10.0 - 15.0, 0.0000001); /* start fade in */
|
||||
env_register_cp (channel_in->volenv, i * 10.0 - 10.0, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
env_register_cp (channel_in->volenv, 0.0 , 0.0000001); /* start muted */
|
||||
env_register_cp (channel_in->volenv, i * 10.0 - 15.0, 0.0000001); /* start fade in */
|
||||
env_register_cp (channel_in->volenv, i * 10.0 - 10.0, 1.0);
|
||||
}
|
||||
env_register_cp (channel_in->volenv, i * 10.0 - 5.0, 1.0); /* end of full level */
|
||||
env_register_cp (channel_in->volenv, i * 10.0 - 5.0, 1.0); /* end of full level */
|
||||
|
||||
if (i != num_channels)
|
||||
{
|
||||
env_register_cp (channel_in->volenv, i * 10.0 , 0.0000001); /* fade to black */
|
||||
env_register_cp (channel_in->volenv, num_channels * 10.0 - 5.0, 0.0000001); /* start fade in */
|
||||
}
|
||||
env_register_cp (channel_in->volenv, num_channels * 10.0 , 1.0 / num_channels); /* to end level */
|
||||
if (i != num_channels) {
|
||||
env_register_cp (channel_in->volenv, i * 10.0, 0.0000001); /* fade to black */
|
||||
env_register_cp (channel_in->volenv, num_channels * 10.0 - 5.0, 0.0000001); /* start fade in */
|
||||
}
|
||||
env_register_cp (channel_in->volenv, num_channels * 10.0, 1.0 / num_channels); /* to end level */
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
gst_xml_write_file (GST_ELEMENT (main_bin), fopen ("mixer.xml", "w"));
|
||||
#endif
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state(main_bin, GST_STATE_PLAYING);
|
||||
gst_element_set_state (main_bin, GST_STATE_PLAYING);
|
||||
|
||||
/* write out the schedule */
|
||||
gst_scheduler_show(GST_ELEMENT_SCHED(main_bin));
|
||||
gst_scheduler_show (GST_ELEMENT_SCHED (main_bin));
|
||||
playing = TRUE;
|
||||
|
||||
j = 0;
|
||||
/*printf ("main: start iterating from 0"); */
|
||||
while (playing && j < 100)
|
||||
{
|
||||
while (playing && j < 100) {
|
||||
/* printf ("main: iterating %d\n", j); */
|
||||
gst_bin_iterate(GST_BIN(main_bin));
|
||||
/*fprintf(stderr,"after iterate()\n"); */
|
||||
gst_bin_iterate (GST_BIN (main_bin));
|
||||
/*fprintf(stderr,"after iterate()\n"); */
|
||||
++j;
|
||||
}
|
||||
}
|
||||
printf ("main: all the channels are open\n");
|
||||
while (playing)
|
||||
{
|
||||
gst_bin_iterate(GST_BIN(main_bin));
|
||||
while (playing) {
|
||||
gst_bin_iterate (GST_BIN (main_bin));
|
||||
/*fprintf(stderr,"after iterate()\n"); */
|
||||
}
|
||||
/* stop the bin */
|
||||
gst_element_set_state(main_bin, GST_STATE_NULL);
|
||||
gst_element_set_state (main_bin, GST_STATE_NULL);
|
||||
|
||||
while (input_channels)
|
||||
{
|
||||
while (input_channels) {
|
||||
destroy_input_channel (input_channels->data);
|
||||
input_channels = g_list_next (input_channels);
|
||||
}
|
||||
g_list_free (input_channels);
|
||||
|
||||
gst_object_unref(GST_OBJECT(audiosink));
|
||||
|
||||
gst_object_unref(GST_OBJECT(main_bin));
|
||||
gst_object_unref (GST_OBJECT (audiosink));
|
||||
|
||||
exit(0);
|
||||
gst_object_unref (GST_OBJECT (main_bin));
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
input_channel_t*
|
||||
create_input_channel (int id, char* location)
|
||||
input_channel_t *
|
||||
create_input_channel (int id, char *location)
|
||||
{
|
||||
/* create an input channel, reading from location
|
||||
* return a pointer to the channel
|
||||
|
@ -234,51 +229,48 @@ create_input_channel (int id, char* location)
|
|||
*/
|
||||
|
||||
input_channel_t *channel;
|
||||
|
||||
char buffer[20]; /* hold the names */
|
||||
|
||||
char buffer[20]; /* hold the names */
|
||||
|
||||
/* GstAutoplug *autoplug;
|
||||
GstCaps *srccaps; */
|
||||
GstElement *new_element;
|
||||
GstElement *new_element;
|
||||
GstElement *decoder;
|
||||
|
||||
GST_DEBUG ( "c_i_p : creating channel with id %d for file %s",
|
||||
id, location);
|
||||
|
||||
GST_DEBUG ("c_i_p : creating channel with id %d for file %s", id, location);
|
||||
|
||||
/* allocate channel */
|
||||
|
||||
channel = (input_channel_t *) malloc (sizeof (input_channel_t));
|
||||
if (channel == NULL)
|
||||
{
|
||||
if (channel == NULL) {
|
||||
printf ("create_input_channel : could not allocate memory for channel !\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create channel */
|
||||
|
||||
GST_DEBUG ( "c_i_p : creating pipeline");
|
||||
GST_DEBUG ("c_i_p : creating pipeline");
|
||||
|
||||
sprintf (buffer, "pipeline%d", id);
|
||||
channel->pipe = gst_bin_new (buffer);
|
||||
g_assert(channel->pipe != NULL);
|
||||
|
||||
g_assert (channel->pipe != NULL);
|
||||
|
||||
/* create elements */
|
||||
|
||||
GST_DEBUG ( "c_i_p : creating filesrc");
|
||||
GST_DEBUG ("c_i_p : creating filesrc");
|
||||
|
||||
sprintf (buffer, "filesrc%d", id);
|
||||
channel->filesrc = gst_element_factory_make ("filesrc", buffer);
|
||||
g_assert(channel->filesrc != NULL);
|
||||
g_assert (channel->filesrc != NULL);
|
||||
|
||||
GST_DEBUG ( "c_i_p : setting location");
|
||||
g_object_set(G_OBJECT(channel->filesrc),"location", location, NULL);
|
||||
GST_DEBUG ("c_i_p : setting location");
|
||||
g_object_set (G_OBJECT (channel->filesrc), "location", location, NULL);
|
||||
|
||||
/* add filesrc to the bin before autoplug */
|
||||
gst_bin_add(GST_BIN(channel->pipe), channel->filesrc);
|
||||
gst_bin_add (GST_BIN (channel->pipe), channel->filesrc);
|
||||
|
||||
/* link signal to eos of filesrc */
|
||||
g_signal_connect (G_OBJECT(channel->filesrc),"eos",
|
||||
G_CALLBACK(eos),NULL);
|
||||
g_signal_connect (G_OBJECT (channel->filesrc), "eos", G_CALLBACK (eos), NULL);
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -287,7 +279,7 @@ create_input_channel (int id, char* location)
|
|||
|
||||
sprintf (buffer, "volenv%d", id);
|
||||
channel->volenv = gst_element_factory_make ("volenv", buffer);
|
||||
g_assert(channel->volenv != NULL);
|
||||
g_assert (channel->volenv != NULL);
|
||||
|
||||
/* autoplug the pipe */
|
||||
|
||||
|
@ -308,7 +300,7 @@ create_input_channel (int id, char* location)
|
|||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
gst_bin_remove (GST_BIN (pipeline), channel->pipe);
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -317,7 +309,6 @@ create_input_channel (int id, char* location)
|
|||
g_print ("could not autoplug, unknown media type...\n");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("DEBUG : c_i_p : creating autoplug\n");
|
||||
#endif
|
||||
|
@ -328,51 +319,49 @@ create_input_channel (int id, char* location)
|
|||
#ifdef DEBUG
|
||||
printf ("DEBUG : c_i_p : autoplugging\n");
|
||||
#endif
|
||||
|
||||
new_element = gst_autoplug_to_caps (autoplug, srccaps,
|
||||
gst_caps_new ("audio/raw", NULL), NULL);
|
||||
|
||||
|
||||
new_element = gst_autoplug_to_caps (autoplug, srccaps,
|
||||
gst_caps_new ("audio/raw", NULL), NULL);
|
||||
|
||||
if (!new_element) {
|
||||
g_print ("could not autoplug, no suitable codecs found...\n");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
new_element = gst_bin_new ("autoplug_bin");
|
||||
|
||||
/* static plug, use mad plugin and assume mp3 input */
|
||||
printf ("using static plugging for input channel\n");
|
||||
decoder = gst_element_factory_make ("mad", "mpg123");
|
||||
if (!decoder)
|
||||
{
|
||||
decoder = gst_element_factory_make ("mad", "mpg123");
|
||||
if (!decoder) {
|
||||
fprintf (stderr, "Could not get a decoder element !\n");
|
||||
exit (1);
|
||||
}
|
||||
gst_bin_add (GST_BIN (new_element), decoder);
|
||||
|
||||
gst_element_add_ghost_pad (new_element,
|
||||
gst_element_get_pad (decoder, "sink"), "sink");
|
||||
gst_element_add_ghost_pad (new_element,
|
||||
gst_element_get_pad (decoder, "src"), "src_00");
|
||||
|
||||
#endif
|
||||
gst_element_add_ghost_pad (new_element,
|
||||
gst_element_get_pad (decoder, "sink"), "sink");
|
||||
gst_element_add_ghost_pad (new_element,
|
||||
gst_element_get_pad (decoder, "src"), "src_00");
|
||||
|
||||
#endif
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
gst_xml_write_file (GST_ELEMENT (new_element), fopen ("mixer.gst", "w"));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
gst_bin_add (GST_BIN(channel->pipe), channel->volenv);
|
||||
gst_bin_add (GST_BIN (channel->pipe), channel->volenv);
|
||||
gst_bin_add (GST_BIN (channel->pipe), new_element);
|
||||
|
||||
|
||||
gst_element_link_pads (channel->filesrc, "src", new_element, "sink");
|
||||
gst_element_link_pads (new_element, "src_00", channel->volenv, "sink");
|
||||
|
||||
|
||||
/* add a ghost pad */
|
||||
sprintf (buffer, "channel%d", id);
|
||||
gst_element_add_ghost_pad (channel->pipe,
|
||||
gst_element_get_pad (channel->volenv, "src"), buffer);
|
||||
gst_element_get_pad (channel->volenv, "src"), buffer);
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("DEBUG : c_i_p : end function\n");
|
||||
#endif
|
||||
|
@ -381,12 +370,12 @@ create_input_channel (int id, char* location)
|
|||
}
|
||||
|
||||
void
|
||||
destroy_input_channel (input_channel_t *channel)
|
||||
destroy_input_channel (input_channel_t * channel)
|
||||
{
|
||||
/*
|
||||
* destroy an input channel
|
||||
*/
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("DEBUG : d_i_p : start\n");
|
||||
#endif
|
||||
|
@ -398,11 +387,12 @@ destroy_input_channel (input_channel_t *channel)
|
|||
free (channel);
|
||||
}
|
||||
|
||||
void env_register_cp (GstElement *volenv, double cp_time, double cp_level)
|
||||
void
|
||||
env_register_cp (GstElement * volenv, double cp_time, double cp_level)
|
||||
{
|
||||
char buffer[30];
|
||||
|
||||
sprintf (buffer, "%f:%f", cp_time, cp_level);
|
||||
g_object_set(G_OBJECT(volenv), "controlpoint", buffer, NULL);
|
||||
g_object_set (G_OBJECT (volenv), "controlpoint", buffer, NULL);
|
||||
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* thomas@apestaart.org
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
GstElement *pipe, *filesrc, *volenv;
|
||||
|
||||
|
||||
char *location;
|
||||
int channel_id;
|
||||
} input_channel_t;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
|
||||
static GstElement*
|
||||
static GstElement *
|
||||
make_bin (gint count)
|
||||
{
|
||||
GstElement *bin;
|
||||
|
@ -42,7 +42,7 @@ make_bin (gint count)
|
|||
}
|
||||
|
||||
gint
|
||||
main (gint argc, gchar *argv[])
|
||||
main (gint argc, gchar * argv[])
|
||||
{
|
||||
GstElement *pipeline;
|
||||
GstElement *aggregator, *sink;
|
||||
|
@ -53,9 +53,9 @@ main (gint argc, gchar *argv[])
|
|||
gst_init (&argc, &argv);
|
||||
|
||||
pipeline = gst_pipeline_new ("main");
|
||||
g_signal_connect (pipeline, "deep_notify",
|
||||
G_CALLBACK (gst_element_default_deep_notify), NULL);
|
||||
|
||||
g_signal_connect (pipeline, "deep_notify",
|
||||
G_CALLBACK (gst_element_default_deep_notify), NULL);
|
||||
|
||||
aggregator = gst_element_factory_make ("aggregator", "mixer");
|
||||
sink = gst_element_factory_make ("fakesink", "sink");
|
||||
|
||||
|
@ -85,7 +85,7 @@ main (gint argc, gchar *argv[])
|
|||
i = 4;
|
||||
while (i--)
|
||||
gst_bin_iterate (GST_BIN (pipeline));
|
||||
|
||||
|
||||
g_print ("playing bin1\n");
|
||||
gst_element_set_state (bin1, GST_STATE_PLAYING);
|
||||
|
||||
|
|
|
@ -27,18 +27,18 @@
|
|||
* plugin, as well as author and version data. Use the GST_ELEMENT_DETAILS
|
||||
* macro when defining it.
|
||||
*/
|
||||
static GstElementDetails example_details = GST_ELEMENT_DETAILS (
|
||||
"An example plugin",
|
||||
"Example/FirstExample",
|
||||
"Shows the basic structure of a plugin",
|
||||
"your name <your.name@your.isp>"
|
||||
);
|
||||
static GstElementDetails example_details =
|
||||
GST_ELEMENT_DETAILS ("An example plugin",
|
||||
"Example/FirstExample",
|
||||
"Shows the basic structure of a plugin",
|
||||
"your name <your.name@your.isp>");
|
||||
|
||||
/* These are the signals that this element can fire. They are zero-
|
||||
* based because the numbers themselves are private to the object.
|
||||
* LAST_SIGNAL is used for initialization of the signal array.
|
||||
*/
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ASDF,
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
|
@ -47,51 +47,46 @@ enum {
|
|||
/* Arguments are identified the same way, but cannot be zero, so you
|
||||
* must leave the ARG_0 entry in as a placeholder.
|
||||
*/
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_ACTIVE
|
||||
/* FILL ME */
|
||||
/* FILL ME */
|
||||
};
|
||||
|
||||
/* The PadFactory structures describe what pads the element has or
|
||||
* can have. They can be quite complex, but for this example plugin
|
||||
* they are rather simple.
|
||||
*/
|
||||
GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE (
|
||||
"sink", /* The name of the pad */
|
||||
GST_PAD_SINK, /* Direction of the pad */
|
||||
GST_PAD_ALWAYS, /* The pad exists for every instance */
|
||||
GST_STATIC_CAPS (
|
||||
"unknown/unknown, " /* The MIME media type */
|
||||
"foo:int=1, " /* an integer property */
|
||||
"bar:boolean=true, " /* a boolean property */
|
||||
"baz:int={ 1, 3 }" /* a list of values */
|
||||
)
|
||||
);
|
||||
GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", /* The name of the pad */
|
||||
GST_PAD_SINK, /* Direction of the pad */
|
||||
GST_PAD_ALWAYS, /* The pad exists for every instance */
|
||||
GST_STATIC_CAPS ("unknown/unknown, " /* The MIME media type */
|
||||
"foo:int=1, " /* an integer property */
|
||||
"bar:boolean=true, " /* a boolean property */
|
||||
"baz:int={ 1, 3 }" /* a list of values */
|
||||
)
|
||||
);
|
||||
|
||||
/* This factory is much simpler, and defines the source pad. */
|
||||
GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE (
|
||||
"src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (
|
||||
"unknown/unknown"
|
||||
)
|
||||
);
|
||||
GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("unknown/unknown")
|
||||
);
|
||||
|
||||
|
||||
/* A number of functon prototypes are given so we can refer to them later. */
|
||||
static void gst_example_class_init (GstExampleClass *klass);
|
||||
static void gst_example_init (GstExample *example);
|
||||
static void gst_example_class_init (GstExampleClass * klass);
|
||||
static void gst_example_init (GstExample * example);
|
||||
|
||||
static void gst_example_chain (GstPad *pad, GstData *_data);
|
||||
static void gst_example_chain (GstPad * pad, GstData * _data);
|
||||
|
||||
static void gst_example_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_example_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
static GstElementStateReturn
|
||||
gst_example_change_state (GstElement *element);
|
||||
static void gst_example_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_example_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
static GstElementStateReturn gst_example_change_state (GstElement * element);
|
||||
|
||||
/* The parent class pointer needs to be kept around for some object
|
||||
* operations.
|
||||
|
@ -109,23 +104,25 @@ static guint gst_example_signals[LAST_SIGNAL] = { 0 };
|
|||
* and pointers to the various functions that define the class.
|
||||
*/
|
||||
GType
|
||||
gst_example_get_type(void)
|
||||
gst_example_get_type (void)
|
||||
{
|
||||
static GType example_type = 0;
|
||||
|
||||
if (!example_type) {
|
||||
static const GTypeInfo example_info = {
|
||||
sizeof(GstExampleClass),
|
||||
sizeof (GstExampleClass),
|
||||
NULL,
|
||||
NULL,
|
||||
(GClassInitFunc)gst_example_class_init,
|
||||
(GClassInitFunc) gst_example_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(GstExample),
|
||||
sizeof (GstExample),
|
||||
0,
|
||||
(GInstanceInitFunc)gst_example_init,
|
||||
(GInstanceInitFunc) gst_example_init,
|
||||
};
|
||||
example_type = g_type_register_static(GST_TYPE_ELEMENT, "GstExample", &example_info, 0);
|
||||
example_type =
|
||||
g_type_register_static (GST_TYPE_ELEMENT, "GstExample", &example_info,
|
||||
0);
|
||||
}
|
||||
return example_type;
|
||||
}
|
||||
|
@ -135,7 +132,7 @@ gst_example_get_type(void)
|
|||
* it, based on the pointer to the function provided above.
|
||||
*/
|
||||
static void
|
||||
gst_example_class_init (GstExampleClass *klass)
|
||||
gst_example_class_init (GstExampleClass * klass)
|
||||
{
|
||||
/* Class pointers are needed to supply pointers to the private
|
||||
* implementations of parent class methods.
|
||||
|
@ -146,27 +143,24 @@ gst_example_class_init (GstExampleClass *klass)
|
|||
/* Since the example class contains the parent classes, you can simply
|
||||
* cast the pointer to get access to the parent classes.
|
||||
*/
|
||||
gobject_class = (GObjectClass*)klass;
|
||||
gstelement_class = (GstElementClass*)klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
/* The parent class is needed for class method overrides. */
|
||||
parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
|
||||
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
|
||||
|
||||
/* Here we add an argument to the object. This argument is an integer,
|
||||
* and can be both read and written.
|
||||
*/
|
||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ACTIVE,
|
||||
g_param_spec_int("active","active","active",
|
||||
G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); /* CHECKME */
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ACTIVE, g_param_spec_int ("active", "active", "active", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE)); /* CHECKME */
|
||||
|
||||
/* Here we add a signal to the object. This is avery useless signal
|
||||
* called asdf. The signal will also pass a pointer to the listeners
|
||||
* which happens to be the example element itself */
|
||||
gst_example_signals[ASDF] =
|
||||
g_signal_new("asdf", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstExampleClass, asdf), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
|
||||
GST_TYPE_EXAMPLE);
|
||||
g_signal_new ("asdf", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstExampleClass, asdf), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, GST_TYPE_EXAMPLE);
|
||||
|
||||
|
||||
/* The last thing is to provide the functions that implement get and set
|
||||
|
@ -193,31 +187,33 @@ gst_example_class_init (GstExampleClass *klass)
|
|||
* the plugin.
|
||||
*/
|
||||
static void
|
||||
gst_example_init(GstExample *example)
|
||||
gst_example_init (GstExample * example)
|
||||
{
|
||||
/* First we create the sink pad, which is the input to the element.
|
||||
* We will use the template constructed by the factory.
|
||||
*/
|
||||
example->sinkpad = gst_pad_new_from_template (
|
||||
gst_static_pad_template_get (&sink_template), "sink");
|
||||
example->sinkpad =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get (&sink_template),
|
||||
"sink");
|
||||
/* Setting the chain function allows us to supply the function that will
|
||||
* actually be performing the work. Without this, the element would do
|
||||
* nothing, with undefined results (assertion failures and such).
|
||||
*/
|
||||
gst_pad_set_chain_function(example->sinkpad,gst_example_chain);
|
||||
gst_pad_set_chain_function (example->sinkpad, gst_example_chain);
|
||||
/* We then must add this pad to the element's list of pads. The base
|
||||
* element class manages the list of pads, and provides accessors to it.
|
||||
*/
|
||||
gst_element_add_pad(GST_ELEMENT(example),example->sinkpad);
|
||||
gst_element_add_pad (GST_ELEMENT (example), example->sinkpad);
|
||||
|
||||
/* The src pad, the output of the element, is created and registered
|
||||
* in the same way, with the exception of the chain function. Source
|
||||
* pads don't have chain functions, because they can't accept buffers,
|
||||
* they only produce them.
|
||||
*/
|
||||
example->srcpad = gst_pad_new_from_template (
|
||||
gst_static_pad_template_get (&src_template), "src");
|
||||
gst_element_add_pad(GST_ELEMENT(example),example->srcpad);
|
||||
example->srcpad =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get (&src_template),
|
||||
"src");
|
||||
gst_element_add_pad (GST_ELEMENT (example), example->srcpad);
|
||||
|
||||
/* Initialization of element's private variables. */
|
||||
example->active = FALSE;
|
||||
|
@ -228,7 +224,7 @@ gst_example_init(GstExample *example)
|
|||
* as the buffer provided by the peer element.
|
||||
*/
|
||||
static void
|
||||
gst_example_chain (GstPad *pad, GstData *_data)
|
||||
gst_example_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
GstBuffer *buf = GST_BUFFER (_data);
|
||||
GstExample *example;
|
||||
|
@ -237,34 +233,35 @@ gst_example_chain (GstPad *pad, GstData *_data)
|
|||
/* Some of these checks are of dubious value, since if there were not
|
||||
* already true, the chain function would never be called.
|
||||
*/
|
||||
g_return_if_fail(pad != NULL);
|
||||
g_return_if_fail(GST_IS_PAD(pad));
|
||||
g_return_if_fail(buf != NULL);
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_PAD (pad));
|
||||
g_return_if_fail (buf != NULL);
|
||||
|
||||
/* We need to get a pointer to the element this pad belogs to. */
|
||||
example = GST_EXAMPLE(gst_pad_get_parent (pad));
|
||||
example = GST_EXAMPLE (gst_pad_get_parent (pad));
|
||||
|
||||
/* A few more sanity checks to make sure that the element that owns
|
||||
* this pad is the right kind of element, in case something got confused.
|
||||
*/
|
||||
g_return_if_fail(example != NULL);
|
||||
g_return_if_fail(GST_IS_EXAMPLE(example));
|
||||
g_return_if_fail (example != NULL);
|
||||
g_return_if_fail (GST_IS_EXAMPLE (example));
|
||||
|
||||
/* If we are supposed to be doing something, here's where it happens. */
|
||||
if (example->active) {
|
||||
/* In this example we're going to copy the buffer to another one,
|
||||
* so we need to allocate a new buffer first. */
|
||||
outbuf = gst_buffer_new();
|
||||
outbuf = gst_buffer_new ();
|
||||
|
||||
/* We need to copy the size and offset of the buffer at a minimum. */
|
||||
GST_BUFFER_SIZE (outbuf) = GST_BUFFER_SIZE (buf);
|
||||
GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buf);
|
||||
|
||||
/* Then allocate the memory for the new buffer */
|
||||
GST_BUFFER_DATA (outbuf) = (guchar *)g_malloc (GST_BUFFER_SIZE (outbuf));
|
||||
GST_BUFFER_DATA (outbuf) = (guchar *) g_malloc (GST_BUFFER_SIZE (outbuf));
|
||||
|
||||
/* Then copy the data in the incoming buffer into the new buffer. */
|
||||
memcpy (GST_BUFFER_DATA (outbuf), GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (outbuf));
|
||||
memcpy (GST_BUFFER_DATA (outbuf), GST_BUFFER_DATA (buf),
|
||||
GST_BUFFER_SIZE (outbuf));
|
||||
|
||||
/* we don't need the incomming buffer anymore so we unref it. When we are
|
||||
* the last plugin with a handle to the buffer, its memory will be freed */
|
||||
|
@ -274,15 +271,14 @@ gst_example_chain (GstPad *pad, GstData *_data)
|
|||
* in the pipeline, through the element's source pad, which is stored
|
||||
* in the element's structure.
|
||||
*/
|
||||
gst_pad_push(example->srcpad,GST_DATA (outbuf));
|
||||
gst_pad_push (example->srcpad, GST_DATA (outbuf));
|
||||
|
||||
/* For fun we'll emit our useless signal here */
|
||||
g_signal_emit(G_OBJECT (example), gst_example_signals[ASDF], 0,
|
||||
example);
|
||||
g_signal_emit (G_OBJECT (example), gst_example_signals[ASDF], 0, example);
|
||||
|
||||
/* If we're not doing something, just send the original incoming buffer. */
|
||||
/* If we're not doing something, just send the original incoming buffer. */
|
||||
} else {
|
||||
gst_pad_push(example->srcpad,GST_DATA (buf));
|
||||
gst_pad_push (example->srcpad, GST_DATA (buf));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,15 +286,16 @@ gst_example_chain (GstPad *pad, GstData *_data)
|
|||
* enable the element to respond to various arguments.
|
||||
*/
|
||||
static void
|
||||
gst_example_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
gst_example_set_property (GObject * object, guint prop_id, const GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstExample *example;
|
||||
|
||||
/* It's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail(GST_IS_EXAMPLE(object));
|
||||
g_return_if_fail (GST_IS_EXAMPLE (object));
|
||||
|
||||
/* Get a pointer of the right type. */
|
||||
example = GST_EXAMPLE(object);
|
||||
example = GST_EXAMPLE (object);
|
||||
|
||||
/* Check the argument id to see which argument we're setting. */
|
||||
switch (prop_id) {
|
||||
|
@ -309,7 +306,7 @@ gst_example_set_property (GObject *object, guint prop_id, const GValue *value, G
|
|||
* is running, if you are using threads.
|
||||
*/
|
||||
example->active = g_value_get_int (value);
|
||||
g_print("example: set active to %d\n",example->active);
|
||||
g_print ("example: set active to %d\n", example->active);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -318,13 +315,14 @@ gst_example_set_property (GObject *object, guint prop_id, const GValue *value, G
|
|||
|
||||
/* The set function is simply the inverse of the get fuction. */
|
||||
static void
|
||||
gst_example_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
gst_example_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstExample *example;
|
||||
|
||||
/* It's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail(GST_IS_EXAMPLE(object));
|
||||
example = GST_EXAMPLE(object);
|
||||
g_return_if_fail (GST_IS_EXAMPLE (object));
|
||||
example = GST_EXAMPLE (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_ACTIVE:
|
||||
|
@ -342,38 +340,38 @@ gst_example_get_property (GObject *object, guint prop_id, GValue *value, GParamS
|
|||
* in the various state transitions.
|
||||
*/
|
||||
static GstElementStateReturn
|
||||
gst_example_change_state (GstElement *element)
|
||||
gst_example_change_state (GstElement * element)
|
||||
{
|
||||
GstExample *example;
|
||||
|
||||
|
||||
/* cast to our plugin */
|
||||
example = GST_EXAMPLE(element);
|
||||
|
||||
example = GST_EXAMPLE (element);
|
||||
|
||||
/* we perform our actions based on the state transition
|
||||
* of the element */
|
||||
switch (GST_STATE_TRANSITION (element)) {
|
||||
/* The NULL to READY transition is used to
|
||||
* create threads (if any) */
|
||||
/* The NULL to READY transition is used to
|
||||
* create threads (if any) */
|
||||
case GST_STATE_NULL_TO_READY:
|
||||
break;
|
||||
/* In the READY to PAUSED state, the element should
|
||||
* open devices (if any) */
|
||||
/* In the READY to PAUSED state, the element should
|
||||
* open devices (if any) */
|
||||
case GST_STATE_READY_TO_PAUSED:
|
||||
break;
|
||||
/* In the PAUSED to PLAYING state, the element should
|
||||
* prepare itself for operation or continue after a PAUSE */
|
||||
/* In the PAUSED to PLAYING state, the element should
|
||||
* prepare itself for operation or continue after a PAUSE */
|
||||
case GST_STATE_PAUSED_TO_PLAYING:
|
||||
break;
|
||||
/* In the PLAYING to PAUSED state, the element should
|
||||
* PAUSE itself and make sure it can resume operation */
|
||||
/* In the PLAYING to PAUSED state, the element should
|
||||
* PAUSE itself and make sure it can resume operation */
|
||||
case GST_STATE_PLAYING_TO_PAUSED:
|
||||
break;
|
||||
/* In the PAUSED to READY state, the element should reset
|
||||
* its internal state and close any devices. */
|
||||
/* In the PAUSED to READY state, the element should reset
|
||||
* its internal state and close any devices. */
|
||||
case GST_STATE_PAUSED_TO_READY:
|
||||
break;
|
||||
/* The element should free all resources, terminate threads
|
||||
* and put itself into its initial state again */
|
||||
/* The element should free all resources, terminate threads
|
||||
* and put itself into its initial state again */
|
||||
case GST_STATE_READY_TO_NULL:
|
||||
break;
|
||||
}
|
||||
|
@ -387,13 +385,14 @@ gst_example_change_state (GstElement *element)
|
|||
* this function is called to register everything that the plugin provides.
|
||||
*/
|
||||
static gboolean
|
||||
plugin_init (GstPlugin *plugin)
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
/* We need to register each element we provide with the plugin. This consists
|
||||
* of the name of the element, a rank that gives the importance of the element
|
||||
* when compared to similar plugins and the GType identifier.
|
||||
*/
|
||||
if (!gst_element_register (plugin, "example", GST_RANK_MARGINAL, GST_TYPE_EXAMPLE))
|
||||
if (!gst_element_register (plugin, "example", GST_RANK_MARGINAL,
|
||||
GST_TYPE_EXAMPLE))
|
||||
return FALSE;
|
||||
|
||||
/* Now we can return successfully. */
|
||||
|
@ -411,21 +410,19 @@ plugin_init (GstPlugin *plugin)
|
|||
* The symbol pointing to this structure is the only symbol looked up when
|
||||
* loading the plugin.
|
||||
*/
|
||||
GST_PLUGIN_DEFINE (
|
||||
GST_VERSION_MAJOR, /* The major version of the core that this was built with */
|
||||
GST_VERSION_MINOR, /* The minor version of the core that this was built with */
|
||||
"example", /* The name of the plugin. This must be unique: plugins with
|
||||
* the same name will be assumed to be identical, and only
|
||||
* one will be loaded. */
|
||||
"an example plugin", /* a short description of the plugin in English */
|
||||
plugin_init, /* Pointer to the initialisation function for the plugin. */
|
||||
"0.1", /* The version number of the plugin */
|
||||
"LGPL", /* ieffective license the plugin can be shipped with. Must be
|
||||
* valid for all libraries it links to, too. */
|
||||
"my nifty plugin package",
|
||||
/* package this plugin belongs to. */
|
||||
"http://www.mydomain.com"
|
||||
/* originating URL for this plugin. This is the place to look
|
||||
* for updates, information and so on. */
|
||||
);
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, /* The major version of the core that this was built with */
|
||||
GST_VERSION_MINOR, /* The minor version of the core that this was built with */
|
||||
"example", /* The name of the plugin. This must be unique: plugins with
|
||||
* the same name will be assumed to be identical, and only
|
||||
* one will be loaded. */
|
||||
"an example plugin", /* a short description of the plugin in English */
|
||||
plugin_init, /* Pointer to the initialisation function for the plugin. */
|
||||
"0.1", /* The version number of the plugin */
|
||||
"LGPL", /* ieffective license the plugin can be shipped with. Must be
|
||||
* valid for all libraries it links to, too. */
|
||||
"my nifty plugin package",
|
||||
/* package this plugin belongs to. */
|
||||
"http://www.mydomain.com"
|
||||
/* originating URL for this plugin. This is the place to look
|
||||
* for updates, information and so on. */
|
||||
);
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* This is the definition of the element's object structure. */
|
||||
typedef struct _GstExample GstExample;
|
||||
|
||||
|
@ -33,11 +32,12 @@ typedef struct _GstExample GstExample;
|
|||
* the beginning of the object. This allows the element to be cast to
|
||||
* an Element or even an Object.
|
||||
*/
|
||||
struct _GstExample {
|
||||
struct _GstExample
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
/* We need to keep track of our pads, so we do so here. */
|
||||
GstPad *sinkpad,*srcpad;
|
||||
GstPad *sinkpad, *srcpad;
|
||||
|
||||
/* We'll use this to decide whether to do anything to the data we get. */
|
||||
gboolean active;
|
||||
|
@ -49,11 +49,12 @@ struct _GstExample {
|
|||
* structure. */
|
||||
typedef struct _GstExampleClass GstExampleClass;
|
||||
|
||||
struct _GstExampleClass {
|
||||
struct _GstExampleClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*asdf) (GstElement *element, GstExample *example);
|
||||
void (*asdf) (GstElement * element, GstExample * example);
|
||||
};
|
||||
|
||||
/* Five standard preprocessing macros are used in the Gtk+ object system.
|
||||
|
@ -80,8 +81,7 @@ struct _GstExampleClass {
|
|||
/* This is the only prototype needed, because it is used in the above
|
||||
* GST_TYPE_EXAMPLE macro.
|
||||
*/
|
||||
GType gst_example_get_type(void);
|
||||
GType gst_example_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_EXAMPLE_H__ */
|
||||
|
|
|
@ -1,56 +1,56 @@
|
|||
#include <stdlib.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *filesrc, *osssink, *parse, *decode, *queue;
|
||||
GstElement *bin;
|
||||
GstElement *thread;
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
if (argc != 2) {
|
||||
g_print("usage: %s <filename>\n", argv[0]);
|
||||
exit(-1);
|
||||
g_print ("usage: %s <filename>\n", argv[0]);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* create a new thread to hold the elements */
|
||||
thread = gst_thread_new("thread");
|
||||
g_assert(thread != NULL);
|
||||
thread = gst_thread_new ("thread");
|
||||
g_assert (thread != NULL);
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
bin = gst_bin_new("bin");
|
||||
g_assert(bin != NULL);
|
||||
bin = gst_bin_new ("bin");
|
||||
g_assert (bin != NULL);
|
||||
|
||||
/* create a disk reader */
|
||||
filesrc = gst_element_factory_make("filesrc", "disk_source");
|
||||
g_assert(filesrc != NULL);
|
||||
g_object_set(G_OBJECT(filesrc),"location", argv[1],NULL);
|
||||
filesrc = gst_element_factory_make ("filesrc", "disk_source");
|
||||
g_assert (filesrc != NULL);
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
|
||||
parse = gst_element_factory_make("mp3parse", "parse");
|
||||
decode = gst_element_factory_make("mpg123", "decode");
|
||||
parse = gst_element_factory_make ("mp3parse", "parse");
|
||||
decode = gst_element_factory_make ("mpg123", "decode");
|
||||
|
||||
queue = gst_element_factory_make("queue", "queue");
|
||||
queue = gst_element_factory_make ("queue", "queue");
|
||||
|
||||
/* and an audio sink */
|
||||
osssink = gst_element_factory_make("osssink", "play_audio");
|
||||
g_assert(osssink != NULL);
|
||||
osssink = gst_element_factory_make ("osssink", "play_audio");
|
||||
g_assert (osssink != NULL);
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
gst_bin_add_many (GST_BIN (bin), filesrc, parse, decode, queue, NULL);
|
||||
|
||||
gst_bin_add(GST_BIN(thread), osssink);
|
||||
gst_bin_add(GST_BIN(bin), thread);
|
||||
gst_bin_add (GST_BIN (thread), osssink);
|
||||
gst_bin_add (GST_BIN (bin), thread);
|
||||
|
||||
gst_element_link_many (filesrc, parse, decode, queue, osssink, NULL);
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state(GST_ELEMENT(bin), GST_STATE_PLAYING);
|
||||
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
|
||||
|
||||
while (gst_bin_iterate(GST_BIN(bin)));
|
||||
while (gst_bin_iterate (GST_BIN (bin)));
|
||||
|
||||
gst_element_set_state(GST_ELEMENT(bin), GST_STATE_NULL);
|
||||
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
|
||||
|
||||
exit(0);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,78 +4,78 @@
|
|||
gboolean playing;
|
||||
|
||||
/* eos will be called when the src element has an end of stream */
|
||||
void eos(GstElement *element, gpointer data)
|
||||
void
|
||||
eos (GstElement * element, gpointer data)
|
||||
{
|
||||
g_print("have eos, quitting\n");
|
||||
g_print ("have eos, quitting\n");
|
||||
|
||||
playing = FALSE;
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *filesrc, *osssink, *queue;
|
||||
GstElement *pipeline;
|
||||
GstElement *thread;
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
if (argc != 2) {
|
||||
g_print("usage: %s <filename>\n", argv[0]);
|
||||
exit(-1);
|
||||
g_print ("usage: %s <filename>\n", argv[0]);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* create a new thread to hold the elements */
|
||||
thread = gst_thread_new("thread");
|
||||
g_assert(thread != NULL);
|
||||
thread = gst_thread_new ("thread");
|
||||
g_assert (thread != NULL);
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
pipeline = gst_pipeline_new("pipeline");
|
||||
g_assert(pipeline != NULL);
|
||||
pipeline = gst_pipeline_new ("pipeline");
|
||||
g_assert (pipeline != NULL);
|
||||
|
||||
/* create a disk reader */
|
||||
filesrc = gst_element_factory_make("filesrc", "disk_source");
|
||||
g_assert(filesrc != NULL);
|
||||
g_object_set(G_OBJECT(filesrc),"location", argv[1],NULL);
|
||||
g_signal_connect (G_OBJECT(filesrc),"eos",
|
||||
G_CALLBACK(eos), thread);
|
||||
filesrc = gst_element_factory_make ("filesrc", "disk_source");
|
||||
g_assert (filesrc != NULL);
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
g_signal_connect (G_OBJECT (filesrc), "eos", G_CALLBACK (eos), thread);
|
||||
|
||||
queue = gst_element_factory_make("queue", "queue");
|
||||
queue = gst_element_factory_make ("queue", "queue");
|
||||
|
||||
/* and an audio sink */
|
||||
osssink = gst_element_factory_make("osssink", "play_audio");
|
||||
g_assert(osssink != NULL);
|
||||
osssink = gst_element_factory_make ("osssink", "play_audio");
|
||||
g_assert (osssink != NULL);
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
/*
|
||||
gst_pipeline_add_src(GST_PIPELINE(pipeline), filesrc);
|
||||
gst_pipeline_add_sink(GST_PIPELINE(pipeline), queue);
|
||||
gst_pipeline_add_src(GST_PIPELINE(pipeline), filesrc);
|
||||
gst_pipeline_add_sink(GST_PIPELINE(pipeline), queue);
|
||||
|
||||
gst_bin_add(GST_BIN(thread), osssink);
|
||||
gst_bin_add(GST_BIN(thread), osssink);
|
||||
|
||||
gst_pad_link(gst_element_get_pad(queue,"src"),
|
||||
gst_element_get_pad(osssink,"sink"));
|
||||
gst_pad_link(gst_element_get_pad(queue,"src"),
|
||||
gst_element_get_pad(osssink,"sink"));
|
||||
|
||||
if (!gst_pipeline_autoplug(GST_PIPELINE(pipeline))) {
|
||||
g_print("cannot autoplug pipeline\n");
|
||||
exit(-1);
|
||||
}
|
||||
*/
|
||||
if (!gst_pipeline_autoplug(GST_PIPELINE(pipeline))) {
|
||||
g_print("cannot autoplug pipeline\n");
|
||||
exit(-1);
|
||||
}
|
||||
*/
|
||||
|
||||
gst_bin_add(GST_BIN(pipeline), thread);
|
||||
gst_bin_add (GST_BIN (pipeline), thread);
|
||||
|
||||
/* make it ready */
|
||||
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_READY);
|
||||
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);
|
||||
/* start playing */
|
||||
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
|
||||
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
|
||||
|
||||
playing = TRUE;
|
||||
|
||||
while (playing) {
|
||||
gst_bin_iterate(GST_BIN(pipeline));
|
||||
gst_bin_iterate (GST_BIN (pipeline));
|
||||
}
|
||||
|
||||
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
|
||||
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
|
||||
|
||||
exit(0);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,73 +4,73 @@
|
|||
gboolean playing;
|
||||
|
||||
/* eos will be called when the src element has an end of stream */
|
||||
void eos(GstElement *element, gpointer data)
|
||||
void
|
||||
eos (GstElement * element, gpointer data)
|
||||
{
|
||||
g_print("have eos, quitting\n");
|
||||
g_print ("have eos, quitting\n");
|
||||
|
||||
playing = FALSE;
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *filesrc, *osssink, *queue, *parse, *decode;
|
||||
GstElement *bin;
|
||||
GstElement *thread;
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
if (argc != 2) {
|
||||
g_print("usage: %s <filename>\n", argv[0]);
|
||||
exit(-1);
|
||||
g_print ("usage: %s <filename>\n", argv[0]);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* create a new thread to hold the elements */
|
||||
thread = gst_thread_new("thread");
|
||||
g_assert(thread != NULL);
|
||||
thread = gst_thread_new ("thread");
|
||||
g_assert (thread != NULL);
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
bin = gst_bin_new("bin");
|
||||
g_assert(bin != NULL);
|
||||
bin = gst_bin_new ("bin");
|
||||
g_assert (bin != NULL);
|
||||
|
||||
/* create a disk reader */
|
||||
filesrc = gst_element_factory_make("filesrc", "disk_source");
|
||||
g_assert(filesrc != NULL);
|
||||
g_object_set(G_OBJECT(filesrc),"location", argv[1],NULL);
|
||||
g_signal_connect(G_OBJECT(filesrc),"eos",
|
||||
G_CALLBACK(eos), thread);
|
||||
filesrc = gst_element_factory_make ("filesrc", "disk_source");
|
||||
g_assert (filesrc != NULL);
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
g_signal_connect (G_OBJECT (filesrc), "eos", G_CALLBACK (eos), thread);
|
||||
|
||||
queue = gst_element_factory_make("queue", "queue");
|
||||
queue = gst_element_factory_make ("queue", "queue");
|
||||
|
||||
/* and an audio sink */
|
||||
osssink = gst_element_factory_make("osssink", "play_audio");
|
||||
g_assert(osssink != NULL);
|
||||
osssink = gst_element_factory_make ("osssink", "play_audio");
|
||||
g_assert (osssink != NULL);
|
||||
|
||||
parse = gst_element_factory_make("mp3parse", "parse");
|
||||
decode = gst_element_factory_make("mpg123", "decode");
|
||||
parse = gst_element_factory_make ("mp3parse", "parse");
|
||||
decode = gst_element_factory_make ("mpg123", "decode");
|
||||
|
||||
/* add objects to the main bin */
|
||||
gst_bin_add(GST_BIN(bin), filesrc);
|
||||
gst_bin_add(GST_BIN(bin), queue);
|
||||
gst_bin_add (GST_BIN (bin), filesrc);
|
||||
gst_bin_add (GST_BIN (bin), queue);
|
||||
|
||||
gst_bin_add(GST_BIN(thread), parse);
|
||||
gst_bin_add(GST_BIN(thread), decode);
|
||||
gst_bin_add(GST_BIN(thread), osssink);
|
||||
gst_bin_add (GST_BIN (thread), parse);
|
||||
gst_bin_add (GST_BIN (thread), decode);
|
||||
gst_bin_add (GST_BIN (thread), osssink);
|
||||
|
||||
gst_element_link_many (filesrc, queue, parse, decode, osssink, NULL);
|
||||
|
||||
/* make it ready */
|
||||
gst_element_set_state(GST_ELEMENT(bin), GST_STATE_READY);
|
||||
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
|
||||
/* start playing */
|
||||
gst_element_set_state(GST_ELEMENT(bin), GST_STATE_PLAYING);
|
||||
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
|
||||
|
||||
playing = TRUE;
|
||||
|
||||
while (playing) {
|
||||
gst_bin_iterate(GST_BIN(bin));
|
||||
gst_bin_iterate (GST_BIN (bin));
|
||||
}
|
||||
|
||||
gst_element_set_state(GST_ELEMENT(bin), GST_STATE_NULL);
|
||||
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
|
||||
|
||||
exit(0);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,81 +4,81 @@
|
|||
gboolean playing;
|
||||
|
||||
/* eos will be called when the src element has an end of stream */
|
||||
void eos(GstElement *element, gpointer data)
|
||||
void
|
||||
eos (GstElement * element, gpointer data)
|
||||
{
|
||||
g_print("have eos, quitting\n");
|
||||
g_print ("have eos, quitting\n");
|
||||
|
||||
playing = FALSE;
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *filesrc, *osssink, *queue, *queue2, *parse, *decode;
|
||||
GstElement *bin;
|
||||
GstElement *thread, *thread2;
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
if (argc != 2) {
|
||||
g_print("usage: %s <filename>\n", argv[0]);
|
||||
exit(-1);
|
||||
g_print ("usage: %s <filename>\n", argv[0]);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* create a new thread to hold the elements */
|
||||
thread = gst_thread_new("thread");
|
||||
g_assert(thread != NULL);
|
||||
thread2 = gst_thread_new("thread2");
|
||||
g_assert(thread2 != NULL);
|
||||
thread = gst_thread_new ("thread");
|
||||
g_assert (thread != NULL);
|
||||
thread2 = gst_thread_new ("thread2");
|
||||
g_assert (thread2 != NULL);
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
bin = gst_bin_new("bin");
|
||||
g_assert(bin != NULL);
|
||||
bin = gst_bin_new ("bin");
|
||||
g_assert (bin != NULL);
|
||||
|
||||
/* create a disk reader */
|
||||
filesrc = gst_element_factory_make("filesrc", "disk_source");
|
||||
g_assert(filesrc != NULL);
|
||||
g_object_set(G_OBJECT(filesrc),"location", argv[1],NULL);
|
||||
g_signal_connect(G_OBJECT(filesrc),"eos",
|
||||
G_CALLBACK(eos), thread);
|
||||
filesrc = gst_element_factory_make ("filesrc", "disk_source");
|
||||
g_assert (filesrc != NULL);
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
g_signal_connect (G_OBJECT (filesrc), "eos", G_CALLBACK (eos), thread);
|
||||
|
||||
queue = gst_element_factory_make("queue", "queue");
|
||||
queue2 = gst_element_factory_make("queue", "queue2");
|
||||
queue = gst_element_factory_make ("queue", "queue");
|
||||
queue2 = gst_element_factory_make ("queue", "queue2");
|
||||
|
||||
/* and an audio sink */
|
||||
osssink = gst_element_factory_make("osssink", "play_audio");
|
||||
g_assert(osssink != NULL);
|
||||
osssink = gst_element_factory_make ("osssink", "play_audio");
|
||||
g_assert (osssink != NULL);
|
||||
|
||||
parse = gst_element_factory_make("mp3parse", "parse");
|
||||
decode = gst_element_factory_make("mpg123", "decode");
|
||||
parse = gst_element_factory_make ("mp3parse", "parse");
|
||||
decode = gst_element_factory_make ("mpg123", "decode");
|
||||
|
||||
/* add objects to the main bin */
|
||||
gst_bin_add(GST_BIN(bin), filesrc);
|
||||
gst_bin_add(GST_BIN(bin), queue);
|
||||
gst_bin_add (GST_BIN (bin), filesrc);
|
||||
gst_bin_add (GST_BIN (bin), queue);
|
||||
|
||||
gst_bin_add(GST_BIN(thread), parse);
|
||||
gst_bin_add(GST_BIN(thread), decode);
|
||||
gst_bin_add(GST_BIN(thread), queue2);
|
||||
gst_bin_add (GST_BIN (thread), parse);
|
||||
gst_bin_add (GST_BIN (thread), decode);
|
||||
gst_bin_add (GST_BIN (thread), queue2);
|
||||
|
||||
gst_bin_add(GST_BIN(thread2), osssink);
|
||||
gst_bin_add (GST_BIN (thread2), osssink);
|
||||
|
||||
gst_element_link_many (filesrc, queue, parse, decode, queue2, osssink, NULL);
|
||||
|
||||
gst_bin_add(GST_BIN(bin), thread);
|
||||
gst_bin_add(GST_BIN(bin), thread2);
|
||||
gst_bin_add (GST_BIN (bin), thread);
|
||||
gst_bin_add (GST_BIN (bin), thread2);
|
||||
|
||||
/* make it ready */
|
||||
gst_element_set_state(GST_ELEMENT(bin), GST_STATE_READY);
|
||||
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
|
||||
/* start playing */
|
||||
gst_element_set_state(GST_ELEMENT(bin), GST_STATE_PLAYING);
|
||||
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
|
||||
|
||||
playing = TRUE;
|
||||
|
||||
while (playing) {
|
||||
gst_bin_iterate(GST_BIN(bin));
|
||||
gst_bin_iterate (GST_BIN (bin));
|
||||
}
|
||||
|
||||
gst_element_set_state(GST_ELEMENT(bin), GST_STATE_NULL);
|
||||
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
|
||||
|
||||
exit(0);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
#include <string.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *bin, *filesrc, *tag_changer, *filesink;
|
||||
gchar *artist, *title, *ext, *filename;
|
||||
|
||||
|
||||
/* initialize GStreamer */
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
|
@ -36,7 +36,8 @@ main (int argc, char *argv[])
|
|||
artist = argv[1];
|
||||
artist = g_strdup (artist);
|
||||
ext = strrchr (artist, '.');
|
||||
if (ext) *ext = '\0';
|
||||
if (ext)
|
||||
*ext = '\0';
|
||||
title = strstr (artist, " - ");
|
||||
if (title == NULL) {
|
||||
g_print ("The format of the mp3 file is invalid.\n");
|
||||
|
@ -44,8 +45,8 @@ main (int argc, char *argv[])
|
|||
}
|
||||
*title = '\0';
|
||||
title += 3;
|
||||
|
||||
|
||||
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
bin = gst_pipeline_new ("pipeline");
|
||||
g_assert (bin);
|
||||
|
@ -66,25 +67,24 @@ main (int argc, char *argv[])
|
|||
g_assert (filesink);
|
||||
|
||||
/* set the filenames */
|
||||
filename = g_strdup_printf ("%s.temp", argv[1]); /* easy solution */
|
||||
filename = g_strdup_printf ("%s.temp", argv[1]); /* easy solution */
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
g_object_set (G_OBJECT (filesink), "location", filename, NULL);
|
||||
|
||||
/* make sure the tag setter uses our stuff
|
||||
(though that should already be default) */
|
||||
gst_tag_setter_set_merge_mode (GST_TAG_SETTER (tag_changer), GST_TAG_MERGE_KEEP);
|
||||
gst_tag_setter_set_merge_mode (GST_TAG_SETTER (tag_changer),
|
||||
GST_TAG_MERGE_KEEP);
|
||||
/* set the tagging information */
|
||||
gst_tag_setter_add (GST_TAG_SETTER (tag_changer), GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_ARTIST, artist,
|
||||
GST_TAG_TITLE, title,
|
||||
NULL);
|
||||
GST_TAG_ARTIST, artist, GST_TAG_TITLE, title, NULL);
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
gst_bin_add_many (GST_BIN (bin), filesrc, tag_changer, filesink, NULL);
|
||||
|
||||
/* link the elements */
|
||||
g_assert (gst_element_link_many (filesrc, tag_changer, filesink));
|
||||
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state (bin, GST_STATE_PLAYING);
|
||||
|
||||
|
@ -100,4 +100,3 @@ main (int argc, char *argv[])
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
#include <string.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *bin, *filesrc, *decoder, *encoder, *filesink;
|
||||
gchar *artist, *title, *ext, *filename;
|
||||
|
||||
|
||||
/* initialize GStreamer */
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
|
@ -36,7 +36,8 @@ main (int argc, char *argv[])
|
|||
artist = argv[1];
|
||||
artist = g_strdup (artist);
|
||||
ext = strrchr (artist, '.');
|
||||
if (ext) *ext = '\0';
|
||||
if (ext)
|
||||
*ext = '\0';
|
||||
title = strstr (artist, " - ");
|
||||
if (title == NULL) {
|
||||
g_print ("The format of the mp3 file is invalid.\n");
|
||||
|
@ -45,8 +46,8 @@ main (int argc, char *argv[])
|
|||
}
|
||||
*title = '\0';
|
||||
title += 3;
|
||||
|
||||
|
||||
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
bin = gst_pipeline_new ("pipeline");
|
||||
g_assert (bin);
|
||||
|
@ -68,13 +69,13 @@ main (int argc, char *argv[])
|
|||
g_print ("cound not find plugin \"vorbisenc\"");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* and a file writer */
|
||||
filesink = gst_element_factory_make ("filesink", "filesink");
|
||||
g_assert (filesink);
|
||||
|
||||
/* set the filenames */
|
||||
filename = g_strdup_printf ("%s.ogg", argv[1]); /* easy solution */
|
||||
filename = g_strdup_printf ("%s.ogg", argv[1]); /* easy solution */
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
g_object_set (G_OBJECT (filesink), "location", filename, NULL);
|
||||
g_free (filename);
|
||||
|
@ -84,16 +85,14 @@ main (int argc, char *argv[])
|
|||
gst_tag_setter_set_merge_mode (GST_TAG_SETTER (encoder), GST_TAG_MERGE_KEEP);
|
||||
/* set the tagging information */
|
||||
gst_tag_setter_add (GST_TAG_SETTER (encoder), GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_ARTIST, artist,
|
||||
GST_TAG_TITLE, title,
|
||||
NULL);
|
||||
GST_TAG_ARTIST, artist, GST_TAG_TITLE, title, NULL);
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
gst_bin_add_many (GST_BIN (bin), filesrc, decoder, encoder, filesink, NULL);
|
||||
|
||||
/* link the elements */
|
||||
gst_element_link_many (filesrc, decoder, encoder, filesink, NULL);
|
||||
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state (bin, GST_STATE_PLAYING);
|
||||
|
||||
|
@ -104,4 +103,3 @@ main (int argc, char *argv[])
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,73 +2,75 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
/* eos will be called when the src element has an end of stream */
|
||||
void eos(GstElement *element, gpointer data)
|
||||
void
|
||||
eos (GstElement * element, gpointer data)
|
||||
{
|
||||
GstThread *thread = GST_THREAD(data);
|
||||
g_print("have eos, quitting\n");
|
||||
GstThread *thread = GST_THREAD (data);
|
||||
|
||||
g_print ("have eos, quitting\n");
|
||||
|
||||
/* stop the bin */
|
||||
gst_element_set_state(GST_ELEMENT(thread), GST_STATE_NULL);
|
||||
gst_element_set_state (GST_ELEMENT (thread), GST_STATE_NULL);
|
||||
|
||||
gst_main_quit();
|
||||
gst_main_quit ();
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *filesrc, *osssink;
|
||||
GstElement *pipeline;
|
||||
GstElement *thread;
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
if (argc != 2) {
|
||||
g_print("usage: %s <filename>\n", argv[0]);
|
||||
exit(-1);
|
||||
g_print ("usage: %s <filename>\n", argv[0]);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* create a new thread to hold the elements */
|
||||
thread = gst_thread_new("thread");
|
||||
g_assert(thread != NULL);
|
||||
thread = gst_thread_new ("thread");
|
||||
g_assert (thread != NULL);
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
pipeline = gst_pipeline_new("pipeline");
|
||||
g_assert(pipeline != NULL);
|
||||
pipeline = gst_pipeline_new ("pipeline");
|
||||
g_assert (pipeline != NULL);
|
||||
|
||||
/* create a disk reader */
|
||||
filesrc = gst_element_factory_make("filesrc", "disk_source");
|
||||
g_assert(filesrc != NULL);
|
||||
g_object_set(G_OBJECT(filesrc),"location", argv[1],NULL);
|
||||
g_signal_connect(G_OBJECT(filesrc),"eos",
|
||||
G_CALLBACK(eos), thread);
|
||||
filesrc = gst_element_factory_make ("filesrc", "disk_source");
|
||||
g_assert (filesrc != NULL);
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
g_signal_connect (G_OBJECT (filesrc), "eos", G_CALLBACK (eos), thread);
|
||||
|
||||
/* and an audio sink */
|
||||
osssink = gst_element_factory_make("osssink", "play_audio");
|
||||
g_assert(osssink != NULL);
|
||||
osssink = gst_element_factory_make ("osssink", "play_audio");
|
||||
g_assert (osssink != NULL);
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
/*
|
||||
gst_pipeline_add_src(GST_PIPELINE(pipeline), filesrc);
|
||||
gst_pipeline_add_sink(GST_PIPELINE(pipeline), osssink);
|
||||
gst_pipeline_add_src(GST_PIPELINE(pipeline), filesrc);
|
||||
gst_pipeline_add_sink(GST_PIPELINE(pipeline), osssink);
|
||||
|
||||
if (!gst_pipeline_autoplug(GST_PIPELINE(pipeline))) {
|
||||
g_print("unable to handle stream\n");
|
||||
exit(-1);
|
||||
}
|
||||
*/
|
||||
if (!gst_pipeline_autoplug(GST_PIPELINE(pipeline))) {
|
||||
g_print("unable to handle stream\n");
|
||||
exit(-1);
|
||||
}
|
||||
*/
|
||||
|
||||
/*gst_bin_remove(GST_BIN(pipeline), filesrc); */
|
||||
|
||||
/*gst_bin_add(GST_BIN(thread), filesrc); */
|
||||
gst_bin_add(GST_BIN(thread), GST_ELEMENT(pipeline));
|
||||
gst_bin_add (GST_BIN (thread), GST_ELEMENT (pipeline));
|
||||
|
||||
/* make it ready */
|
||||
gst_element_set_state(GST_ELEMENT(thread), GST_STATE_READY);
|
||||
gst_element_set_state (GST_ELEMENT (thread), GST_STATE_READY);
|
||||
/* start playing */
|
||||
gst_element_set_state(GST_ELEMENT(thread), GST_STATE_PLAYING);
|
||||
gst_element_set_state (GST_ELEMENT (thread), GST_STATE_PLAYING);
|
||||
|
||||
gst_main();
|
||||
gst_main ();
|
||||
|
||||
gst_object_unref(GST_OBJECT(thread));
|
||||
gst_object_unref (GST_OBJECT (thread));
|
||||
|
||||
exit(0);
|
||||
exit (0);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
void
|
||||
type_found (GstElement *typefind, const GstCaps * caps)
|
||||
type_found (GstElement * typefind, const GstCaps * caps)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr parent;
|
||||
|
||||
doc = xmlNewDoc ("1.0");
|
||||
|
||||
doc = xmlNewDoc ("1.0");
|
||||
doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Capabilities", NULL);
|
||||
|
||||
parent = xmlNewChild (doc->xmlRootNode, NULL, "Caps1", NULL);
|
||||
|
@ -16,46 +16,45 @@ type_found (GstElement *typefind, const GstCaps * caps)
|
|||
xmlDocDump (stdout, doc);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *bin, *filesrc, *typefind;
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
if (argc != 2) {
|
||||
g_print("usage: %s <filename>\n", argv[0]);
|
||||
exit(-1);
|
||||
g_print ("usage: %s <filename>\n", argv[0]);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
bin = gst_pipeline_new("bin");
|
||||
g_assert(bin != NULL);
|
||||
bin = gst_pipeline_new ("bin");
|
||||
g_assert (bin != NULL);
|
||||
|
||||
/* create a file reader */
|
||||
filesrc = gst_element_factory_make("filesrc", "file_source");
|
||||
g_assert(filesrc != NULL);
|
||||
g_object_set(G_OBJECT(filesrc),"location", argv[1],NULL);
|
||||
filesrc = gst_element_factory_make ("filesrc", "file_source");
|
||||
g_assert (filesrc != NULL);
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
|
||||
typefind = gst_element_factory_make("typefind", "typefind");
|
||||
g_assert(typefind != NULL);
|
||||
typefind = gst_element_factory_make ("typefind", "typefind");
|
||||
g_assert (typefind != NULL);
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
gst_bin_add(GST_BIN(bin), filesrc);
|
||||
gst_bin_add(GST_BIN(bin), typefind);
|
||||
gst_bin_add (GST_BIN (bin), filesrc);
|
||||
gst_bin_add (GST_BIN (bin), typefind);
|
||||
|
||||
g_signal_connect (G_OBJECT (typefind), "have_type",
|
||||
G_CALLBACK (type_found), NULL);
|
||||
g_signal_connect (G_OBJECT (typefind), "have_type",
|
||||
G_CALLBACK (type_found), NULL);
|
||||
|
||||
gst_element_link (filesrc, typefind);
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state(GST_ELEMENT(bin), GST_STATE_PLAYING);
|
||||
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
|
||||
|
||||
gst_bin_iterate(GST_BIN(bin));
|
||||
gst_bin_iterate (GST_BIN (bin));
|
||||
|
||||
gst_element_set_state(GST_ELEMENT(bin), GST_STATE_NULL);
|
||||
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
|
||||
|
||||
exit(0);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,34 +4,37 @@
|
|||
gboolean playing;
|
||||
|
||||
static void
|
||||
object_saved (GstObject *object, xmlNodePtr parent, gpointer data)
|
||||
object_saved (GstObject * object, xmlNodePtr parent, gpointer data)
|
||||
{
|
||||
xmlNodePtr child;
|
||||
xmlNsPtr ns;
|
||||
|
||||
|
||||
/* first see if the namespace is already known */
|
||||
ns = xmlSearchNsByHref (parent->doc, parent, "http://gstreamer.net/gst-test/1.0/");
|
||||
ns = xmlSearchNsByHref (parent->doc, parent,
|
||||
"http://gstreamer.net/gst-test/1.0/");
|
||||
if (ns == NULL) {
|
||||
xmlNodePtr root = xmlDocGetRootElement (parent->doc);
|
||||
|
||||
/* add namespace to root node */
|
||||
ns = xmlNewNs (root, "http://gstreamer.net/gst-test/1.0/", "test");
|
||||
}
|
||||
child = xmlNewChild(parent, ns, "comment", NULL);
|
||||
|
||||
xmlNewChild(child, NULL, "text", (gchar *)data);
|
||||
child = xmlNewChild (parent, ns, "comment", NULL);
|
||||
|
||||
xmlNewChild (child, NULL, "text", (gchar *) data);
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *filesrc, *osssink, *queue, *queue2, *decode;
|
||||
GstElement *pipeline;
|
||||
GstElement *thread, *thread2;
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
if (argc != 2) {
|
||||
g_print("usage: %s <filename>\n", argv[0]);
|
||||
exit(-1);
|
||||
g_print ("usage: %s <filename>\n", argv[0]);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* create new threads to hold the elements */
|
||||
|
@ -42,12 +45,10 @@ int main(int argc,char *argv[])
|
|||
|
||||
/* these signals will allow us to save custom tags with the gst xml output */
|
||||
g_signal_connect (G_OBJECT (thread), "object_saved",
|
||||
G_CALLBACK (object_saved),
|
||||
g_strdup ("decoder thread"));
|
||||
G_CALLBACK (object_saved), g_strdup ("decoder thread"));
|
||||
g_signal_connect (G_OBJECT (thread2), "object_saved",
|
||||
G_CALLBACK (object_saved),
|
||||
g_strdup ("render thread"));
|
||||
|
||||
G_CALLBACK (object_saved), g_strdup ("render thread"));
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
pipeline = gst_pipeline_new ("pipeline");
|
||||
g_assert (pipeline != NULL);
|
||||
|
@ -89,4 +90,3 @@ int main(int argc,char *argv[])
|
|||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
gboolean playing;
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
xml_loaded (GstXML *xml, GstObject *object, xmlNodePtr self, gpointer data)
|
||||
xml_loaded (GstXML * xml, GstObject * object, xmlNodePtr self, gpointer data)
|
||||
{
|
||||
xmlNodePtr children = self->xmlChildrenNode;
|
||||
|
||||
|
@ -14,10 +14,11 @@ xml_loaded (GstXML *xml, GstObject *object, xmlNodePtr self, gpointer data)
|
|||
xmlNodePtr nodes = children->xmlChildrenNode;
|
||||
|
||||
while (nodes) {
|
||||
if (!strcmp (nodes->name, "text")) {
|
||||
gchar *name = g_strdup (xmlNodeGetContent (nodes));
|
||||
g_print ("object %s loaded with comment '%s'\n",
|
||||
gst_object_get_name (object), name);
|
||||
if (!strcmp (nodes->name, "text")) {
|
||||
gchar *name = g_strdup (xmlNodeGetContent (nodes));
|
||||
|
||||
g_print ("object %s loaded with comment '%s'\n",
|
||||
gst_object_get_name (object), name);
|
||||
}
|
||||
nodes = nodes->next;
|
||||
}
|
||||
|
@ -26,13 +27,14 @@ xml_loaded (GstXML *xml, GstObject *object, xmlNodePtr self, gpointer data)
|
|||
}
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstXML *xml;
|
||||
GstElement *pipeline;
|
||||
gboolean ret;
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
xml = gst_xml_new ();
|
||||
|
||||
|
@ -40,21 +42,20 @@ int main(int argc,char *argv[])
|
|||
/* G_CALLBACK (xml_loaded), xml); */
|
||||
|
||||
if (argc == 2)
|
||||
ret = gst_xml_parse_file(xml, argv[1], NULL);
|
||||
ret = gst_xml_parse_file (xml, argv[1], NULL);
|
||||
else
|
||||
ret = gst_xml_parse_file(xml, "xmlTest.gst", NULL);
|
||||
|
||||
ret = gst_xml_parse_file (xml, "xmlTest.gst", NULL);
|
||||
|
||||
g_assert (ret == TRUE);
|
||||
|
||||
pipeline = gst_xml_get_element(xml, "pipeline");
|
||||
pipeline = gst_xml_get_element (xml, "pipeline");
|
||||
g_assert (pipeline != NULL);
|
||||
|
||||
gst_element_set_state(pipeline, GST_STATE_PLAYING);
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
while (gst_bin_iterate(GST_BIN(pipeline)));
|
||||
while (gst_bin_iterate (GST_BIN (pipeline)));
|
||||
|
||||
gst_element_set_state(pipeline, GST_STATE_NULL);
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
|
||||
exit(0);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,17 +35,17 @@ GST_DEBUG_CATEGORY_EXTERN (GST_CAT_AUTOPLUG_ATTEMPT);
|
|||
* though the GLib version should take a function as argument...
|
||||
*/
|
||||
static void
|
||||
g_list_free_list_and_elements (GList *list)
|
||||
g_list_free_list_and_elements (GList * list)
|
||||
{
|
||||
GList *walk = list;
|
||||
|
||||
while (walk)
|
||||
{
|
||||
|
||||
while (walk) {
|
||||
g_free (walk->data);
|
||||
walk = g_list_next (walk);
|
||||
}
|
||||
g_list_free (list);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_autoplug_caps_intersect:
|
||||
* @src: a source #GstCaps
|
||||
|
@ -56,19 +56,19 @@ g_list_free_list_and_elements (GList *list)
|
|||
* Returns: TRUE, if both caps intersect.
|
||||
*/
|
||||
gboolean
|
||||
gst_autoplug_caps_intersect (const GstCaps *src, const GstCaps *sink)
|
||||
gst_autoplug_caps_intersect (const GstCaps * src, const GstCaps * sink)
|
||||
{
|
||||
GstCaps *caps;
|
||||
|
||||
/* get an intersection */
|
||||
caps = gst_caps_intersect (src, sink);
|
||||
|
||||
|
||||
/* if the caps can't link, there is no intersection */
|
||||
if (gst_caps_is_empty (caps)) {
|
||||
gst_caps_free (caps);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* hurrah, we can link, now remove the intersection */
|
||||
gst_caps_free (caps);
|
||||
return TRUE;
|
||||
|
@ -84,25 +84,24 @@ gst_autoplug_caps_intersect (const GstCaps *src, const GstCaps *sink)
|
|||
* Returns: #GstPadTemplate that can connect to the given caps
|
||||
*/
|
||||
GstPadTemplate *
|
||||
gst_autoplug_can_connect_src (GstElementFactory *fac, const GstCaps *src)
|
||||
gst_autoplug_can_connect_src (GstElementFactory * fac, const GstCaps * src)
|
||||
{
|
||||
GList *templs;
|
||||
|
||||
|
||||
templs = fac->padtemplates;
|
||||
|
||||
while (templs)
|
||||
{
|
||||
if ((GST_PAD_TEMPLATE_DIRECTION (templs->data) == GST_PAD_SINK) &&
|
||||
gst_autoplug_caps_intersect (src,
|
||||
GST_PAD_TEMPLATE_CAPS (templs->data)))
|
||||
{
|
||||
|
||||
while (templs) {
|
||||
if ((GST_PAD_TEMPLATE_DIRECTION (templs->data) == GST_PAD_SINK) &&
|
||||
gst_autoplug_caps_intersect (src,
|
||||
GST_PAD_TEMPLATE_CAPS (templs->data))) {
|
||||
return GST_PAD_TEMPLATE (templs->data);
|
||||
}
|
||||
templs = g_list_next (templs);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_autoplug_can_connect_sink:
|
||||
* @fac: factory to connect to
|
||||
|
@ -113,74 +112,73 @@ gst_autoplug_can_connect_src (GstElementFactory *fac, const GstCaps *src)
|
|||
* Returns: #GstPadTemplate that can connect to the given caps
|
||||
*/
|
||||
GstPadTemplate *
|
||||
gst_autoplug_can_connect_sink (GstElementFactory *fac, const GstCaps *sink)
|
||||
gst_autoplug_can_connect_sink (GstElementFactory * fac, const GstCaps * sink)
|
||||
{
|
||||
GList *templs;
|
||||
|
||||
|
||||
templs = fac->padtemplates;
|
||||
|
||||
while (templs)
|
||||
{
|
||||
|
||||
while (templs) {
|
||||
GstCaps *caps = GST_PAD_TEMPLATE_CAPS (templs->data);
|
||||
|
||||
if ((GST_PAD_TEMPLATE_DIRECTION (templs->data) == GST_PAD_SRC) &&
|
||||
gst_autoplug_caps_intersect (caps, sink))
|
||||
{
|
||||
gst_autoplug_caps_intersect (caps, sink)) {
|
||||
return GST_PAD_TEMPLATE (templs->data);
|
||||
}
|
||||
templs = g_list_next (templs);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GstPadTemplate *
|
||||
gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest)
|
||||
gst_autoplug_can_match (GstElementFactory * src, GstElementFactory * dest)
|
||||
{
|
||||
GList *srctemps, *desttemps;
|
||||
|
||||
srctemps = src->padtemplates;
|
||||
|
||||
while (srctemps) {
|
||||
GstPadTemplate *srctemp = (GstPadTemplate *)srctemps->data;
|
||||
GstPadTemplate *srctemp = (GstPadTemplate *) srctemps->data;
|
||||
|
||||
desttemps = dest->padtemplates;
|
||||
|
||||
while (desttemps) {
|
||||
GstPadTemplate *desttemp = (GstPadTemplate *)desttemps->data;
|
||||
GstPadTemplate *desttemp = (GstPadTemplate *) desttemps->data;
|
||||
|
||||
if (srctemp->direction == GST_PAD_SRC &&
|
||||
desttemp->direction == GST_PAD_SINK) {
|
||||
if (gst_autoplug_caps_intersect (gst_pad_template_get_caps (srctemp),
|
||||
gst_pad_template_get_caps (desttemp))) {
|
||||
GST_DEBUG ("factory \"%s\" can connect with factory \"%s\"",
|
||||
GST_OBJECT_NAME (src), GST_OBJECT_NAME (dest));
|
||||
return desttemp;
|
||||
}
|
||||
desttemp->direction == GST_PAD_SINK) {
|
||||
if (gst_autoplug_caps_intersect (gst_pad_template_get_caps (srctemp),
|
||||
gst_pad_template_get_caps (desttemp))) {
|
||||
GST_DEBUG ("factory \"%s\" can connect with factory \"%s\"",
|
||||
GST_OBJECT_NAME (src), GST_OBJECT_NAME (dest));
|
||||
return desttemp;
|
||||
}
|
||||
}
|
||||
|
||||
desttemps = g_list_next (desttemps);
|
||||
}
|
||||
srctemps = g_list_next (srctemps);
|
||||
}
|
||||
GST_DEBUG ("factory \"%s\" cannot connect with factory \"%s\"",
|
||||
GST_OBJECT_NAME (src), GST_OBJECT_NAME (dest));
|
||||
GST_DEBUG ("factory \"%s\" cannot connect with factory \"%s\"",
|
||||
GST_OBJECT_NAME (src), GST_OBJECT_NAME (dest));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* returns TRUE if the factory has padtemplates with the specified direction */
|
||||
gboolean
|
||||
gst_autoplug_factory_has_direction (GstElementFactory *fac, GstPadDirection dir)
|
||||
gst_autoplug_factory_has_direction (GstElementFactory * fac,
|
||||
GstPadDirection dir)
|
||||
{
|
||||
GList *templs = fac->padtemplates;
|
||||
|
||||
while (templs)
|
||||
{
|
||||
if (GST_PAD_TEMPLATE_DIRECTION (templs->data) == dir)
|
||||
{
|
||||
|
||||
while (templs) {
|
||||
if (GST_PAD_TEMPLATE_DIRECTION (templs->data) == dir) {
|
||||
return TRUE;
|
||||
}
|
||||
templs = g_list_next (templs);
|
||||
}
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -188,52 +186,54 @@ gst_autoplug_factory_has_direction (GstElementFactory *fac, GstPadDirection dir)
|
|||
* These functions return a new list so be sure to free it.
|
||||
*/
|
||||
GList *
|
||||
gst_autoplug_factories_sinks (GList *factories)
|
||||
gst_autoplug_factories_sinks (GList * factories)
|
||||
{
|
||||
GList *ret = NULL;
|
||||
|
||||
while (factories)
|
||||
{
|
||||
|
||||
while (factories) {
|
||||
if (gst_autoplug_factory_has_sink (factories->data))
|
||||
ret = g_list_prepend (ret, factories->data);
|
||||
factories = g_list_next (factories);
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
GList *
|
||||
gst_autoplug_factories_srcs (GList *factories)
|
||||
gst_autoplug_factories_srcs (GList * factories)
|
||||
{
|
||||
GList *ret = NULL;
|
||||
|
||||
while (factories)
|
||||
{
|
||||
|
||||
while (factories) {
|
||||
if (gst_autoplug_factory_has_src (factories->data))
|
||||
ret = g_list_prepend (ret, factories->data);
|
||||
factories = g_list_next (factories);
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
GList *
|
||||
gst_autoplug_factories_filters (GList *factories)
|
||||
|
||||
GList *
|
||||
gst_autoplug_factories_filters (GList * factories)
|
||||
{
|
||||
GList *ret = NULL;
|
||||
|
||||
while (factories)
|
||||
{
|
||||
|
||||
while (factories) {
|
||||
/* if you want it faster do src/sink check at once, don't call two functions */
|
||||
if (gst_autoplug_factory_has_src (factories->data) && gst_autoplug_factory_has_sink (factories->data))
|
||||
if (gst_autoplug_factory_has_src (factories->data)
|
||||
&& gst_autoplug_factory_has_sink (factories->data))
|
||||
ret = g_list_prepend (ret, factories->data);
|
||||
factories = g_list_next (factories);
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static gint
|
||||
gst_autoplug_rank_compare (const GstElementFactory *a, const GstElementFactory *b)
|
||||
static gint
|
||||
gst_autoplug_rank_compare (const GstElementFactory * a,
|
||||
const GstElementFactory * b)
|
||||
{
|
||||
if (GST_PLUGIN_FEATURE (a)->rank > GST_PLUGIN_FEATURE (b)->rank) return -1;
|
||||
return (GST_PLUGIN_FEATURE (a)->rank < GST_PLUGIN_FEATURE (b)->rank) ? 1 : 0;
|
||||
if (GST_PLUGIN_FEATURE (a)->rank > GST_PLUGIN_FEATURE (b)->rank)
|
||||
return -1;
|
||||
return (GST_PLUGIN_FEATURE (a)->rank < GST_PLUGIN_FEATURE (b)->rank) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* returns all factories which have sinks with non-NULL caps and srcs with
|
||||
|
@ -241,42 +241,38 @@ gst_autoplug_rank_compare (const GstElementFactory *a, const GstElementFactory *
|
|||
* rank descending.
|
||||
*/
|
||||
GList *
|
||||
gst_autoplug_factories_filters_with_sink_caps (GList *factories)
|
||||
gst_autoplug_factories_filters_with_sink_caps (GList * factories)
|
||||
{
|
||||
GList *ret = NULL;
|
||||
GstElementFactory *factory;
|
||||
GList *templs;
|
||||
|
||||
while (factories)
|
||||
{
|
||||
while (factories) {
|
||||
factory = (GstElementFactory *) factories->data;
|
||||
templs = factory->padtemplates;
|
||||
|
||||
if (GST_PLUGIN_FEATURE (factory)->rank > 0){
|
||||
if (GST_PLUGIN_FEATURE (factory)->rank > 0) {
|
||||
gboolean have_src = FALSE;
|
||||
gboolean have_sink = FALSE;
|
||||
|
||||
while (templs)
|
||||
{
|
||||
if (GST_PAD_TEMPLATE_DIRECTION (templs->data) == GST_PAD_SRC)
|
||||
{
|
||||
have_src = TRUE;
|
||||
}
|
||||
if ((GST_PAD_TEMPLATE_DIRECTION (templs->data) == GST_PAD_SINK) && (GST_PAD_TEMPLATE_CAPS (templs->data) != NULL))
|
||||
{
|
||||
have_sink = TRUE;
|
||||
}
|
||||
if (have_src && have_sink)
|
||||
{
|
||||
ret = g_list_prepend (ret, factory);
|
||||
break;
|
||||
}
|
||||
templs = g_list_next (templs);
|
||||
while (templs) {
|
||||
if (GST_PAD_TEMPLATE_DIRECTION (templs->data) == GST_PAD_SRC) {
|
||||
have_src = TRUE;
|
||||
}
|
||||
if ((GST_PAD_TEMPLATE_DIRECTION (templs->data) == GST_PAD_SINK)
|
||||
&& (GST_PAD_TEMPLATE_CAPS (templs->data) != NULL)) {
|
||||
have_sink = TRUE;
|
||||
}
|
||||
if (have_src && have_sink) {
|
||||
ret = g_list_prepend (ret, factory);
|
||||
break;
|
||||
}
|
||||
templs = g_list_next (templs);
|
||||
}
|
||||
}
|
||||
factories = g_list_next (factories);
|
||||
}
|
||||
return g_list_sort(ret, (GCompareFunc)gst_autoplug_rank_compare);
|
||||
return g_list_sort (ret, (GCompareFunc) gst_autoplug_rank_compare);
|
||||
}
|
||||
|
||||
|
||||
|
@ -284,32 +280,31 @@ gst_autoplug_factories_filters_with_sink_caps (GList *factories)
|
|||
/* returns all factories which have a maximum of maxtemplates GstPadTemplates in direction dir
|
||||
*/
|
||||
GList *
|
||||
gst_autoplug_factories_at_most_templates(GList *factories, GstPadDirection dir, guint maxtemplates)
|
||||
gst_autoplug_factories_at_most_templates (GList * factories,
|
||||
GstPadDirection dir, guint maxtemplates)
|
||||
{
|
||||
GList *ret = NULL;
|
||||
|
||||
while (factories)
|
||||
{
|
||||
|
||||
while (factories) {
|
||||
guint count = 0;
|
||||
GList *templs = ((GstElementFactory *) factories->data)->padtemplates;
|
||||
|
||||
while (templs)
|
||||
{
|
||||
if (GST_PAD_TEMPLATE_DIRECTION (templs->data) == dir)
|
||||
{
|
||||
count++;
|
||||
while (templs) {
|
||||
if (GST_PAD_TEMPLATE_DIRECTION (templs->data) == dir) {
|
||||
count++;
|
||||
}
|
||||
if (count > maxtemplates)
|
||||
break;
|
||||
break;
|
||||
templs = g_list_next (templs);
|
||||
}
|
||||
if (count <= maxtemplates)
|
||||
ret = g_list_prepend (ret, factories->data);
|
||||
|
||||
|
||||
factories = g_list_next (factories);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SHORTEST PATH ALGORITHM
|
||||
|
@ -327,39 +322,38 @@ gst_autoplug_factories_at_most_templates(GList *factories, GstPadDirection dir,
|
|||
* to get the shortest path.
|
||||
*/
|
||||
GList *
|
||||
gst_autoplug_sp (const GstCaps *srccaps, const GstCaps *sinkcaps, GList *factories)
|
||||
gst_autoplug_sp (const GstCaps * srccaps, const GstCaps * sinkcaps,
|
||||
GList * factories)
|
||||
{
|
||||
GList *factory_nodes = NULL;
|
||||
guint curcost = GST_AUTOPLUG_MAX_COST; /* below this cost, there is no path */
|
||||
GstAutoplugNode *bestnode = NULL; /* best (unconnected) endpoint currently */
|
||||
|
||||
guint curcost = GST_AUTOPLUG_MAX_COST; /* below this cost, there is no path */
|
||||
GstAutoplugNode *bestnode = NULL; /* best (unconnected) endpoint currently */
|
||||
|
||||
g_return_val_if_fail (srccaps != NULL, NULL);
|
||||
g_return_val_if_fail (sinkcaps != NULL, NULL);
|
||||
|
||||
|
||||
GST_INFO ("attempting to autoplug via shortest path from %"
|
||||
GST_PTR_FORMAT " to %" GST_PTR_FORMAT, srccaps, sinkcaps);
|
||||
|
||||
/* wrap all factories as GstAutoplugNode
|
||||
* initialize the cost */
|
||||
while (factories)
|
||||
{
|
||||
while (factories) {
|
||||
GstAutoplugNode *node = g_new0 (GstAutoplugNode, 1);
|
||||
|
||||
node->prev = NULL;
|
||||
node->fac = (GstElementFactory *) factories->data;
|
||||
GST_DEBUG ("trying with %s", node->fac->details.longname);
|
||||
node->templ = gst_autoplug_can_connect_src (node->fac, srccaps);
|
||||
node->cost = (node->templ ? gst_autoplug_get_cost (node->fac)
|
||||
: GST_AUTOPLUG_MAX_COST);
|
||||
node->cost = (node->templ ? gst_autoplug_get_cost (node->fac)
|
||||
: GST_AUTOPLUG_MAX_COST);
|
||||
node->endpoint = gst_autoplug_can_connect_sink (node->fac, sinkcaps);
|
||||
if (node->templ && node->endpoint)
|
||||
GST_DEBUG ("%s makes connection possible",
|
||||
node->fac->details.longname);
|
||||
GST_DEBUG ("%s makes connection possible", node->fac->details.longname);
|
||||
else
|
||||
GST_DEBUG ("direct connection with %s not possible",
|
||||
node->fac->details.longname);
|
||||
if ((node->endpoint != NULL) &&
|
||||
((bestnode == NULL) || (node->cost < bestnode->cost)))
|
||||
{
|
||||
node->fac->details.longname);
|
||||
if ((node->endpoint != NULL) &&
|
||||
((bestnode == NULL) || (node->cost < bestnode->cost))) {
|
||||
bestnode = node;
|
||||
}
|
||||
factory_nodes = g_list_prepend (factory_nodes, node);
|
||||
|
@ -367,80 +361,81 @@ gst_autoplug_sp (const GstCaps *srccaps, const GstCaps *sinkcaps, GList *factori
|
|||
curcost = node->cost < curcost ? node->cost : curcost;
|
||||
factories = g_list_next (factories);
|
||||
}
|
||||
|
||||
|
||||
/* check if we even have possible endpoints */
|
||||
if (bestnode == NULL)
|
||||
{
|
||||
if (bestnode == NULL) {
|
||||
GST_DEBUG ("no factory found that could connect to sink caps");
|
||||
g_list_free_list_and_elements (factory_nodes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* iterate until we found the best path */
|
||||
while (curcost < GST_AUTOPLUG_MAX_COST)
|
||||
{
|
||||
while (curcost < GST_AUTOPLUG_MAX_COST) {
|
||||
GList *nodes = factory_nodes;
|
||||
guint nextcost = GST_AUTOPLUG_MAX_COST; /* next cost to check */
|
||||
GST_DEBUG ("iterating at current cost %d, bestnode %s at %d", curcost, GST_OBJECT_NAME (bestnode->fac), bestnode->cost);
|
||||
guint nextcost = GST_AUTOPLUG_MAX_COST; /* next cost to check */
|
||||
|
||||
GST_DEBUG ("iterating at current cost %d, bestnode %s at %d", curcost,
|
||||
GST_OBJECT_NAME (bestnode->fac), bestnode->cost);
|
||||
/* check if we already have a valid best connection to the sink */
|
||||
if (bestnode->cost <= curcost)
|
||||
{
|
||||
if (bestnode->cost <= curcost) {
|
||||
GList *ret;
|
||||
GST_DEBUG ("found a way to connect via %s", GST_OBJECT_NAME ((GstObject *) bestnode->fac));
|
||||
|
||||
GST_DEBUG ("found a way to connect via %s",
|
||||
GST_OBJECT_NAME ((GstObject *) bestnode->fac));
|
||||
/* enter all factories into the return list */
|
||||
ret = g_list_prepend (NULL, bestnode->fac);
|
||||
bestnode = bestnode->prev;
|
||||
while (bestnode != NULL)
|
||||
{
|
||||
ret = g_list_prepend (ret, bestnode->fac);
|
||||
bestnode = bestnode->prev;
|
||||
while (bestnode != NULL) {
|
||||
ret = g_list_prepend (ret, bestnode->fac);
|
||||
bestnode = bestnode->prev;
|
||||
}
|
||||
g_list_free_list_and_elements (factory_nodes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* iterate over all factories we have
|
||||
* if they have the current cost, calculate if this
|
||||
* factory supplies shorter paths to other elements
|
||||
*/
|
||||
while (nodes)
|
||||
{
|
||||
if (((GstAutoplugNode *) nodes->data)->cost == curcost)
|
||||
{
|
||||
/* now check all elements if we got a shorter path */
|
||||
GList *sinknodes = factory_nodes;
|
||||
GstAutoplugNode *srcnode = (GstAutoplugNode *) nodes->data;
|
||||
while (sinknodes)
|
||||
{
|
||||
GstAutoplugNode *sinknode = (GstAutoplugNode *) sinknodes->data;
|
||||
GstPadTemplate *templ;
|
||||
if ((sinknode->cost > srcnode->cost + gst_autoplug_get_cost (sinknode->fac)) && (templ = gst_autoplug_can_match(srcnode->fac, sinknode->fac)))
|
||||
{
|
||||
/* we got a shorter path
|
||||
* now enter that path to that node */
|
||||
sinknode->prev = srcnode;
|
||||
sinknode->templ = templ;
|
||||
sinknode->cost = srcnode->cost + gst_autoplug_get_cost (sinknode->fac);
|
||||
/* make sure to set which cost to view next */
|
||||
nextcost = (nextcost > sinknode->cost) ? sinknode->cost : nextcost;
|
||||
/* did we get a new best node? */
|
||||
if (sinknode->endpoint && (sinknode->cost < bestnode->cost))
|
||||
{
|
||||
bestnode = sinknode;
|
||||
}
|
||||
}
|
||||
sinknodes = g_list_next (sinknodes);
|
||||
}
|
||||
/* FIXME: for speed remove the item we just iterated with from the factory_nodes
|
||||
* but don't free it yet and don't forget to free it.
|
||||
*/
|
||||
while (nodes) {
|
||||
if (((GstAutoplugNode *) nodes->data)->cost == curcost) {
|
||||
/* now check all elements if we got a shorter path */
|
||||
GList *sinknodes = factory_nodes;
|
||||
GstAutoplugNode *srcnode = (GstAutoplugNode *) nodes->data;
|
||||
|
||||
while (sinknodes) {
|
||||
GstAutoplugNode *sinknode = (GstAutoplugNode *) sinknodes->data;
|
||||
GstPadTemplate *templ;
|
||||
|
||||
if ((sinknode->cost >
|
||||
srcnode->cost + gst_autoplug_get_cost (sinknode->fac))
|
||||
&& (templ =
|
||||
gst_autoplug_can_match (srcnode->fac, sinknode->fac))) {
|
||||
/* we got a shorter path
|
||||
* now enter that path to that node */
|
||||
sinknode->prev = srcnode;
|
||||
sinknode->templ = templ;
|
||||
sinknode->cost =
|
||||
srcnode->cost + gst_autoplug_get_cost (sinknode->fac);
|
||||
/* make sure to set which cost to view next */
|
||||
nextcost = (nextcost > sinknode->cost) ? sinknode->cost : nextcost;
|
||||
/* did we get a new best node? */
|
||||
if (sinknode->endpoint && (sinknode->cost < bestnode->cost)) {
|
||||
bestnode = sinknode;
|
||||
}
|
||||
}
|
||||
sinknodes = g_list_next (sinknodes);
|
||||
}
|
||||
/* FIXME: for speed remove the item we just iterated with from the factory_nodes
|
||||
* but don't free it yet and don't forget to free it.
|
||||
*/
|
||||
}
|
||||
nodes = g_list_next (nodes);
|
||||
}
|
||||
curcost = nextcost;
|
||||
}
|
||||
|
||||
GST_DEBUG ("found no path from source caps to sink caps");
|
||||
|
||||
GST_DEBUG ("found no path from source caps to sink caps");
|
||||
g_list_free_list_and_elements (factory_nodes);
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -30,21 +30,27 @@
|
|||
|
||||
/* struct for a node, in the search tree */
|
||||
typedef struct _GstAutoplugNode GstAutoplugNode;
|
||||
|
||||
struct _GstAutoplugNode {
|
||||
GstAutoplugNode *prev; /* previous node */
|
||||
GstElementFactory *fac; /* factory of element to connect to */
|
||||
GstPadTemplate *templ; /* template which can connect */
|
||||
guint cost; /* total cost to get here */
|
||||
GstPadTemplate *endpoint; /* pad template that can connect to sink caps */
|
||||
|
||||
struct _GstAutoplugNode
|
||||
{
|
||||
GstAutoplugNode *prev; /* previous node */
|
||||
GstElementFactory *fac; /* factory of element to connect to */
|
||||
GstPadTemplate *templ; /* template which can connect */
|
||||
guint cost; /* total cost to get here */
|
||||
GstPadTemplate *endpoint; /* pad template that can connect to sink caps */
|
||||
};
|
||||
|
||||
/* helper functions */
|
||||
gboolean gst_autoplug_caps_intersect (const GstCaps *src, const GstCaps *sink);
|
||||
GstPadTemplate * gst_autoplug_can_connect_src (GstElementFactory *fac, const GstCaps *src);
|
||||
GstPadTemplate * gst_autoplug_can_connect_sink (GstElementFactory *fac, const GstCaps *sink);
|
||||
GstPadTemplate * gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest);
|
||||
gboolean gst_autoplug_factory_has_direction (GstElementFactory *fac, GstPadDirection dir);
|
||||
gboolean gst_autoplug_caps_intersect (const GstCaps * src,
|
||||
const GstCaps * sink);
|
||||
GstPadTemplate *gst_autoplug_can_connect_src (GstElementFactory * fac,
|
||||
const GstCaps * src);
|
||||
GstPadTemplate *gst_autoplug_can_connect_sink (GstElementFactory * fac,
|
||||
const GstCaps * sink);
|
||||
GstPadTemplate *gst_autoplug_can_match (GstElementFactory * src,
|
||||
GstElementFactory * dest);
|
||||
gboolean gst_autoplug_factory_has_direction (GstElementFactory * fac,
|
||||
GstPadDirection dir);
|
||||
#define gst_autoplug_factory_has_sink(fac) gst_autoplug_factory_has_direction((fac), GST_PAD_SINK)
|
||||
#define gst_autoplug_factory_has_src(fac) gst_autoplug_factory_has_direction((fac), GST_PAD_SRC)
|
||||
|
||||
|
@ -52,13 +58,15 @@ gboolean gst_autoplug_factory_has_direction (Gs
|
|||
#define gst_autoplug_get_cost(fac) 1
|
||||
|
||||
/* factory selections */
|
||||
GList * gst_autoplug_factories_sinks (GList *factories);
|
||||
GList * gst_autoplug_factories_srcs (GList *factories);
|
||||
GList * gst_autoplug_factories_filters (GList *factories);
|
||||
GList * gst_autoplug_factories_filters_with_sink_caps(GList *factories);
|
||||
GList * gst_autoplug_factories_at_most_templates(GList *factories, GstPadDirection dir, guint maxtemplates);
|
||||
GList *gst_autoplug_factories_sinks (GList * factories);
|
||||
GList *gst_autoplug_factories_srcs (GList * factories);
|
||||
GList *gst_autoplug_factories_filters (GList * factories);
|
||||
GList *gst_autoplug_factories_filters_with_sink_caps (GList * factories);
|
||||
GList *gst_autoplug_factories_at_most_templates (GList * factories,
|
||||
GstPadDirection dir, guint maxtemplates);
|
||||
|
||||
/* shortest path algorithm */
|
||||
GList * gst_autoplug_sp (const GstCaps *src_caps, const GstCaps *sink_caps, GList *factories);
|
||||
GList *gst_autoplug_sp (const GstCaps * src_caps, const GstCaps * sink_caps,
|
||||
GList * factories);
|
||||
|
||||
#endif /* __GST_SEARCHFUNCS_H__ */
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - handle automatic removal of unneeded elements
|
||||
|
@ -54,12 +54,14 @@ GST_DEBUG_CATEGORY (gst_spider_debug);
|
|||
#define GST_CAT_DEFAULT gst_spider_debug
|
||||
|
||||
/* signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_FACTORIES,
|
||||
/* FILL ME TOO */
|
||||
|
@ -67,88 +69,96 @@ enum {
|
|||
|
||||
/* generic templates */
|
||||
static GstStaticPadTemplate spider_src_factory =
|
||||
GST_STATIC_PAD_TEMPLATE (
|
||||
"src_%d",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
GST_STATIC_PAD_TEMPLATE ("src_%d",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
/* standard GObject stuff */
|
||||
static void gst_spider_class_init (GstSpiderClass *klass);
|
||||
static void gst_spider_init (GstSpider *spider);
|
||||
static void gst_spider_dispose (GObject *object);
|
||||
static void gst_spider_class_init (GstSpiderClass * klass);
|
||||
static void gst_spider_init (GstSpider * spider);
|
||||
static void gst_spider_dispose (GObject * object);
|
||||
|
||||
/* element class functions */
|
||||
static GstPad* gst_spider_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *name);
|
||||
static void gst_spider_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
static void gst_spider_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||
static GstPad *gst_spider_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * name);
|
||||
static void gst_spider_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_spider_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
/* link functions */
|
||||
static GstSpiderConnection * gst_spider_link_new (GstSpiderIdentity *src);
|
||||
static void gst_spider_link_destroy (GstSpiderConnection *conn);
|
||||
static void gst_spider_link_reset (GstSpiderConnection *conn, GstElement *to);
|
||||
static void gst_spider_link_add (GstSpiderConnection *conn, GstElement *element);
|
||||
static GstSpiderConnection * gst_spider_link_find (GstSpiderIdentity *src);
|
||||
static GstSpiderConnection * gst_spider_link_get (GstSpiderIdentity *src);
|
||||
static GstSpiderConnection *gst_spider_link_new (GstSpiderIdentity * src);
|
||||
static void gst_spider_link_destroy (GstSpiderConnection * conn);
|
||||
static void gst_spider_link_reset (GstSpiderConnection * conn, GstElement * to);
|
||||
static void gst_spider_link_add (GstSpiderConnection * conn,
|
||||
GstElement * element);
|
||||
static GstSpiderConnection *gst_spider_link_find (GstSpiderIdentity * src);
|
||||
static GstSpiderConnection *gst_spider_link_get (GstSpiderIdentity * src);
|
||||
|
||||
/* autoplugging functions */
|
||||
static GstElement * gst_spider_find_element_to_plug (GstElement *src, GstElementFactory *fac, GstPadDirection dir);
|
||||
static GstPadLinkReturn gst_spider_plug (GstSpiderConnection *conn);
|
||||
static GstPadLinkReturn gst_spider_plug_from_srcpad (GstSpiderConnection *conn, GstPad *srcpad);
|
||||
static GstElement *gst_spider_find_element_to_plug (GstElement * src,
|
||||
GstElementFactory * fac, GstPadDirection dir);
|
||||
static GstPadLinkReturn gst_spider_plug (GstSpiderConnection * conn);
|
||||
static GstPadLinkReturn gst_spider_plug_from_srcpad (GstSpiderConnection * conn,
|
||||
GstPad * srcpad);
|
||||
/*static GstPadLinkReturn gst_spider_plug_peers (GstSpider *spider, GstPad *srcpad, GstPad *sinkpad); */
|
||||
static GstPadLinkReturn gst_spider_create_and_plug (GstSpiderConnection *conn, GList *plugpath);
|
||||
static GstPadLinkReturn gst_spider_create_and_plug (GstSpiderConnection * conn,
|
||||
GList * plugpath);
|
||||
|
||||
/* random functions */
|
||||
static gchar * gst_spider_unused_elementname (GstBin *bin, const gchar *startwith);
|
||||
static gchar *gst_spider_unused_elementname (GstBin * bin,
|
||||
const gchar * startwith);
|
||||
|
||||
/* debugging stuff
|
||||
static void print_spider_contents (GstSpider *spider);
|
||||
static void print_spider_link (GstSpiderConnection *conn); */
|
||||
|
||||
/* === variables === */
|
||||
static GstElementClass * parent_class = NULL;
|
||||
static GstElementClass *parent_class = NULL;
|
||||
|
||||
/* no signals yet
|
||||
static guint gst_spider_signals[LAST_SIGNAL] = { 0 };*/
|
||||
|
||||
/* GObject and GStreamer init functions */
|
||||
GType
|
||||
gst_spider_get_type(void)
|
||||
gst_spider_get_type (void)
|
||||
{
|
||||
static GType spider_type = 0;
|
||||
|
||||
if (!spider_type) {
|
||||
static const GTypeInfo spider_info = {
|
||||
sizeof(GstSpiderClass),
|
||||
sizeof (GstSpiderClass),
|
||||
NULL,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_spider_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(GstSpider),
|
||||
sizeof (GstSpider),
|
||||
0,
|
||||
(GInstanceInitFunc)gst_spider_init,
|
||||
(GInstanceInitFunc) gst_spider_init,
|
||||
};
|
||||
spider_type = g_type_register_static (GST_TYPE_BIN, "GstSpider", &spider_info, 0);
|
||||
spider_type =
|
||||
g_type_register_static (GST_TYPE_BIN, "GstSpider", &spider_info, 0);
|
||||
}
|
||||
return spider_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_spider_class_init (GstSpiderClass *klass)
|
||||
gst_spider_class_init (GstSpiderClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
||||
gobject_class = (GObjectClass*) klass;
|
||||
gstelement_class = (GstElementClass*) klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
parent_class = g_type_class_ref(GST_TYPE_BIN);
|
||||
parent_class = g_type_class_ref (GST_TYPE_BIN);
|
||||
|
||||
/* properties */
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FACTORIES,
|
||||
g_param_spec_pointer ("factories", "allowed factories", "allowed factories for autoplugging", G_PARAM_READWRITE));
|
||||
g_param_spec_pointer ("factories", "allowed factories",
|
||||
"allowed factories for autoplugging", G_PARAM_READWRITE));
|
||||
|
||||
gobject_class->set_property = gst_spider_set_property;
|
||||
gobject_class->get_property = gst_spider_get_property;
|
||||
|
@ -157,74 +167,81 @@ gst_spider_class_init (GstSpiderClass *klass)
|
|||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&spider_src_factory));
|
||||
gst_element_class_set_details (gstelement_class, &gst_spider_details);
|
||||
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_spider_request_new_pad);
|
||||
|
||||
gstelement_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_spider_request_new_pad);
|
||||
}
|
||||
static void
|
||||
gst_spider_init (GstSpider *spider)
|
||||
static void
|
||||
gst_spider_init (GstSpider * spider)
|
||||
{
|
||||
/* use only elements which have sources and sinks and where the sinks have caps */
|
||||
/* FIXME: How do we handle factories that are added after the spider was constructed? */
|
||||
spider->factories = gst_autoplug_factories_filters_with_sink_caps ((GList *)
|
||||
gst_registry_pool_feature_list (GST_TYPE_ELEMENT_FACTORY));
|
||||
spider->factories = gst_autoplug_factories_filters_with_sink_caps ((GList *)
|
||||
gst_registry_pool_feature_list (GST_TYPE_ELEMENT_FACTORY));
|
||||
|
||||
spider->links = NULL;
|
||||
|
||||
spider->sink_ident = gst_spider_identity_new_sink ("sink_ident");
|
||||
gst_bin_add (GST_BIN (spider), GST_ELEMENT (spider->sink_ident));
|
||||
gst_element_add_ghost_pad (GST_ELEMENT(spider), spider->sink_ident->sink, "sink");
|
||||
|
||||
gst_element_add_ghost_pad (GST_ELEMENT (spider), spider->sink_ident->sink,
|
||||
"sink");
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gst_spider_dispose (GObject *object)
|
||||
gst_spider_dispose (GObject * object)
|
||||
{
|
||||
GstSpider *spider;
|
||||
|
||||
|
||||
spider = GST_SPIDER (object);
|
||||
g_list_free (spider->factories);
|
||||
|
||||
|
||||
((GObjectClass *) parent_class)->dispose (object);
|
||||
}
|
||||
static GstPad *
|
||||
gst_spider_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *name)
|
||||
gst_spider_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
||||
const gchar * name)
|
||||
{
|
||||
GstPad *returnpad;
|
||||
gchar *padname;
|
||||
GstSpiderIdentity *identity;
|
||||
GstSpider *spider;
|
||||
|
||||
|
||||
g_return_val_if_fail (templ != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
|
||||
g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC, NULL);
|
||||
|
||||
g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC,
|
||||
NULL);
|
||||
|
||||
spider = GST_SPIDER (element);
|
||||
|
||||
|
||||
/* create an identity object, so we have a pad */
|
||||
padname = gst_spider_unused_elementname ((GstBin *)spider, "src_");
|
||||
padname = gst_spider_unused_elementname ((GstBin *) spider, "src_");
|
||||
identity = gst_spider_identity_new_src (padname);
|
||||
returnpad = identity->src;
|
||||
|
||||
|
||||
/* FIXME: use the requested name for the pad */
|
||||
|
||||
gst_object_replace ((GstObject **) &returnpad->padtemplate, (GstObject *) templ);
|
||||
|
||||
gst_object_replace ((GstObject **) & returnpad->padtemplate,
|
||||
(GstObject *) templ);
|
||||
|
||||
gst_bin_add (GST_BIN (element), GST_ELEMENT (identity));
|
||||
|
||||
|
||||
returnpad = gst_element_add_ghost_pad (element, returnpad, padname);
|
||||
g_free (padname);
|
||||
gst_spider_link_new (identity);
|
||||
GST_DEBUG ("successuflly created requested pad %s:%s", GST_DEBUG_PAD_NAME (returnpad));
|
||||
|
||||
GST_DEBUG ("successuflly created requested pad %s:%s",
|
||||
GST_DEBUG_PAD_NAME (returnpad));
|
||||
|
||||
return returnpad;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_spider_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
gst_spider_set_property (GObject * object, guint prop_id, const GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstSpider *spider;
|
||||
GList *list;
|
||||
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_SPIDER (object));
|
||||
|
||||
|
@ -233,8 +250,7 @@ gst_spider_set_property (GObject *object, guint prop_id, const GValue *value, GP
|
|||
switch (prop_id) {
|
||||
case ARG_FACTORIES:
|
||||
list = (GList *) g_value_get_pointer (value);
|
||||
while (list)
|
||||
{
|
||||
while (list) {
|
||||
g_return_if_fail (list->data != NULL);
|
||||
g_return_if_fail (GST_IS_ELEMENT_FACTORY (list->data));
|
||||
list = g_list_next (list);
|
||||
|
@ -247,12 +263,13 @@ gst_spider_set_property (GObject *object, guint prop_id, const GValue *value, GP
|
|||
}
|
||||
}
|
||||
static void
|
||||
gst_spider_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
gst_spider_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstSpider *spider;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
spider = GST_SPIDER(object);
|
||||
spider = GST_SPIDER (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_FACTORIES:
|
||||
|
@ -263,161 +280,167 @@ gst_spider_get_property (GObject *object, guint prop_id, GValue *value, GParamSp
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* get a name for an element that isn't used yet */
|
||||
static gchar *
|
||||
gst_spider_unused_elementname (GstBin *bin, const gchar *startwith)
|
||||
gst_spider_unused_elementname (GstBin * bin, const gchar * startwith)
|
||||
{
|
||||
gchar * name = g_strdup_printf ("%s%d", startwith, 0);
|
||||
gchar *name = g_strdup_printf ("%s%d", startwith, 0);
|
||||
guint i;
|
||||
|
||||
for (i = 0; gst_bin_get_by_name (bin, name) != NULL; )
|
||||
{
|
||||
|
||||
for (i = 0; gst_bin_get_by_name (bin, name) != NULL;) {
|
||||
g_free (name);
|
||||
name = g_strdup_printf ("%s%d", startwith, ++i);
|
||||
}
|
||||
|
||||
|
||||
return name;
|
||||
}
|
||||
static void
|
||||
gst_spider_link_sometimes (GstElement *src, GstPad *pad, GstSpiderConnection *conn)
|
||||
gst_spider_link_sometimes (GstElement * src, GstPad * pad,
|
||||
GstSpiderConnection * conn)
|
||||
{
|
||||
gulong signal_id = conn->signal_id;
|
||||
|
||||
|
||||
/* try to autoplug the elements */
|
||||
if (gst_spider_plug_from_srcpad (conn, pad) != GST_PAD_LINK_REFUSED) {
|
||||
GST_DEBUG ("%s:%s was autoplugged to %s:%s, removing callback",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (conn->src->sink));
|
||||
GST_DEBUG ("%s:%s was autoplugged to %s:%s, removing callback",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (conn->src->sink));
|
||||
g_signal_handler_disconnect (src, signal_id);
|
||||
signal_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* create a new link from those two elements */
|
||||
static GstSpiderConnection *
|
||||
gst_spider_link_new (GstSpiderIdentity *src)
|
||||
gst_spider_link_new (GstSpiderIdentity * src)
|
||||
{
|
||||
GstSpider *spider = GST_SPIDER (GST_OBJECT_PARENT (src));
|
||||
|
||||
|
||||
GstSpiderConnection *conn = g_new0 (GstSpiderConnection, 1);
|
||||
|
||||
conn->src = src;
|
||||
conn->path = NULL;
|
||||
conn->current = (GstElement *) spider->sink_ident;
|
||||
spider->links = g_list_prepend (spider->links, conn);
|
||||
|
||||
|
||||
return conn;
|
||||
}
|
||||
static void
|
||||
gst_spider_link_destroy (GstSpiderConnection *conn)
|
||||
gst_spider_link_destroy (GstSpiderConnection * conn)
|
||||
{
|
||||
GstSpider *spider = GST_SPIDER (GST_OBJECT_PARENT (conn->src));
|
||||
|
||||
/* reset link to unplugged */
|
||||
gst_spider_link_reset (conn, (GstElement *) spider->sink_ident);
|
||||
g_free (conn);
|
||||
}
|
||||
static void
|
||||
gst_spider_link_reset (GstSpiderConnection *conn, GstElement *to)
|
||||
gst_spider_link_reset (GstSpiderConnection * conn, GstElement * to)
|
||||
{
|
||||
GstSpider *spider = GST_SPIDER (GST_OBJECT_PARENT (conn->src));
|
||||
GST_DEBUG ("resetting link from %s to %s, currently at %s to %s", GST_ELEMENT_NAME (spider->sink_ident),
|
||||
GST_ELEMENT_NAME (conn->src), GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (to));
|
||||
while ((conn->path != NULL) && ((GstElement *) conn->path->data != to))
|
||||
{
|
||||
|
||||
GST_DEBUG ("resetting link from %s to %s, currently at %s to %s",
|
||||
GST_ELEMENT_NAME (spider->sink_ident), GST_ELEMENT_NAME (conn->src),
|
||||
GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (to));
|
||||
while ((conn->path != NULL) && ((GstElement *) conn->path->data != to)) {
|
||||
gst_object_unref ((GstObject *) conn->path->data);
|
||||
conn->path = g_list_delete_link (conn->path, conn->path);
|
||||
}
|
||||
if (conn->path == NULL)
|
||||
{
|
||||
if (conn->path == NULL) {
|
||||
conn->current = (GstElement *) spider->sink_ident;
|
||||
} else {
|
||||
conn->current = to;
|
||||
}
|
||||
}
|
||||
|
||||
/* add an element to the link */
|
||||
static void
|
||||
gst_spider_link_add (GstSpiderConnection *conn, GstElement *element)
|
||||
gst_spider_link_add (GstSpiderConnection * conn, GstElement * element)
|
||||
{
|
||||
gst_object_ref ((GstObject *) element);
|
||||
gst_object_sink ((GstObject *) element);
|
||||
conn->path = g_list_prepend (conn->path, element);
|
||||
conn->current = element;
|
||||
}
|
||||
|
||||
/* find the link from those two elements */
|
||||
static GstSpiderConnection *
|
||||
gst_spider_link_find (GstSpiderIdentity *src)
|
||||
gst_spider_link_find (GstSpiderIdentity * src)
|
||||
{
|
||||
GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (src);
|
||||
GList *list = spider->links;
|
||||
|
||||
while (list)
|
||||
{
|
||||
|
||||
while (list) {
|
||||
GstSpiderConnection *conn = (GstSpiderConnection *) list->data;
|
||||
if (conn->src == src){
|
||||
|
||||
if (conn->src == src) {
|
||||
return conn;
|
||||
}
|
||||
list = g_list_next(list);
|
||||
list = g_list_next (list);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get a new link from those two elements
|
||||
* search first; if none is found, create a new one */
|
||||
static GstSpiderConnection *
|
||||
gst_spider_link_get (GstSpiderIdentity *src)
|
||||
gst_spider_link_get (GstSpiderIdentity * src)
|
||||
{
|
||||
GstSpiderConnection *ret;
|
||||
|
||||
if ((ret = gst_spider_link_find (src)) != NULL)
|
||||
{
|
||||
|
||||
if ((ret = gst_spider_link_find (src)) != NULL) {
|
||||
return ret;
|
||||
}
|
||||
return gst_spider_link_new (src);
|
||||
}
|
||||
void
|
||||
gst_spider_identity_plug (GstSpiderIdentity *ident)
|
||||
}
|
||||
|
||||
void
|
||||
gst_spider_identity_plug (GstSpiderIdentity * ident)
|
||||
{
|
||||
GstSpider *spider;
|
||||
const GList *padlist;
|
||||
GstPadDirection dir;
|
||||
GstSpiderConnection *conn;
|
||||
|
||||
|
||||
/* checks */
|
||||
g_return_if_fail (ident != NULL);
|
||||
g_return_if_fail (GST_IS_SPIDER_IDENTITY (ident));
|
||||
spider = GST_SPIDER (GST_ELEMENT_PARENT (ident));
|
||||
g_assert (spider != NULL);
|
||||
g_assert (GST_IS_SPIDER (spider));
|
||||
|
||||
|
||||
/* return if we're already plugged */
|
||||
if (ident->plugged) return;
|
||||
if (ident->plugged)
|
||||
return;
|
||||
|
||||
/* check if there is at least one element factory that can handle the
|
||||
identity's src caps */
|
||||
{
|
||||
GstCaps *src_caps = gst_pad_get_caps (ident->src);
|
||||
if (! gst_caps_is_empty (src_caps) && ! gst_caps_is_any (src_caps))
|
||||
{
|
||||
|
||||
if (!gst_caps_is_empty (src_caps) && !gst_caps_is_any (src_caps)) {
|
||||
GList *factories;
|
||||
GstPadTemplate *padtemp;
|
||||
gboolean found = FALSE;
|
||||
|
||||
factories = spider->factories;
|
||||
while (factories)
|
||||
{
|
||||
if ((padtemp = gst_autoplug_can_connect_src (factories->data, src_caps)))
|
||||
{
|
||||
const GstCaps *caps = gst_pad_template_get_caps (padtemp);
|
||||
GST_DEBUG ("can connect src to pad template: %" GST_PTR_FORMAT, caps);
|
||||
found = TRUE;
|
||||
}
|
||||
factories = factories->next;
|
||||
while (factories) {
|
||||
if ((padtemp =
|
||||
gst_autoplug_can_connect_src (factories->data, src_caps))) {
|
||||
const GstCaps *caps = gst_pad_template_get_caps (padtemp);
|
||||
|
||||
GST_DEBUG ("can connect src to pad template: %" GST_PTR_FORMAT, caps);
|
||||
found = TRUE;
|
||||
}
|
||||
factories = factories->next;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
if (!found) {
|
||||
const char *mime;
|
||||
|
||||
mime = gst_structure_get_name (gst_caps_get_structure (src_caps, 0));
|
||||
|
||||
GST_ELEMENT_ERROR (spider, STREAM, CODEC_NOT_FOUND,
|
||||
(_("There is no element present to handle the stream's mime type %s."), mime),
|
||||
(NULL));
|
||||
GST_ELEMENT_ERROR (spider, STREAM, CODEC_NOT_FOUND,
|
||||
(_("There is no element present to handle the stream's mime type %s."), mime), (NULL));
|
||||
gst_caps_free (src_caps);
|
||||
return;
|
||||
}
|
||||
|
@ -428,10 +451,8 @@ gst_spider_identity_plug (GstSpiderIdentity *ident)
|
|||
|
||||
|
||||
/* get the direction of our ident */
|
||||
if (GST_PAD_PEER (ident->sink))
|
||||
{
|
||||
if (GST_PAD_PEER (ident->src))
|
||||
{
|
||||
if (GST_PAD_PEER (ident->sink)) {
|
||||
if (GST_PAD_PEER (ident->src)) {
|
||||
/* Hey, the ident is linked on both sides */
|
||||
g_warning ("Trying to autoplug a linked element. Aborting...");
|
||||
return;
|
||||
|
@ -439,8 +460,7 @@ gst_spider_identity_plug (GstSpiderIdentity *ident)
|
|||
dir = GST_PAD_SINK;
|
||||
}
|
||||
} else {
|
||||
if (GST_PAD_PEER (ident->src))
|
||||
{
|
||||
if (GST_PAD_PEER (ident->src)) {
|
||||
dir = GST_PAD_SRC;
|
||||
} else {
|
||||
/* the ident isn't linked on either side */
|
||||
|
@ -451,8 +471,7 @@ gst_spider_identity_plug (GstSpiderIdentity *ident)
|
|||
|
||||
/* now iterate all possible pads and link when needed */
|
||||
padlist = gst_element_get_pad_list (GST_ELEMENT (spider));
|
||||
while (padlist)
|
||||
{
|
||||
while (padlist) {
|
||||
GstPad *otherpad;
|
||||
GstSpiderIdentity *peer;
|
||||
|
||||
|
@ -460,169 +479,182 @@ gst_spider_identity_plug (GstSpiderIdentity *ident)
|
|||
otherpad = (GstPad *) GST_GPAD_REALPAD (padlist->data);
|
||||
peer = (GstSpiderIdentity *) GST_PAD_PARENT (otherpad);
|
||||
/* we only want to link to the other side */
|
||||
if (dir != GST_PAD_DIRECTION (otherpad))
|
||||
{
|
||||
if (dir != GST_PAD_DIRECTION (otherpad)) {
|
||||
/* we only link to plugged in elements */
|
||||
if (peer->plugged == TRUE)
|
||||
{
|
||||
/* plug in the right direction */
|
||||
if (dir == GST_PAD_SINK)
|
||||
{
|
||||
if (peer->plugged == TRUE) {
|
||||
/* plug in the right direction */
|
||||
if (dir == GST_PAD_SINK) {
|
||||
conn = gst_spider_link_get (peer);
|
||||
} else {
|
||||
} else {
|
||||
conn = gst_spider_link_get (ident);
|
||||
}
|
||||
if ((GstElement *) spider->sink_ident == conn->current)
|
||||
{
|
||||
}
|
||||
if ((GstElement *) spider->sink_ident == conn->current) {
|
||||
gst_spider_plug (conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
padlist = g_list_next (padlist);
|
||||
}
|
||||
|
||||
ident->plugged = TRUE;
|
||||
|
||||
ident->plugged = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gst_spider_identity_unplug (GstSpiderIdentity *ident)
|
||||
gst_spider_identity_unplug (GstSpiderIdentity * ident)
|
||||
{
|
||||
GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (ident);
|
||||
GList *list = spider->links;
|
||||
|
||||
while (list)
|
||||
{
|
||||
|
||||
while (list) {
|
||||
GstSpiderConnection *conn = list->data;
|
||||
GList *cur = list;
|
||||
|
||||
list = g_list_next (list);
|
||||
if (conn->src == ident)
|
||||
{
|
||||
if (conn->src == ident) {
|
||||
g_list_delete_link (spider->links, cur);
|
||||
gst_spider_link_destroy (conn);
|
||||
}
|
||||
}
|
||||
ident->plugged = FALSE;
|
||||
}
|
||||
|
||||
/* links src to sink using the elementfactories in plugpath
|
||||
* plugpath will be removed afterwards */
|
||||
static GstPadLinkReturn
|
||||
gst_spider_create_and_plug (GstSpiderConnection *conn, GList *plugpath)
|
||||
gst_spider_create_and_plug (GstSpiderConnection * conn, GList * plugpath)
|
||||
{
|
||||
GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (conn->src);
|
||||
GList *endelements = NULL, *templist = NULL;
|
||||
GstElement *element;
|
||||
|
||||
|
||||
/* exit if plugging is already done */
|
||||
if ((GstElement *) conn->src == conn->current)
|
||||
return GST_PAD_LINK_DONE;
|
||||
|
||||
|
||||
/* try to shorten the list at the end and not duplicate link code */
|
||||
if (plugpath != NULL)
|
||||
{
|
||||
if (plugpath != NULL) {
|
||||
templist = g_list_last (plugpath);
|
||||
element = (GstElement *) conn->src;
|
||||
while ((plugpath != NULL) && (element = gst_spider_find_element_to_plug (element, (GstElementFactory *) plugpath->data, GST_PAD_SINK)))
|
||||
{
|
||||
while ((plugpath != NULL)
|
||||
&& (element =
|
||||
gst_spider_find_element_to_plug (element,
|
||||
(GstElementFactory *) plugpath->data, GST_PAD_SINK))) {
|
||||
GList *cur = templist;
|
||||
|
||||
endelements = g_list_prepend (endelements, element);
|
||||
templist = g_list_previous (templist);
|
||||
g_list_delete_link (cur, cur);
|
||||
g_list_delete_link (cur, cur);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* do the linking */
|
||||
while (conn->current != (GstElement *) (endelements == NULL ? conn->src : endelements->data))
|
||||
{
|
||||
while (conn->current != (GstElement *) (endelements ==
|
||||
NULL ? conn->src : endelements->data)) {
|
||||
/* get sink element to plug, src is conn->current */
|
||||
if (plugpath == NULL)
|
||||
{
|
||||
element = (GstElement *) (endelements == NULL ? conn->src : endelements->data);
|
||||
if (plugpath == NULL) {
|
||||
element =
|
||||
(GstElement *) (endelements == NULL ? conn->src : endelements->data);
|
||||
} else {
|
||||
element = gst_element_factory_create ((GstElementFactory *) plugpath->data, NULL);
|
||||
GST_DEBUG ("Adding element %s of type %s and syncing state with autoplugger",
|
||||
GST_ELEMENT_NAME (element), GST_PLUGIN_FEATURE_NAME (plugpath->data));
|
||||
element =
|
||||
gst_element_factory_create ((GstElementFactory *) plugpath->data,
|
||||
NULL);
|
||||
GST_DEBUG
|
||||
("Adding element %s of type %s and syncing state with autoplugger",
|
||||
GST_ELEMENT_NAME (element), GST_PLUGIN_FEATURE_NAME (plugpath->data));
|
||||
gst_bin_add (GST_BIN (spider), element);
|
||||
}
|
||||
/* insert and link new element */
|
||||
if (gst_element_link (conn->current, element)) {
|
||||
gst_element_sync_state_with_parent (element);
|
||||
gst_element_sync_state_with_parent (element);
|
||||
} else {
|
||||
/* check if the src has SOMETIMES templates. If so, link a callback */
|
||||
GList *templs = gst_element_get_pad_template_list (conn->current);
|
||||
|
||||
|
||||
/* remove element that couldn't be linked, if it wasn't the endpoint */
|
||||
if (element != (GstElement *) conn->src)
|
||||
gst_bin_remove (GST_BIN (spider), element);
|
||||
|
||||
gst_bin_remove (GST_BIN (spider), element);
|
||||
|
||||
while (templs) {
|
||||
GstPadTemplate *templ = (GstPadTemplate *) templs->data;
|
||||
if ((GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) && (GST_PAD_TEMPLATE_PRESENCE(templ) == GST_PAD_SOMETIMES))
|
||||
{
|
||||
GST_DEBUG ("adding callback to link element %s to %s", GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (conn->src));
|
||||
conn->signal_id = g_signal_connect (G_OBJECT (conn->current), "new_pad",
|
||||
G_CALLBACK (gst_spider_link_sometimes), conn);
|
||||
GstPadTemplate *templ = (GstPadTemplate *) templs->data;
|
||||
|
||||
if ((GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC)
|
||||
&& (GST_PAD_TEMPLATE_PRESENCE (templ) == GST_PAD_SOMETIMES)) {
|
||||
GST_DEBUG ("adding callback to link element %s to %s",
|
||||
GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (conn->src));
|
||||
conn->signal_id =
|
||||
g_signal_connect (G_OBJECT (conn->current), "new_pad",
|
||||
G_CALLBACK (gst_spider_link_sometimes), conn);
|
||||
g_list_free (plugpath);
|
||||
return GST_PAD_LINK_DELAYED;
|
||||
}
|
||||
templs = g_list_next (templs);
|
||||
}
|
||||
templs = g_list_next (templs);
|
||||
}
|
||||
GST_DEBUG ("no chance to link element %s to %s", GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (conn->src));
|
||||
GST_DEBUG ("no chance to link element %s to %s",
|
||||
GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (conn->src));
|
||||
g_list_free (plugpath);
|
||||
return GST_PAD_LINK_REFUSED;
|
||||
}
|
||||
GST_DEBUG ("added element %s and attached it to element %s", GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (conn->current));
|
||||
GST_DEBUG ("added element %s and attached it to element %s",
|
||||
GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (conn->current));
|
||||
gst_spider_link_add (conn, element);
|
||||
if (plugpath != NULL)
|
||||
plugpath = g_list_delete_link (plugpath, plugpath);
|
||||
}
|
||||
|
||||
|
||||
/* ref all elements at the end */
|
||||
while (endelements)
|
||||
{
|
||||
while (endelements) {
|
||||
gst_spider_link_add (conn, endelements->data);
|
||||
endelements = g_list_delete_link (endelements, endelements);
|
||||
}
|
||||
|
||||
|
||||
return GST_PAD_LINK_DONE;
|
||||
}
|
||||
|
||||
/* checks, if src is already linked to an element from factory fac on direction dir */
|
||||
static GstElement *
|
||||
gst_spider_find_element_to_plug (GstElement *src, GstElementFactory *fac, GstPadDirection dir)
|
||||
gst_spider_find_element_to_plug (GstElement * src, GstElementFactory * fac,
|
||||
GstPadDirection dir)
|
||||
{
|
||||
GList *padlist = GST_ELEMENT_PADS (src);
|
||||
|
||||
while (padlist)
|
||||
{
|
||||
|
||||
while (padlist) {
|
||||
GstPad *pad = (GstPad *) GST_PAD_REALIZE (padlist->data);
|
||||
|
||||
/* is the pad on the right side and is it linked? */
|
||||
if ((GST_PAD_DIRECTION (pad) == dir) && (pad = (GstPad *) (GST_RPAD_PEER (pad))))
|
||||
{
|
||||
if ((GST_PAD_DIRECTION (pad) == dir)
|
||||
&& (pad = (GstPad *) (GST_RPAD_PEER (pad)))) {
|
||||
/* is the element the pad is linked to of the right type? */
|
||||
GstElement *element = GST_PAD_PARENT (pad);
|
||||
|
||||
if (G_TYPE_FROM_INSTANCE (element) == gst_element_factory_get_element_type (fac)) {
|
||||
return element;
|
||||
|
||||
if (G_TYPE_FROM_INSTANCE (element) ==
|
||||
gst_element_factory_get_element_type (fac)) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
padlist = g_list_next (padlist);
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* try to establish the link */
|
||||
static GstPadLinkReturn
|
||||
gst_spider_plug (GstSpiderConnection *conn)
|
||||
gst_spider_plug (GstSpiderConnection * conn)
|
||||
{
|
||||
GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (conn->src);
|
||||
|
||||
if ((GstElement *) conn->src == conn->current)
|
||||
return GST_PAD_LINK_DONE;
|
||||
if ((GstElement *) spider->sink_ident == conn->current)
|
||||
return gst_spider_plug_from_srcpad (conn, spider->sink_ident->src);
|
||||
g_warning ("FIXME: autoplugging only possible from GstSpiderIdentity conn->sink yet (yep, that's technical)\n");
|
||||
g_warning
|
||||
("FIXME: autoplugging only possible from GstSpiderIdentity conn->sink yet (yep, that's technical)\n");
|
||||
return GST_PAD_LINK_REFUSED;
|
||||
}
|
||||
|
||||
/* try to establish the link using this pad */
|
||||
static GstPadLinkReturn
|
||||
gst_spider_plug_from_srcpad (GstSpiderConnection *conn, GstPad *srcpad)
|
||||
gst_spider_plug_from_srcpad (GstSpiderConnection * conn, GstPad * srcpad)
|
||||
{
|
||||
GstElement *element;
|
||||
GList *plugpath;
|
||||
|
@ -633,37 +665,38 @@ gst_spider_plug_from_srcpad (GstSpiderConnection *conn, GstPad *srcpad)
|
|||
GstCaps *caps2;
|
||||
|
||||
g_assert ((GstElement *) GST_OBJECT_PARENT (srcpad) == conn->current);
|
||||
GST_DEBUG ("trying to plug from %s:%s to %s",
|
||||
GST_DEBUG_PAD_NAME (srcpad), GST_ELEMENT_NAME (conn->src));
|
||||
|
||||
GST_DEBUG ("trying to plug from %s:%s to %s",
|
||||
GST_DEBUG_PAD_NAME (srcpad), GST_ELEMENT_NAME (conn->src));
|
||||
|
||||
/* see if they match already */
|
||||
if (gst_pad_link (srcpad, conn->src->sink)) {
|
||||
GST_DEBUG ("%s:%s and %s:%s can link directly",
|
||||
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (conn->src->sink));
|
||||
GST_DEBUG ("%s:%s and %s:%s can link directly",
|
||||
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (conn->src->sink));
|
||||
gst_pad_unlink (srcpad, conn->src->sink);
|
||||
gst_spider_create_and_plug (conn, NULL);
|
||||
return GST_PAD_LINK_OK;
|
||||
}
|
||||
|
||||
|
||||
/* find a path from src to sink */
|
||||
caps1 = gst_pad_get_caps (srcpad);
|
||||
caps2 = gst_pad_get_caps (conn->src->sink);
|
||||
plugpath = gst_autoplug_sp (caps1, caps2, spider->factories);
|
||||
gst_caps_free (caps1);
|
||||
gst_caps_free (caps2);
|
||||
|
||||
|
||||
/* prints out the path that was found for plugging */
|
||||
/* g_print ("found path from %s to %s:\n", GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (conn->src));
|
||||
templist = plugpath;
|
||||
while (templist)
|
||||
{
|
||||
g_print("%s\n", GST_OBJECT_NAME (templist->data));
|
||||
templist = g_list_next (templist);
|
||||
}*/
|
||||
|
||||
templist = plugpath;
|
||||
while (templist)
|
||||
{
|
||||
g_print("%s\n", GST_OBJECT_NAME (templist->data));
|
||||
templist = g_list_next (templist);
|
||||
} */
|
||||
|
||||
/* if there is no way to plug: return */
|
||||
if (plugpath == NULL) {
|
||||
GST_DEBUG ("no chance to plug from %s to %s", GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (conn->src));
|
||||
GST_DEBUG ("no chance to plug from %s to %s",
|
||||
GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (conn->src));
|
||||
return GST_PAD_LINK_REFUSED;
|
||||
}
|
||||
GST_DEBUG ("found a link that needs %d elements", g_list_length (plugpath));
|
||||
|
@ -673,53 +706,50 @@ gst_spider_plug_from_srcpad (GstSpiderConnection *conn, GstPad *srcpad)
|
|||
* plugging and alter the plugpath to represent the elements, that must be plugged
|
||||
*/
|
||||
element = conn->current;
|
||||
while ((plugpath != NULL) && (element = gst_spider_find_element_to_plug (element, (GstElementFactory *) plugpath->data, GST_PAD_SRC)))
|
||||
{
|
||||
while ((plugpath != NULL)
|
||||
&& (element =
|
||||
gst_spider_find_element_to_plug (element,
|
||||
(GstElementFactory *) plugpath->data, GST_PAD_SRC))) {
|
||||
gst_spider_link_add (conn, element);
|
||||
plugpath = g_list_delete_link (plugpath, plugpath);
|
||||
}
|
||||
|
||||
GST_DEBUG ("%d elements must be inserted to establish the link", g_list_length (plugpath));
|
||||
|
||||
GST_DEBUG ("%d elements must be inserted to establish the link",
|
||||
g_list_length (plugpath));
|
||||
/* create the elements and plug them */
|
||||
result = gst_spider_create_and_plug (conn, plugpath);
|
||||
|
||||
|
||||
/* reset the "current" element */
|
||||
if (result == GST_PAD_LINK_REFUSED)
|
||||
{
|
||||
gst_spider_link_reset (conn, startelement);
|
||||
if (result == GST_PAD_LINK_REFUSED) {
|
||||
gst_spider_link_reset (conn, startelement);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GstElementDetails gst_spider_details = GST_ELEMENT_DETAILS (
|
||||
"Spider",
|
||||
"Generic",
|
||||
"Automatically link sinks and sources",
|
||||
"Benjamin Otte <in7y118@public.uni-hamburg.de>"
|
||||
);
|
||||
GstElementDetails gst_spider_details = GST_ELEMENT_DETAILS ("Spider",
|
||||
"Generic",
|
||||
"Automatically link sinks and sources",
|
||||
"Benjamin Otte <in7y118@public.uni-hamburg.de>");
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin *plugin)
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
GST_DEBUG_CATEGORY_INIT (gst_spider_debug, "spider", 0, "spider autoplugging element");
|
||||
GST_DEBUG_CATEGORY_INIT (gst_spider_debug, "spider", 0,
|
||||
"spider autoplugging element");
|
||||
|
||||
if (!gst_element_register (plugin, "spider", GST_RANK_SECONDARY, GST_TYPE_SPIDER))
|
||||
if (!gst_element_register (plugin, "spider", GST_RANK_SECONDARY,
|
||||
GST_TYPE_SPIDER))
|
||||
return FALSE;
|
||||
if (!gst_element_register (plugin, "spideridentity", GST_RANK_NONE, GST_TYPE_SPIDER_IDENTITY))
|
||||
if (!gst_element_register (plugin, "spideridentity", GST_RANK_NONE,
|
||||
GST_TYPE_SPIDER_IDENTITY))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (
|
||||
GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"gstspider",
|
||||
"a 1:n autoplugger",
|
||||
plugin_init,
|
||||
VERSION,
|
||||
GST_LICENSE,
|
||||
GST_PACKAGE,
|
||||
GST_ORIGIN
|
||||
)
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"gstspider",
|
||||
"a 1:n autoplugger",
|
||||
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
|
||||
|
|
|
@ -19,17 +19,16 @@
|
|||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GST_SPIDER_H__
|
||||
#define __GST_SPIDER_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include "gstspideridentity.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
extern GstElementDetails gst_spider_details;
|
||||
GST_DEBUG_CATEGORY_EXTERN(gst_spider_debug);
|
||||
G_BEGIN_DECLS extern GstElementDetails gst_spider_details;
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (gst_spider_debug);
|
||||
|
||||
/*
|
||||
* Theory of operation:
|
||||
|
@ -46,7 +45,8 @@ GST_DEBUG_CATEGORY_EXTERN(gst_spider_debug);
|
|||
* are refcounted once for every path.
|
||||
* A GstSpider keeps a list of all GstSpiderConnections in it.
|
||||
*/
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
GstSpiderIdentity *src;
|
||||
/* dunno if the path should stay here or if its too much load.
|
||||
* it's at least easier then always searching it */
|
||||
|
@ -60,35 +60,36 @@ typedef struct {
|
|||
#define GST_SPIDER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SPIDER,GstSpider))
|
||||
#define GST_SPIDER_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SPIDER,GstSpiderClass))
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SPIDER,GstSpiderClass))
|
||||
#define GST_IS_SPIDER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SPIDER))
|
||||
#define GST_IS_SPIDER_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SPIDER))
|
||||
|
||||
|
||||
typedef struct _GstSpider GstSpider;
|
||||
typedef struct _GstSpiderClass GstSpiderClass;
|
||||
|
||||
struct _GstSpider {
|
||||
GstBin parent;
|
||||
|
||||
GstSpiderIdentity *sink_ident;
|
||||
GList * factories; /* factories to use for plugging */
|
||||
struct _GstSpider
|
||||
{
|
||||
GstBin parent;
|
||||
|
||||
GList * links; /* GStSpiderConnection list of all links */
|
||||
GstSpiderIdentity *sink_ident;
|
||||
GList *factories; /* factories to use for plugging */
|
||||
|
||||
GList *links; /* GStSpiderConnection list of all links */
|
||||
};
|
||||
|
||||
struct _GstSpiderClass {
|
||||
|
||||
struct _GstSpiderClass
|
||||
{
|
||||
GstBinClass parent_class;
|
||||
};
|
||||
|
||||
/* default initialization stuff */
|
||||
GType gst_spider_get_type (void);
|
||||
GType gst_spider_get_type (void);
|
||||
|
||||
/* private link functions to be called by GstSpiderIdentity */
|
||||
void gst_spider_identity_plug (GstSpiderIdentity *ident);
|
||||
void gst_spider_identity_unplug (GstSpiderIdentity *ident);
|
||||
void gst_spider_identity_plug (GstSpiderIdentity * ident);
|
||||
void gst_spider_identity_unplug (GstSpiderIdentity * ident);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_SPIDER_H__ */
|
||||
|
|
|
@ -30,159 +30,174 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_spider_identity_debug);
|
||||
#define GST_CAT_DEFAULT gst_spider_identity_debug
|
||||
|
||||
static GstElementDetails gst_spider_identity_details = GST_ELEMENT_DETAILS (
|
||||
"SpiderIdentity",
|
||||
"Generic",
|
||||
"Link between spider and outside elements",
|
||||
"Benjamin Otte <in7y118@public.uni-hamburg.de>"
|
||||
);
|
||||
static GstElementDetails gst_spider_identity_details =
|
||||
GST_ELEMENT_DETAILS ("SpiderIdentity",
|
||||
"Generic",
|
||||
"Link between spider and outside elements",
|
||||
"Benjamin Otte <in7y118@public.uni-hamburg.de>");
|
||||
|
||||
|
||||
/* generic templates
|
||||
* delete me when meging with spider.c
|
||||
*/
|
||||
static GstStaticPadTemplate spider_src_factory =
|
||||
GST_STATIC_PAD_TEMPLATE (
|
||||
"src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
static GstStaticPadTemplate spider_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static GstStaticPadTemplate spider_sink_factory =
|
||||
GST_STATIC_PAD_TEMPLATE (
|
||||
"sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
/* SpiderIdentity signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0
|
||||
/* FILL ME */
|
||||
/* FILL ME */
|
||||
};
|
||||
|
||||
/* GObject stuff */
|
||||
static void gst_spider_identity_class_init (GstSpiderIdentityClass *klass);
|
||||
static void gst_spider_identity_init (GstSpiderIdentity *spider_identity);
|
||||
static void gst_spider_identity_class_init (GstSpiderIdentityClass * klass);
|
||||
static void gst_spider_identity_init (GstSpiderIdentity * spider_identity);
|
||||
|
||||
/* functions set in pads, elements and stuff */
|
||||
static void gst_spider_identity_chain (GstPad *pad, GstBuffer *buf);
|
||||
static GstElementStateReturn gst_spider_identity_change_state (GstElement *element);
|
||||
static GstPadLinkReturn gst_spider_identity_link (GstPad *pad, const GstCaps *caps);
|
||||
static GstCaps * gst_spider_identity_getcaps (GstPad *pad);
|
||||
/* loop functions */
|
||||
static void gst_spider_identity_dumb_loop (GstSpiderIdentity *ident);
|
||||
static void gst_spider_identity_src_loop (GstSpiderIdentity *ident);
|
||||
static void gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *ident);
|
||||
static void gst_spider_identity_chain (GstPad * pad, GstBuffer * buf);
|
||||
static GstElementStateReturn gst_spider_identity_change_state (GstElement *
|
||||
element);
|
||||
static GstPadLinkReturn gst_spider_identity_link (GstPad * pad,
|
||||
const GstCaps * caps);
|
||||
static GstCaps *gst_spider_identity_getcaps (GstPad * pad);
|
||||
|
||||
static gboolean gst_spider_identity_handle_src_event (GstPad *pad, GstEvent *event);
|
||||
/* loop functions */
|
||||
static void gst_spider_identity_dumb_loop (GstSpiderIdentity * ident);
|
||||
static void gst_spider_identity_src_loop (GstSpiderIdentity * ident);
|
||||
static void gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *
|
||||
ident);
|
||||
|
||||
static gboolean gst_spider_identity_handle_src_event (GstPad * pad,
|
||||
GstEvent * event);
|
||||
|
||||
/* other functions */
|
||||
static void gst_spider_identity_start_type_finding (GstSpiderIdentity *ident);
|
||||
static void gst_spider_identity_start_type_finding (GstSpiderIdentity * ident);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
|
||||
static GstElementClass * parent_class = NULL;
|
||||
/* no signals
|
||||
static guint gst_spider_identity_signals[LAST_SIGNAL] = { 0 }; */
|
||||
|
||||
GType
|
||||
gst_spider_identity_get_type (void)
|
||||
gst_spider_identity_get_type (void)
|
||||
{
|
||||
static GType spider_identity_type = 0;
|
||||
|
||||
if (!spider_identity_type) {
|
||||
static const GTypeInfo spider_identity_info = {
|
||||
sizeof(GstSpiderIdentityClass), NULL,
|
||||
sizeof (GstSpiderIdentityClass), NULL,
|
||||
NULL,
|
||||
(GClassInitFunc)gst_spider_identity_class_init,
|
||||
(GClassInitFunc) gst_spider_identity_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(GstSpiderIdentity),
|
||||
sizeof (GstSpiderIdentity),
|
||||
0,
|
||||
(GInstanceInitFunc)gst_spider_identity_init,
|
||||
(GInstanceInitFunc) gst_spider_identity_init,
|
||||
};
|
||||
spider_identity_type = g_type_register_static (GST_TYPE_ELEMENT, "GstSpiderIdentity",
|
||||
&spider_identity_info, 0);
|
||||
GST_DEBUG_CATEGORY_INIT (gst_spider_identity_debug, "spideridentity",
|
||||
0, "spider autoplugging proxy element");
|
||||
spider_identity_type =
|
||||
g_type_register_static (GST_TYPE_ELEMENT, "GstSpiderIdentity",
|
||||
&spider_identity_info, 0);
|
||||
GST_DEBUG_CATEGORY_INIT (gst_spider_identity_debug, "spideridentity", 0,
|
||||
"spider autoplugging proxy element");
|
||||
}
|
||||
return spider_identity_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_spider_identity_class_init (GstSpiderIdentityClass *klass)
|
||||
static void
|
||||
gst_spider_identity_class_init (GstSpiderIdentityClass * klass)
|
||||
{
|
||||
GstElementClass *gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
|
||||
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
|
||||
|
||||
|
||||
/* add our two pad templates */
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&spider_src_factory));
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&spider_sink_factory));
|
||||
gst_element_class_set_details (gstelement_class, &gst_spider_identity_details);
|
||||
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_spider_identity_change_state);
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_spider_identity_request_new_pad);
|
||||
gst_element_class_set_details (gstelement_class,
|
||||
&gst_spider_identity_details);
|
||||
|
||||
gstelement_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_change_state);
|
||||
gstelement_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_request_new_pad);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_spider_identity_init (GstSpiderIdentity *ident)
|
||||
static void
|
||||
gst_spider_identity_init (GstSpiderIdentity * ident)
|
||||
{
|
||||
/* sink */
|
||||
ident->sink = gst_pad_new_from_template (
|
||||
gst_static_pad_template_get (&spider_sink_factory), "sink");
|
||||
ident->sink =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&spider_sink_factory), "sink");
|
||||
gst_element_add_pad (GST_ELEMENT (ident), ident->sink);
|
||||
gst_pad_set_link_function (ident->sink, GST_DEBUG_FUNCPTR (gst_spider_identity_link));
|
||||
gst_pad_set_getcaps_function (ident->sink, GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
|
||||
gst_pad_set_link_function (ident->sink,
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_link));
|
||||
gst_pad_set_getcaps_function (ident->sink,
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
|
||||
/* src */
|
||||
ident->src = gst_pad_new_from_template (
|
||||
gst_static_pad_template_get (&spider_src_factory), "src");
|
||||
ident->src =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&spider_src_factory), "src");
|
||||
gst_element_add_pad (GST_ELEMENT (ident), ident->src);
|
||||
gst_pad_set_link_function (ident->src, GST_DEBUG_FUNCPTR (gst_spider_identity_link));
|
||||
gst_pad_set_getcaps_function (ident->src, GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
|
||||
gst_pad_set_event_function (ident->src, GST_DEBUG_FUNCPTR (gst_spider_identity_handle_src_event));
|
||||
gst_pad_set_link_function (ident->src,
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_link));
|
||||
gst_pad_set_getcaps_function (ident->src,
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
|
||||
gst_pad_set_event_function (ident->src,
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_handle_src_event));
|
||||
|
||||
/* variables */
|
||||
ident->plugged = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_spider_identity_chain (GstPad *pad, GstBuffer *buf)
|
||||
static void
|
||||
gst_spider_identity_chain (GstPad * pad, GstBuffer * buf)
|
||||
{
|
||||
GstSpiderIdentity *ident;
|
||||
|
||||
/*g_print ("chaining on pad %s:%s with buffer %p\n", GST_DEBUG_PAD_NAME (pad), buf);*/
|
||||
|
||||
/*g_print ("chaining on pad %s:%s with buffer %p\n", GST_DEBUG_PAD_NAME (pad), buf); */
|
||||
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_PAD (pad));
|
||||
if (buf == NULL) return;
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
ident = GST_SPIDER_IDENTITY (gst_pad_get_parent (pad));
|
||||
|
||||
if (GST_IS_EVENT (buf)) {
|
||||
/* start hack for current event stuff here */
|
||||
/* check for unlinked elements and send them the EOS event, too */
|
||||
if (GST_EVENT_TYPE (GST_EVENT (buf)) == GST_EVENT_EOS)
|
||||
{
|
||||
if (GST_EVENT_TYPE (GST_EVENT (buf)) == GST_EVENT_EOS) {
|
||||
GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (ident);
|
||||
GList *list = spider->links;
|
||||
while (list)
|
||||
{
|
||||
|
||||
while (list) {
|
||||
GstSpiderConnection *conn = (GstSpiderConnection *) list->data;
|
||||
|
||||
list = g_list_next (list);
|
||||
if (conn->current != (GstElement *) conn->src) {
|
||||
GST_DEBUG ("sending EOS to unconnected element %s from %s",
|
||||
GST_ELEMENT_NAME (conn->src), GST_ELEMENT_NAME (ident));
|
||||
gst_pad_push (conn->src->src, GST_DATA (GST_BUFFER (gst_event_new (GST_EVENT_EOS))));
|
||||
gst_element_set_eos (GST_ELEMENT (conn->src));
|
||||
if (conn->current != (GstElement *) conn->src) {
|
||||
GST_DEBUG ("sending EOS to unconnected element %s from %s",
|
||||
GST_ELEMENT_NAME (conn->src), GST_ELEMENT_NAME (ident));
|
||||
gst_pad_push (conn->src->src,
|
||||
GST_DATA (GST_BUFFER (gst_event_new (GST_EVENT_EOS))));
|
||||
gst_element_set_eos (GST_ELEMENT (conn->src));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -194,40 +209,48 @@ gst_spider_identity_chain (GstPad *pad, GstBuffer *buf)
|
|||
|
||||
if ((ident->src != NULL) && (GST_PAD_PEER (ident->src) != NULL)) {
|
||||
/* g_print("pushing buffer %p (refcount %d - buffersize %d) to pad %s:%s\n", buf, GST_BUFFER_REFCOUNT (buf), GST_BUFFER_SIZE (buf), GST_DEBUG_PAD_NAME (ident->src)); */
|
||||
GST_LOG ( "push %p %" G_GINT64_FORMAT, buf, GST_BUFFER_OFFSET (buf));
|
||||
GST_LOG ("push %p %" G_GINT64_FORMAT, buf, GST_BUFFER_OFFSET (buf));
|
||||
gst_pad_push (ident->src, GST_DATA (buf));
|
||||
} else if (GST_IS_BUFFER (buf)) {
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
}
|
||||
GstSpiderIdentity*
|
||||
gst_spider_identity_new_src (gchar *name)
|
||||
GstSpiderIdentity *
|
||||
gst_spider_identity_new_src (gchar * name)
|
||||
{
|
||||
GstSpiderIdentity *ret = (GstSpiderIdentity *) gst_element_factory_make ("spideridentity", name);
|
||||
GstSpiderIdentity *ret =
|
||||
(GstSpiderIdentity *) gst_element_factory_make ("spideridentity", name);
|
||||
/* set the right functions */
|
||||
gst_element_set_loop_function (GST_ELEMENT (ret), (GstElementLoopFunction) GST_DEBUG_FUNCPTR (gst_spider_identity_src_loop));
|
||||
|
||||
gst_element_set_loop_function (GST_ELEMENT (ret),
|
||||
(GstElementLoopFunction)
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_src_loop));
|
||||
|
||||
return ret;
|
||||
}
|
||||
GstSpiderIdentity*
|
||||
gst_spider_identity_new_sink (gchar *name)
|
||||
|
||||
GstSpiderIdentity *
|
||||
gst_spider_identity_new_sink (gchar * name)
|
||||
{
|
||||
GstSpiderIdentity *ret = (GstSpiderIdentity *) gst_element_factory_make ("spideridentity", name);
|
||||
GstSpiderIdentity *ret =
|
||||
(GstSpiderIdentity *) gst_element_factory_make ("spideridentity", name);
|
||||
|
||||
/* set the right functions */
|
||||
gst_element_set_loop_function (GST_ELEMENT (ret), (GstElementLoopFunction) GST_DEBUG_FUNCPTR (gst_spider_identity_dumb_loop));
|
||||
gst_element_set_loop_function (GST_ELEMENT (ret),
|
||||
(GstElementLoopFunction)
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_dumb_loop));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* shamelessly stolen from gstqueue.c to get proxy links */
|
||||
static GstPadLinkReturn
|
||||
gst_spider_identity_link (GstPad *pad, const GstCaps *caps)
|
||||
gst_spider_identity_link (GstPad * pad, const GstCaps * caps)
|
||||
{
|
||||
GstSpiderIdentity *spider_identity = GST_SPIDER_IDENTITY (gst_pad_get_parent (pad));
|
||||
GstSpiderIdentity *spider_identity =
|
||||
GST_SPIDER_IDENTITY (gst_pad_get_parent (pad));
|
||||
GstPad *otherpad;
|
||||
|
||||
if (pad == spider_identity->src)
|
||||
if (pad == spider_identity->src)
|
||||
otherpad = spider_identity->sink;
|
||||
else
|
||||
otherpad = spider_identity->src;
|
||||
|
@ -239,13 +262,13 @@ gst_spider_identity_link (GstPad *pad, const GstCaps *caps)
|
|||
return gst_pad_try_set_caps (otherpad, caps);
|
||||
}
|
||||
|
||||
static GstCaps*
|
||||
gst_spider_identity_getcaps (GstPad *pad)
|
||||
static GstCaps *
|
||||
gst_spider_identity_getcaps (GstPad * pad)
|
||||
{
|
||||
GstSpiderIdentity *ident = GST_SPIDER_IDENTITY (gst_pad_get_parent (pad));
|
||||
GstPad *otherpad;
|
||||
|
||||
if (pad == ident->src)
|
||||
if (pad == ident->src)
|
||||
otherpad = ident->sink;
|
||||
else
|
||||
otherpad = ident->src;
|
||||
|
@ -253,8 +276,10 @@ gst_spider_identity_getcaps (GstPad *pad)
|
|||
if (otherpad != NULL) {
|
||||
if (GST_PAD_PEER (otherpad)) {
|
||||
GstCaps *ret = gst_pad_get_allowed_caps (otherpad);
|
||||
|
||||
if (ident->caps) {
|
||||
GstCaps *ret2 = gst_caps_intersect (ident->caps, ret);
|
||||
|
||||
gst_caps_free (ret);
|
||||
ret = ret2;
|
||||
}
|
||||
|
@ -267,44 +292,52 @@ gst_spider_identity_getcaps (GstPad *pad)
|
|||
return gst_caps_new_any ();
|
||||
}
|
||||
|
||||
GstPad*
|
||||
gst_spider_identity_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *name)
|
||||
GstPad *
|
||||
gst_spider_identity_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * name)
|
||||
{
|
||||
GstSpiderIdentity *ident;
|
||||
|
||||
|
||||
/*checks */
|
||||
g_return_val_if_fail (templ != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
|
||||
ident = GST_SPIDER_IDENTITY (element);
|
||||
g_return_val_if_fail (ident != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_SPIDER_IDENTITY (ident), NULL);
|
||||
|
||||
switch (GST_PAD_TEMPLATE_DIRECTION (templ))
|
||||
{
|
||||
|
||||
switch (GST_PAD_TEMPLATE_DIRECTION (templ)) {
|
||||
case GST_PAD_SINK:
|
||||
if (ident->sink != NULL) break;
|
||||
if (ident->sink != NULL)
|
||||
break;
|
||||
/* sink */
|
||||
GST_DEBUG ( "element %s requests new sink pad", GST_ELEMENT_NAME(ident));
|
||||
GST_DEBUG ("element %s requests new sink pad", GST_ELEMENT_NAME (ident));
|
||||
ident->sink = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (ident), ident->sink);
|
||||
gst_pad_set_link_function (ident->sink, GST_DEBUG_FUNCPTR (gst_spider_identity_link));
|
||||
gst_pad_set_getcaps_function (ident->sink, GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
|
||||
gst_pad_set_link_function (ident->sink,
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_link));
|
||||
gst_pad_set_getcaps_function (ident->sink,
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
|
||||
return ident->sink;
|
||||
case GST_PAD_SRC:
|
||||
/* src */
|
||||
if (ident->src != NULL) break;
|
||||
GST_DEBUG ( "element %s requests new src pad", GST_ELEMENT_NAME(ident));
|
||||
if (ident->src != NULL)
|
||||
break;
|
||||
GST_DEBUG ("element %s requests new src pad", GST_ELEMENT_NAME (ident));
|
||||
ident->src = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_element_add_pad (GST_ELEMENT (ident), ident->src);
|
||||
gst_pad_set_link_function (ident->src, GST_DEBUG_FUNCPTR (gst_spider_identity_link));
|
||||
gst_pad_set_getcaps_function (ident->src, GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
|
||||
gst_pad_set_event_function (ident->src, GST_DEBUG_FUNCPTR (gst_spider_identity_handle_src_event));
|
||||
gst_pad_set_link_function (ident->src,
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_link));
|
||||
gst_pad_set_getcaps_function (ident->src,
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
|
||||
gst_pad_set_event_function (ident->src,
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_handle_src_event));
|
||||
return ident->src;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
GST_DEBUG ( "element %s requested a new pad but none could be created", GST_ELEMENT_NAME(ident));
|
||||
|
||||
GST_DEBUG ("element %s requested a new pad but none could be created",
|
||||
GST_ELEMENT_NAME (ident));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -314,17 +347,17 @@ gst_spider_identity_request_new_pad (GstElement *element, GstPadTemplate *templ
|
|||
* ...
|
||||
*/
|
||||
static GstElementStateReturn
|
||||
gst_spider_identity_change_state (GstElement *element)
|
||||
gst_spider_identity_change_state (GstElement * element)
|
||||
{
|
||||
GstSpiderIdentity *ident;
|
||||
GstSpider *spider;
|
||||
GstElementStateReturn ret = GST_STATE_SUCCESS;
|
||||
|
||||
|
||||
/* element check */
|
||||
ident = GST_SPIDER_IDENTITY (element);
|
||||
g_return_val_if_fail (ident != NULL, GST_STATE_FAILURE);
|
||||
g_return_val_if_fail (GST_IS_SPIDER_IDENTITY (ident), GST_STATE_FAILURE);
|
||||
|
||||
|
||||
switch (GST_STATE_TRANSITION (element)) {
|
||||
case GST_STATE_PAUSED_TO_READY:
|
||||
gst_caps_replace (&ident->caps, NULL);
|
||||
|
@ -334,55 +367,58 @@ gst_spider_identity_change_state (GstElement *element)
|
|||
spider = GST_SPIDER (GST_ELEMENT_PARENT (ident));
|
||||
g_return_val_if_fail (spider != NULL, GST_STATE_FAILURE);
|
||||
g_return_val_if_fail (GST_IS_SPIDER (spider), GST_STATE_FAILURE);
|
||||
|
||||
|
||||
/* start typefinding or plugging */
|
||||
if ((GST_RPAD_PEER (ident->sink) != NULL) && (GST_RPAD_PEER (ident->src) == NULL))
|
||||
{
|
||||
GstCaps *caps = gst_pad_get_caps ((GstPad *) GST_PAD_PEER (ident->sink));
|
||||
if (gst_caps_is_any (caps) || gst_caps_is_empty (caps))
|
||||
{
|
||||
gst_spider_identity_start_type_finding (ident);
|
||||
if ((GST_RPAD_PEER (ident->sink) != NULL)
|
||||
&& (GST_RPAD_PEER (ident->src) == NULL)) {
|
||||
GstCaps *caps =
|
||||
gst_pad_get_caps ((GstPad *) GST_PAD_PEER (ident->sink));
|
||||
if (gst_caps_is_any (caps) || gst_caps_is_empty (caps)) {
|
||||
gst_spider_identity_start_type_finding (ident);
|
||||
gst_caps_free (caps);
|
||||
break;
|
||||
} else {
|
||||
gst_spider_identity_plug (ident);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
gst_spider_identity_plug (ident);
|
||||
}
|
||||
gst_caps_free (caps);
|
||||
}
|
||||
/* autoplug on src */
|
||||
if ((GST_RPAD_PEER (ident->src) != NULL) && (GST_RPAD_PEER (ident->sink) == NULL))
|
||||
{
|
||||
gst_spider_identity_plug (ident);
|
||||
if ((GST_RPAD_PEER (ident->src) != NULL)
|
||||
&& (GST_RPAD_PEER (ident->sink) == NULL)) {
|
||||
gst_spider_identity_plug (ident);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((ret != GST_STATE_FAILURE) && (GST_ELEMENT_CLASS (parent_class)->change_state))
|
||||
|
||||
if ((ret != GST_STATE_FAILURE)
|
||||
&& (GST_ELEMENT_CLASS (parent_class)->change_state))
|
||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_spider_identity_start_type_finding (GstSpiderIdentity *ident)
|
||||
gst_spider_identity_start_type_finding (GstSpiderIdentity * ident)
|
||||
{
|
||||
/* GstElement* typefind;
|
||||
gchar *name;*/
|
||||
gboolean restart = FALSE;
|
||||
|
||||
GST_DEBUG ("element %s starts typefinding", GST_ELEMENT_NAME(ident));
|
||||
if (GST_STATE (GST_ELEMENT_PARENT (ident)) == GST_STATE_PLAYING)
|
||||
{
|
||||
gst_element_set_state (GST_ELEMENT (GST_ELEMENT_PARENT (ident)), GST_STATE_PAUSED);
|
||||
|
||||
GST_DEBUG ("element %s starts typefinding", GST_ELEMENT_NAME (ident));
|
||||
if (GST_STATE (GST_ELEMENT_PARENT (ident)) == GST_STATE_PLAYING) {
|
||||
gst_element_set_state (GST_ELEMENT (GST_ELEMENT_PARENT (ident)),
|
||||
GST_STATE_PAUSED);
|
||||
restart = TRUE;
|
||||
}
|
||||
|
||||
gst_element_set_loop_function (GST_ELEMENT (ident), (GstElementLoopFunction) GST_DEBUG_FUNCPTR (gst_spider_identity_sink_loop_type_finding));
|
||||
gst_element_set_loop_function (GST_ELEMENT (ident),
|
||||
(GstElementLoopFunction)
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_sink_loop_type_finding));
|
||||
|
||||
if (restart)
|
||||
{
|
||||
gst_element_set_state (GST_ELEMENT (GST_ELEMENT_PARENT (ident)), GST_STATE_PLAYING);
|
||||
if (restart) {
|
||||
gst_element_set_state (GST_ELEMENT (GST_ELEMENT_PARENT (ident)),
|
||||
GST_STATE_PLAYING);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -390,7 +426,7 @@ gst_spider_identity_start_type_finding (GstSpiderIdentity *ident)
|
|||
* we have to use a dumb one
|
||||
*/
|
||||
static void
|
||||
gst_spider_identity_dumb_loop (GstSpiderIdentity *ident)
|
||||
gst_spider_identity_dumb_loop (GstSpiderIdentity * ident)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
|
||||
|
@ -402,27 +438,31 @@ gst_spider_identity_dumb_loop (GstSpiderIdentity *ident)
|
|||
|
||||
gst_spider_identity_chain (ident->sink, buf);
|
||||
}
|
||||
|
||||
/* do nothing until we're linked - then disable yourself
|
||||
*/
|
||||
static void
|
||||
gst_spider_identity_src_loop (GstSpiderIdentity *ident)
|
||||
gst_spider_identity_src_loop (GstSpiderIdentity * ident)
|
||||
{
|
||||
/* checks - disable for speed */
|
||||
g_return_if_fail (ident != NULL);
|
||||
g_return_if_fail (GST_IS_SPIDER_IDENTITY (ident));
|
||||
|
||||
|
||||
/* we don't want a loop function if we're plugged */
|
||||
if (ident->sink && GST_PAD_PEER (ident->sink))
|
||||
{
|
||||
gst_element_set_loop_function (GST_ELEMENT (ident), (GstElementLoopFunction) GST_DEBUG_FUNCPTR (gst_spider_identity_dumb_loop));
|
||||
if (ident->sink && GST_PAD_PEER (ident->sink)) {
|
||||
gst_element_set_loop_function (GST_ELEMENT (ident),
|
||||
(GstElementLoopFunction)
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_dumb_loop));
|
||||
gst_spider_identity_dumb_loop (ident);
|
||||
return;
|
||||
}
|
||||
gst_element_interrupt (GST_ELEMENT (ident));
|
||||
}
|
||||
|
||||
/* This loop function is only needed when typefinding.
|
||||
*/
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
GstBuffer *buffer;
|
||||
guint best_probability;
|
||||
GstCaps *caps;
|
||||
|
@ -431,19 +471,20 @@ guint8 *
|
|||
spider_find_peek (gpointer data, gint64 offset, guint size)
|
||||
{
|
||||
SpiderTypeFind *find = (SpiderTypeFind *) data;
|
||||
gint64 buffer_offset = GST_BUFFER_OFFSET_IS_VALID (find->buffer) ?
|
||||
GST_BUFFER_OFFSET (find->buffer) : 0;
|
||||
|
||||
if (offset >= buffer_offset && offset + size <= buffer_offset + GST_BUFFER_SIZE (find->buffer)) {
|
||||
GST_LOG ("peek %"G_GINT64_FORMAT", %u successful", offset, size);
|
||||
gint64 buffer_offset = GST_BUFFER_OFFSET_IS_VALID (find->buffer) ?
|
||||
GST_BUFFER_OFFSET (find->buffer) : 0;
|
||||
|
||||
if (offset >= buffer_offset
|
||||
&& offset + size <= buffer_offset + GST_BUFFER_SIZE (find->buffer)) {
|
||||
GST_LOG ("peek %" G_GINT64_FORMAT ", %u successful", offset, size);
|
||||
return GST_BUFFER_DATA (find->buffer) + offset - buffer_offset;
|
||||
} else {
|
||||
GST_LOG ("peek %"G_GINT64_FORMAT", %u failed", offset, size);
|
||||
GST_LOG ("peek %" G_GINT64_FORMAT ", %u failed", offset, size);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
static void
|
||||
spider_find_suggest (gpointer data, guint probability, const GstCaps *caps)
|
||||
spider_find_suggest (gpointer data, guint probability, const GstCaps * caps)
|
||||
{
|
||||
SpiderTypeFind *find = (SpiderTypeFind *) data;
|
||||
|
||||
|
@ -454,7 +495,7 @@ spider_find_suggest (gpointer data, guint probability, const GstCaps *caps)
|
|||
}
|
||||
}
|
||||
static void
|
||||
gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *ident)
|
||||
gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity * ident)
|
||||
{
|
||||
GstData *data;
|
||||
GstTypeFind gst_find;
|
||||
|
@ -468,7 +509,7 @@ gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *ident)
|
|||
gst_spider_identity_chain (ident->sink, GST_BUFFER (data));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
find.buffer = GST_BUFFER (data);
|
||||
/* maybe there are already valid caps now? */
|
||||
find.caps = gst_pad_get_allowed_caps (ident->sink);
|
||||
|
@ -478,10 +519,10 @@ gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *ident)
|
|||
gst_caps_free (find.caps);
|
||||
find.caps = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* now do the actual typefinding with the supplied buffer */
|
||||
walk = type_list = gst_type_find_factory_get_list ();
|
||||
|
||||
|
||||
find.best_probability = 0;
|
||||
find.caps = NULL;
|
||||
gst_find.data = &find;
|
||||
|
@ -490,7 +531,8 @@ gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *ident)
|
|||
while (walk) {
|
||||
GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data);
|
||||
|
||||
GST_DEBUG ("trying typefind function %s", GST_PLUGIN_FEATURE_NAME (factory));
|
||||
GST_DEBUG ("trying typefind function %s",
|
||||
GST_PLUGIN_FEATURE_NAME (factory));
|
||||
gst_type_find_factory_call_function (factory, &gst_find);
|
||||
if (find.best_probability >= GST_TYPE_FIND_MAXIMUM)
|
||||
goto plug;
|
||||
|
@ -503,23 +545,24 @@ gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *ident)
|
|||
|
||||
end:
|
||||
/* remove loop function */
|
||||
gst_element_set_loop_function (GST_ELEMENT (ident),
|
||||
(GstElementLoopFunction) GST_DEBUG_FUNCPTR (gst_spider_identity_dumb_loop));
|
||||
|
||||
gst_element_set_loop_function (GST_ELEMENT (ident),
|
||||
(GstElementLoopFunction)
|
||||
GST_DEBUG_FUNCPTR (gst_spider_identity_dumb_loop));
|
||||
|
||||
/* push the buffer */
|
||||
gst_spider_identity_chain (ident->sink, find.buffer);
|
||||
|
||||
|
||||
return;
|
||||
|
||||
plug:
|
||||
GST_INFO ("typefind function found caps");
|
||||
GST_INFO ("typefind function found caps");
|
||||
ident->caps = find.caps;
|
||||
if (GST_PAD_IS_LINKED (ident->src)) {
|
||||
GstPadLinkReturn ret;
|
||||
|
||||
ret = gst_pad_try_set_caps (ident->src, find.caps);
|
||||
if (GST_PAD_LINK_FAILED (ret)){
|
||||
g_critical("could not set caps on spideridentity src pad\n");
|
||||
if (GST_PAD_LINK_FAILED (ret)) {
|
||||
g_critical ("could not set caps on spideridentity src pad\n");
|
||||
}
|
||||
}
|
||||
GST_LOG_OBJECT (ident, "spider starting caps: %" GST_PTR_FORMAT, find.caps);
|
||||
|
@ -532,12 +575,12 @@ plug:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_spider_identity_handle_src_event (GstPad *pad, GstEvent *event)
|
||||
gst_spider_identity_handle_src_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
gboolean res = TRUE;
|
||||
GstSpiderIdentity *ident;
|
||||
|
||||
GST_DEBUG ( "spider_identity src_event");
|
||||
GST_DEBUG ("spider_identity src_event");
|
||||
|
||||
ident = GST_SPIDER_IDENTITY (gst_pad_get_parent (pad));
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_SPIDER_IDENTITY \
|
||||
(gst_spider_identity_get_type())
|
||||
#define GST_SPIDER_IDENTITY(obj) \
|
||||
|
@ -38,35 +37,36 @@ G_BEGIN_DECLS
|
|||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SPIDER_IDENTITY))
|
||||
#define GST_IS_SPIDER_IDENTITY_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SPIDER_IDENTITY))
|
||||
|
||||
typedef struct _GstSpiderIdentity GstSpiderIdentity;
|
||||
typedef struct _GstSpiderIdentityClass GstSpiderIdentityClass;
|
||||
|
||||
struct _GstSpiderIdentity {
|
||||
struct _GstSpiderIdentity
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
/* sink and source */
|
||||
GstPad *sink;
|
||||
GstPad *src;
|
||||
|
||||
|
||||
/* plugged into autoplugger yet? */
|
||||
gboolean plugged;
|
||||
|
||||
|
||||
/* Caps from typefinding */
|
||||
GstCaps *caps;
|
||||
};
|
||||
|
||||
struct _GstSpiderIdentityClass {
|
||||
struct _GstSpiderIdentityClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
|
||||
};
|
||||
|
||||
GType gst_spider_identity_get_type (void);
|
||||
GType gst_spider_identity_get_type (void);
|
||||
|
||||
GstSpiderIdentity* gst_spider_identity_new_sink (gchar *name);
|
||||
GstSpiderIdentity* gst_spider_identity_new_src (gchar *name);
|
||||
GstPad* gst_spider_identity_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *name);
|
||||
GstSpiderIdentity *gst_spider_identity_new_sink (gchar * name);
|
||||
GstSpiderIdentity *gst_spider_identity_new_src (gchar * name);
|
||||
GstPad *gst_spider_identity_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * name);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_SPIDER_IDENTITY_H__ */
|
||||
|
|
|
@ -4,41 +4,40 @@
|
|||
/* returns all factories which have a maximum of maxtemplates GstPadTemplates in direction dir
|
||||
*/
|
||||
GList *
|
||||
gst_factories_at_most_templates(GList *factories, GstPadDirection dir, guint maxtemplates)
|
||||
gst_factories_at_most_templates (GList * factories, GstPadDirection dir,
|
||||
guint maxtemplates)
|
||||
{
|
||||
GList *ret = NULL;
|
||||
|
||||
while (factories)
|
||||
{
|
||||
|
||||
while (factories) {
|
||||
guint count = 0;
|
||||
GList *templs = ((GstElementFactory *) factories->data)->padtemplates;
|
||||
|
||||
while (templs)
|
||||
{
|
||||
if (GST_PAD_TEMPLATE_DIRECTION (templs->data) == dir)
|
||||
{
|
||||
count++;
|
||||
while (templs) {
|
||||
if (GST_PAD_TEMPLATE_DIRECTION (templs->data) == dir) {
|
||||
count++;
|
||||
}
|
||||
if (count > maxtemplates)
|
||||
break;
|
||||
break;
|
||||
templs = g_list_next (templs);
|
||||
}
|
||||
if (count <= maxtemplates)
|
||||
ret = g_list_prepend (ret, factories->data);
|
||||
|
||||
|
||||
factories = g_list_next (factories);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
property_change_callback (GObject *object, GstObject *orig, GParamSpec *pspec)
|
||||
property_change_callback (GObject * object, GstObject * orig,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GValue value = { 0, }; /* the important thing is that value.type = 0 */
|
||||
GValue value = { 0, }; /* the important thing is that value.type = 0 */
|
||||
gchar *str = 0;
|
||||
|
||||
|
||||
if (pspec->flags & G_PARAM_READABLE) {
|
||||
g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
||||
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
||||
g_object_get_property (G_OBJECT (orig), pspec->name, &value);
|
||||
if (G_IS_PARAM_SPEC_STRING (pspec))
|
||||
str = g_value_dup_string (&value);
|
||||
|
@ -48,17 +47,17 @@ property_change_callback (GObject *object, GstObject *orig, GParamSpec *pspec)
|
|||
str = g_strdup_printf ("%" G_GINT64_FORMAT, g_value_get_int64 (&value));
|
||||
else
|
||||
str = g_strdup_value_contents (&value);
|
||||
|
||||
|
||||
g_print ("%s: %s = %s\n", GST_OBJECT_NAME (orig), pspec->name, str);
|
||||
g_free (str);
|
||||
g_value_unset(&value);
|
||||
g_value_unset (&value);
|
||||
} else {
|
||||
g_warning ("Parameter not readable. What's up with that?");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
error_callback (GObject *object, GstObject *orig, gchar *error)
|
||||
error_callback (GObject * object, GstObject * orig, gchar * error)
|
||||
{
|
||||
g_print ("ERROR: %s: %s\n", GST_OBJECT_NAME (orig), error);
|
||||
}
|
||||
|
@ -70,42 +69,44 @@ error_callback (GObject *object, GstObject *orig, gchar *error)
|
|||
* USAGE: spidertest <mediafile>
|
||||
* If mediafile can be recognized, xvideo and oss audio output are tried.
|
||||
*/
|
||||
int main(int argc,char *argv[])
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *bin, *filesrc, *decoder, *osssink, *videosink;
|
||||
GList *facs;
|
||||
|
||||
|
||||
if (argc < 2) {
|
||||
g_print("usage: %s <file>\n", argv[0]);
|
||||
exit(-1);
|
||||
g_print ("usage: %s <file>\n", argv[0]);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
bin = gst_pipeline_new("pipeline");
|
||||
g_signal_connect (bin, "deep_notify", G_CALLBACK (property_change_callback), NULL);
|
||||
bin = gst_pipeline_new ("pipeline");
|
||||
g_signal_connect (bin, "deep_notify", G_CALLBACK (property_change_callback),
|
||||
NULL);
|
||||
g_signal_connect (bin, "error", G_CALLBACK (error_callback), NULL);
|
||||
|
||||
|
||||
/* create a disk reader */
|
||||
filesrc = gst_element_factory_make("filesrc", "disk_source");
|
||||
g_object_set(G_OBJECT(filesrc),"location", argv[1], NULL);
|
||||
filesrc = gst_element_factory_make ("filesrc", "disk_source");
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
|
||||
/* now it's time to get the decoder */
|
||||
decoder = gst_element_factory_make("spider", "spider");
|
||||
decoder = gst_element_factory_make ("spider", "spider");
|
||||
if (!decoder) {
|
||||
g_print ("could not find plugin \"spider\"\n");
|
||||
exit (-2);
|
||||
}
|
||||
|
||||
|
||||
/* only use decoding plugins */
|
||||
g_object_get (decoder, "factories", &facs, NULL);
|
||||
facs = gst_factories_at_most_templates(facs, GST_PAD_SINK, 1);
|
||||
facs = gst_factories_at_most_templates (facs, GST_PAD_SINK, 1);
|
||||
g_object_set (decoder, "factories", facs, NULL);
|
||||
|
||||
/* create video and audio sink */
|
||||
osssink = gst_element_factory_make("osssink", "audio");
|
||||
videosink = gst_element_factory_make("xvideosink", "video");
|
||||
osssink = gst_element_factory_make ("osssink", "audio");
|
||||
videosink = gst_element_factory_make ("xvideosink", "video");
|
||||
|
||||
if ((!osssink) || (!videosink)) {
|
||||
g_print ("could not create output plugins\n");
|
||||
|
@ -113,16 +114,15 @@ int main(int argc,char *argv[])
|
|||
}
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
gst_bin_add(GST_BIN(bin), filesrc);
|
||||
gst_bin_add(GST_BIN(bin), decoder);
|
||||
gst_bin_add(GST_BIN(bin), osssink);
|
||||
gst_bin_add(GST_BIN(bin), videosink);
|
||||
gst_bin_add (GST_BIN (bin), filesrc);
|
||||
gst_bin_add (GST_BIN (bin), decoder);
|
||||
gst_bin_add (GST_BIN (bin), osssink);
|
||||
gst_bin_add (GST_BIN (bin), videosink);
|
||||
|
||||
/* link objects */
|
||||
if (!(gst_element_link(filesrc, decoder) &&
|
||||
gst_element_link(decoder, osssink) &&
|
||||
gst_element_link(decoder, videosink)))
|
||||
{
|
||||
if (!(gst_element_link (filesrc, decoder) &&
|
||||
gst_element_link (decoder, osssink) &&
|
||||
gst_element_link (decoder, videosink))) {
|
||||
g_print ("the pipeline could not be linked\n");
|
||||
exit (-4);
|
||||
}
|
||||
|
@ -130,10 +130,9 @@ int main(int argc,char *argv[])
|
|||
/* gst_bin_use_clock (GST_BIN (bin), gst_system_clock_obtain ());*/
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state(bin, GST_STATE_PLAYING);
|
||||
gst_element_set_state (bin, GST_STATE_PLAYING);
|
||||
|
||||
while (gst_bin_iterate(GST_BIN(bin)));
|
||||
while (gst_bin_iterate (GST_BIN (bin)));
|
||||
|
||||
exit(0);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
|
210
gst/cothreads.c
210
gst/cothreads.c
|
@ -59,11 +59,11 @@
|
|||
#define COTHREAD_MAXTHREADS 16
|
||||
#define COTHREAD_STACKSIZE (STACK_SIZE/COTHREAD_MAXTHREADS)
|
||||
|
||||
static void cothread_destroy (cothread_state *cothread);
|
||||
static void cothread_destroy (cothread_state * cothread);
|
||||
|
||||
struct _cothread_context
|
||||
{
|
||||
cothread_state *cothreads[COTHREAD_MAXTHREADS]; /* array of cothread states */
|
||||
cothread_state *cothreads[COTHREAD_MAXTHREADS]; /* array of cothread states */
|
||||
int ncothreads;
|
||||
int current;
|
||||
unsigned long stack_top;
|
||||
|
@ -92,10 +92,10 @@ cothread_get_current_context (void)
|
|||
cothread_context *ctx;
|
||||
|
||||
ctx = g_static_private_get (&_cothread_ctx_key);
|
||||
g_assert(ctx);
|
||||
g_assert (ctx);
|
||||
|
||||
#ifdef COTHREAD_PARANOID
|
||||
g_assert (ctx->thread == g_thread_self());
|
||||
g_assert (ctx->thread == g_thread_self ());
|
||||
#endif
|
||||
|
||||
return ctx;
|
||||
|
@ -112,15 +112,15 @@ cothread_context *
|
|||
cothread_context_init (void)
|
||||
{
|
||||
char __csf;
|
||||
void *current_stack_frame = &__csf; /* Get pointer inside current stack frame */
|
||||
void *current_stack_frame = &__csf; /* Get pointer inside current stack frame */
|
||||
cothread_context *ctx;
|
||||
|
||||
/* if there already is a cotread context for this thread,
|
||||
* just return it */
|
||||
ctx = g_static_private_get (&_cothread_ctx_key);
|
||||
if (ctx) {
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS,
|
||||
"returning private _cothread_ctx_key %p", ctx);
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS,
|
||||
"returning private _cothread_ctx_key %p", ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
@ -133,16 +133,17 @@ cothread_context_init (void)
|
|||
ctx->ncothreads = 1;
|
||||
ctx->current = 0;
|
||||
ctx->data = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
ctx->thread = g_thread_self();
|
||||
ctx->thread = g_thread_self ();
|
||||
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS, "initializing cothreads");
|
||||
|
||||
/* set this thread's context pointer */
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS, "setting private _cothread_ctx_key to %p in thread %p",
|
||||
ctx,g_thread_self());
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS,
|
||||
"setting private _cothread_ctx_key to %p in thread %p", ctx,
|
||||
g_thread_self ());
|
||||
g_static_private_set (&_cothread_ctx_key, ctx, NULL);
|
||||
|
||||
g_assert(ctx == cothread_get_current_context());
|
||||
g_assert (ctx == cothread_get_current_context ());
|
||||
|
||||
/* clear the cothread data */
|
||||
memset (ctx->cothreads, 0, sizeof (ctx->cothreads));
|
||||
|
@ -170,8 +171,8 @@ cothread_context_init (void)
|
|||
ctx->cothreads[0]->flags = COTHREAD_STARTED;
|
||||
ctx->cothreads[0]->sp = (void *) current_stack_frame;
|
||||
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS, "0th cothread is %p at sp:%p",
|
||||
ctx->cothreads[0], ctx->cothreads[0]->sp);
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS, "0th cothread is %p at sp:%p",
|
||||
ctx->cothreads[0], ctx->cothreads[0]->sp);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
@ -183,12 +184,12 @@ cothread_context_init (void)
|
|||
* Free the cothread context.
|
||||
*/
|
||||
void
|
||||
cothread_context_free (cothread_context *ctx)
|
||||
cothread_context_free (cothread_context * ctx)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (ctx != NULL);
|
||||
g_assert (ctx->thread == g_thread_self());
|
||||
g_assert (ctx->thread == g_thread_self ());
|
||||
g_assert (ctx->current == 0);
|
||||
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS, "free cothread context");
|
||||
|
@ -199,13 +200,14 @@ cothread_context_free (cothread_context *ctx)
|
|||
}
|
||||
}
|
||||
if (ctx->cothreads[0]) {
|
||||
g_free(ctx->cothreads[0]);
|
||||
g_free (ctx->cothreads[0]);
|
||||
ctx->cothreads[0] = NULL;
|
||||
}
|
||||
g_hash_table_destroy (ctx->data);
|
||||
/* make sure we free the private key for cothread context */
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS, "setting private _cothread_ctx_key to NULL in thread %p",
|
||||
g_thread_self());
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS,
|
||||
"setting private _cothread_ctx_key to NULL in thread %p",
|
||||
g_thread_self ());
|
||||
g_static_private_set (&_cothread_ctx_key, NULL, NULL);
|
||||
g_free (ctx);
|
||||
}
|
||||
|
@ -218,8 +220,8 @@ cothread_context_free (cothread_context *ctx)
|
|||
*
|
||||
* Returns: the new cothread state or NULL on error
|
||||
*/
|
||||
cothread_state*
|
||||
cothread_create (cothread_context *ctx)
|
||||
cothread_state *
|
||||
cothread_create (cothread_context * ctx)
|
||||
{
|
||||
cothread_state *cothread;
|
||||
void *mmaped = 0;
|
||||
|
@ -228,8 +230,8 @@ cothread_create (cothread_context *ctx)
|
|||
|
||||
g_return_val_if_fail (ctx != NULL, NULL);
|
||||
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "manager sef %p, cothread self %p",
|
||||
ctx->thread, g_thread_self());
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "manager sef %p, cothread self %p",
|
||||
ctx->thread, g_thread_self ());
|
||||
|
||||
if (ctx->ncothreads == COTHREAD_MAXTHREADS) {
|
||||
/* this is pretty fatal */
|
||||
|
@ -241,7 +243,7 @@ cothread_create (cothread_context *ctx)
|
|||
if (ctx->cothreads[slot] == NULL)
|
||||
break;
|
||||
else if (ctx->cothreads[slot]->flags & COTHREAD_DESTROYED &&
|
||||
slot != ctx->current) {
|
||||
slot != ctx->current) {
|
||||
cothread_destroy (ctx->cothreads[slot]);
|
||||
break;
|
||||
}
|
||||
|
@ -251,66 +253,69 @@ cothread_create (cothread_context *ctx)
|
|||
|
||||
/* cothread stack space of the thread is mapped in reverse, with cothread 0
|
||||
* stack space at the top */
|
||||
cothread = (cothread_state *) (ctx->stack_top - (slot + 1) * COTHREAD_STACKSIZE);
|
||||
cothread =
|
||||
(cothread_state *) (ctx->stack_top - (slot + 1) * COTHREAD_STACKSIZE);
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "cothread pointer is %p", cothread);
|
||||
|
||||
#if 0
|
||||
/* This tests to see whether or not we can grow down the stack */
|
||||
{
|
||||
unsigned long ptr;
|
||||
for(ptr=ctx->stack_top - 4096; ptr > (unsigned long)cothread; ptr -= 4096){
|
||||
|
||||
for (ptr = ctx->stack_top - 4096; ptr > (unsigned long) cothread;
|
||||
ptr -= 4096) {
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "touching location 0x%08lx", ptr);
|
||||
*(volatile unsigned int *)ptr = *(volatile unsigned int *)ptr;
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "ok (0x%08x)", *(unsigned int *)ptr);
|
||||
*(volatile unsigned int *) ptr = *(volatile unsigned int *) ptr;
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "ok (0x%08x)", *(unsigned int *) ptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _SC_PAGESIZE
|
||||
page_size = sysconf(_SC_PAGESIZE);
|
||||
page_size = sysconf (_SC_PAGESIZE);
|
||||
#else
|
||||
page_size = getpagesize();
|
||||
page_size = getpagesize ();
|
||||
#endif
|
||||
|
||||
/* The mmap is necessary on Linux/i386, and possibly others, since the
|
||||
* kernel is picky about when we can expand our stack. */
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "mmaping %p, size 0x%08x", cothread,
|
||||
COTHREAD_STACKSIZE);
|
||||
COTHREAD_STACKSIZE);
|
||||
/* Remap with a guard page. This decreases our stack size by 8 kB (for
|
||||
* 4 kB pages) and also wastes almost 4 kB for the cothreads
|
||||
* structure */
|
||||
munmap((void *)cothread, COTHREAD_STACKSIZE);
|
||||
munmap ((void *) cothread, COTHREAD_STACKSIZE);
|
||||
mmaped = mmap ((void *) cothread, page_size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
mmaped = mmap (((void *) cothread) + page_size * 2,
|
||||
COTHREAD_STACKSIZE - page_size * 2,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
COTHREAD_STACKSIZE - page_size * 2,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "coming out of mmap");
|
||||
if (mmaped == MAP_FAILED) {
|
||||
perror ("mmap'ing cothread stack space");
|
||||
return NULL;
|
||||
}
|
||||
if (mmaped != (void *)cothread + page_size * 2) {
|
||||
if (mmaped != (void *) cothread + page_size * 2) {
|
||||
g_warning ("could not mmap requested memory for cothread");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cothread->magic_number = COTHREAD_MAGIC_NUMBER;
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "create cothread %d with magic number 0x%x",
|
||||
slot, cothread->magic_number);
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS,
|
||||
"create cothread %d with magic number 0x%x", slot,
|
||||
cothread->magic_number);
|
||||
cothread->ctx = ctx;
|
||||
cothread->cothreadnum = slot;
|
||||
cothread->flags = 0;
|
||||
cothread->priv = NULL;
|
||||
cothread->sp = ((guchar *) cothread + COTHREAD_STACKSIZE);
|
||||
cothread->stack_size = COTHREAD_STACKSIZE - page_size * 2;
|
||||
cothread->stack_base = (void *)cothread + 2 * page_size;
|
||||
cothread->stack_base = (void *) cothread + 2 * page_size;
|
||||
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS,
|
||||
"created cothread #%d in slot %d: %p at sp:%p",
|
||||
ctx->ncothreads, slot, cothread, cothread->sp);
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS,
|
||||
"created cothread #%d in slot %d: %p at sp:%p",
|
||||
ctx->ncothreads, slot, cothread, cothread->sp);
|
||||
|
||||
ctx->cothreads[slot] = cothread;
|
||||
ctx->ncothreads++;
|
||||
|
@ -325,12 +330,12 @@ cothread_create (cothread_context *ctx)
|
|||
* Free the given cothread state
|
||||
*/
|
||||
void
|
||||
cothread_free (cothread_state *cothread)
|
||||
cothread_free (cothread_state * cothread)
|
||||
{
|
||||
g_return_if_fail (cothread != NULL);
|
||||
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS, "flag cothread %d for destruction",
|
||||
cothread->cothreadnum);
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS, "flag cothread %d for destruction",
|
||||
cothread->cothreadnum);
|
||||
|
||||
/* we simply flag the cothread for destruction here */
|
||||
if (cothread)
|
||||
|
@ -340,7 +345,7 @@ cothread_free (cothread_state *cothread)
|
|||
}
|
||||
|
||||
static void
|
||||
cothread_destroy (cothread_state *cothread)
|
||||
cothread_destroy (cothread_state * cothread)
|
||||
{
|
||||
cothread_context *ctx;
|
||||
gint cothreadnum;
|
||||
|
@ -349,27 +354,28 @@ cothread_destroy (cothread_state *cothread)
|
|||
|
||||
cothreadnum = cothread->cothreadnum;
|
||||
ctx = cothread->ctx;
|
||||
g_assert (ctx->thread == g_thread_self());
|
||||
g_assert (ctx == cothread_get_current_context());
|
||||
g_assert (ctx->thread == g_thread_self ());
|
||||
g_assert (ctx == cothread_get_current_context ());
|
||||
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS, "destroy cothread %d %p %d",
|
||||
cothreadnum, cothread, ctx->current);
|
||||
GST_CAT_INFO (GST_CAT_COTHREADS, "destroy cothread %d %p %d",
|
||||
cothreadnum, cothread, ctx->current);
|
||||
|
||||
/* cothread 0 needs to be destroyed specially */
|
||||
g_assert(cothreadnum != 0);
|
||||
g_assert (cothreadnum != 0);
|
||||
|
||||
/* we have to unlock here because we might be switched out
|
||||
* with the lock held */
|
||||
cothread_unlock (cothread);
|
||||
|
||||
/* doing cleanups of the cothread create */
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "destroy cothread %d with magic number 0x%x",
|
||||
cothreadnum, cothread->magic_number);
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS,
|
||||
"destroy cothread %d with magic number 0x%x", cothreadnum,
|
||||
cothread->magic_number);
|
||||
g_assert (cothread->magic_number == COTHREAD_MAGIC_NUMBER);
|
||||
|
||||
g_assert (cothread->priv == NULL);
|
||||
|
||||
memset(cothread,0,sizeof(*cothread));
|
||||
memset (cothread, 0, sizeof (*cothread));
|
||||
|
||||
ctx->cothreads[cothreadnum] = NULL;
|
||||
ctx->ncothreads--;
|
||||
|
@ -385,7 +391,8 @@ cothread_destroy (cothread_state *cothread)
|
|||
* Set the cothread function
|
||||
*/
|
||||
void
|
||||
cothread_setfunc (cothread_state* cothread, cothread_func func, int argc, char **argv)
|
||||
cothread_setfunc (cothread_state * cothread, cothread_func func, int argc,
|
||||
char **argv)
|
||||
{
|
||||
cothread->func = func;
|
||||
cothread->argc = argc;
|
||||
|
@ -399,7 +406,7 @@ cothread_setfunc (cothread_state* cothread, cothread_func func, int argc, char *
|
|||
* Stop the cothread and reset the stack and program counter.
|
||||
*/
|
||||
void
|
||||
cothread_stop (cothread_state* cothread)
|
||||
cothread_stop (cothread_state * cothread)
|
||||
{
|
||||
cothread->flags &= ~COTHREAD_STARTED;
|
||||
}
|
||||
|
@ -412,13 +419,13 @@ cothread_stop (cothread_state* cothread)
|
|||
*
|
||||
* Returns: the #cothread_state of the main (0th) cothread.
|
||||
*/
|
||||
cothread_state*
|
||||
cothread_main (cothread_context* ctx)
|
||||
cothread_state *
|
||||
cothread_main (cothread_context * ctx)
|
||||
{
|
||||
g_assert (ctx->thread == g_thread_self());
|
||||
g_assert (ctx->thread == g_thread_self ());
|
||||
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "returning %p, the 0th cothread",
|
||||
ctx->cothreads[0]);
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "returning %p, the 0th cothread",
|
||||
ctx->cothreads[0]);
|
||||
return ctx->cothreads[0];
|
||||
}
|
||||
|
||||
|
@ -429,10 +436,10 @@ cothread_main (cothread_context* ctx)
|
|||
*
|
||||
* Returns: the #cothread_state of the main (0th) thread in the current GThread
|
||||
*/
|
||||
cothread_state*
|
||||
cothread_state *
|
||||
cothread_current_main (void)
|
||||
{
|
||||
cothread_context *ctx = cothread_get_current_context();
|
||||
cothread_context *ctx = cothread_get_current_context ();
|
||||
|
||||
return ctx->cothreads[0];
|
||||
}
|
||||
|
@ -444,10 +451,10 @@ cothread_current_main (void)
|
|||
*
|
||||
* Returns: the #cothread_state of the current cothread
|
||||
*/
|
||||
cothread_state*
|
||||
cothread_state *
|
||||
cothread_current (void)
|
||||
{
|
||||
cothread_context *ctx = cothread_get_current_context();
|
||||
cothread_context *ctx = cothread_get_current_context ();
|
||||
|
||||
return ctx->cothreads[ctx->current];
|
||||
}
|
||||
|
@ -455,9 +462,10 @@ cothread_current (void)
|
|||
static void
|
||||
cothread_stub (void)
|
||||
{
|
||||
cothread_context *ctx = cothread_get_current_context();
|
||||
cothread_context *ctx = cothread_get_current_context ();
|
||||
cothread_state *cothread = ctx->cothreads[ctx->current];
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
char __csf;
|
||||
void *current_stack_frame = &__csf;
|
||||
#endif
|
||||
|
@ -469,11 +477,13 @@ cothread_stub (void)
|
|||
while (TRUE) {
|
||||
cothread->func (cothread->argc, cothread->argv);
|
||||
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "cothread[%d] thread->func exited", ctx->current);
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "cothread[%d] thread->func exited",
|
||||
ctx->current);
|
||||
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "sp=%p", current_stack_frame);
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "ctx=%p current=%p", ctx,cothread_get_current_context());
|
||||
g_assert (ctx == cothread_get_current_context());
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "ctx=%p current=%p", ctx,
|
||||
cothread_get_current_context ());
|
||||
g_assert (ctx == cothread_get_current_context ());
|
||||
|
||||
g_assert (ctx->current != 0);
|
||||
|
||||
|
@ -489,12 +499,13 @@ cothread_stub (void)
|
|||
*
|
||||
* Returns: the current cothread id
|
||||
*/
|
||||
int cothread_getcurrent (void) G_GNUC_NO_INSTRUMENT;
|
||||
|
||||
int
|
||||
cothread_getcurrent (void)
|
||||
G_GNUC_NO_INSTRUMENT;
|
||||
|
||||
int cothread_getcurrent (void)
|
||||
{
|
||||
cothread_context *ctx = cothread_get_current_context();
|
||||
cothread_context *ctx = cothread_get_current_context ();
|
||||
|
||||
if (!ctx)
|
||||
return -1;
|
||||
|
@ -510,7 +521,7 @@ cothread_getcurrent (void)
|
|||
* set private data for the cothread.
|
||||
*/
|
||||
void
|
||||
cothread_set_private (cothread_state *cothread, gpointer data)
|
||||
cothread_set_private (cothread_state * cothread, gpointer data)
|
||||
{
|
||||
cothread->priv = data;
|
||||
}
|
||||
|
@ -524,9 +535,10 @@ cothread_set_private (cothread_state *cothread, gpointer data)
|
|||
* adds data to a cothread
|
||||
*/
|
||||
void
|
||||
cothread_context_set_data (cothread_state *cothread, gchar *key, gpointer data)
|
||||
cothread_context_set_data (cothread_state * cothread, gchar * key,
|
||||
gpointer data)
|
||||
{
|
||||
cothread_context *ctx = cothread_get_current_context();
|
||||
cothread_context *ctx = cothread_get_current_context ();
|
||||
|
||||
g_hash_table_insert (ctx->data, key, data);
|
||||
}
|
||||
|
@ -540,7 +552,7 @@ cothread_context_set_data (cothread_state *cothread, gchar *key, gpointer data)
|
|||
* Returns: the private data of the cothread
|
||||
*/
|
||||
gpointer
|
||||
cothread_get_private (cothread_state *cothread)
|
||||
cothread_get_private (cothread_state * cothread)
|
||||
{
|
||||
return cothread->priv;
|
||||
}
|
||||
|
@ -555,9 +567,9 @@ cothread_get_private (cothread_state *cothread)
|
|||
* Returns: the data associated with the key
|
||||
*/
|
||||
gpointer
|
||||
cothread_context_get_data (cothread_state *cothread, gchar *key)
|
||||
cothread_context_get_data (cothread_state * cothread, gchar * key)
|
||||
{
|
||||
cothread_context *ctx = cothread_get_current_context();
|
||||
cothread_context *ctx = cothread_get_current_context ();
|
||||
|
||||
return g_hash_table_lookup (ctx->data, key);
|
||||
}
|
||||
|
@ -569,7 +581,7 @@ cothread_context_get_data (cothread_state *cothread, gchar *key)
|
|||
* Switches to the given cothread state
|
||||
*/
|
||||
void
|
||||
cothread_switch (cothread_state *cothread)
|
||||
cothread_switch (cothread_state * cothread)
|
||||
{
|
||||
cothread_context *ctx;
|
||||
cothread_state *current;
|
||||
|
@ -582,7 +594,7 @@ cothread_switch (cothread_state *cothread)
|
|||
ctx = cothread->ctx;
|
||||
|
||||
/* paranoia check to make sure we're in the right thread */
|
||||
g_assert (ctx->thread == g_thread_self());
|
||||
g_assert (ctx->thread == g_thread_self ());
|
||||
|
||||
#ifdef COTHREAD_PARANOID
|
||||
if (ctx == NULL)
|
||||
|
@ -599,9 +611,9 @@ cothread_switch (cothread_state *cothread)
|
|||
|
||||
|
||||
/* find the number of the thread to switch to */
|
||||
GST_CAT_INFO (GST_CAT_COTHREAD_SWITCH,
|
||||
"switching from cothread #%d to cothread #%d",
|
||||
ctx->current, cothread->cothreadnum);
|
||||
GST_CAT_INFO (GST_CAT_COTHREAD_SWITCH,
|
||||
"switching from cothread #%d to cothread #%d",
|
||||
ctx->current, cothread->cothreadnum);
|
||||
ctx->current = cothread->cothreadnum;
|
||||
|
||||
/* save the current stack pointer, frame pointer, and pc */
|
||||
|
@ -610,13 +622,13 @@ cothread_switch (cothread_state *cothread)
|
|||
#endif
|
||||
enter = setjmp (current->jmp);
|
||||
if (enter != 0) {
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS,
|
||||
"enter cothread #%d %d sp=%p jmpbuf=%p",
|
||||
current->cothreadnum, enter, current->sp, current->jmp);
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS,
|
||||
"enter cothread #%d %d sp=%p jmpbuf=%p",
|
||||
current->cothreadnum, enter, current->sp, current->jmp);
|
||||
return;
|
||||
}
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "exit cothread #%d %d sp=%p jmpbuf=%p",
|
||||
current->cothreadnum, enter, current->sp, current->jmp);
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "exit cothread #%d %d sp=%p jmpbuf=%p",
|
||||
current->cothreadnum, enter, current->sp, current->jmp);
|
||||
enter = 1;
|
||||
|
||||
if (current->flags & COTHREAD_DESTROYED) {
|
||||
|
@ -629,22 +641,21 @@ cothread_switch (cothread_state *cothread)
|
|||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "via longjmp() jmpbuf %p", cothread->jmp);
|
||||
/* switch to it */
|
||||
longjmp (cothread->jmp, 1);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
#ifdef HAVE_MAKECONTEXT
|
||||
ucontext_t ucp;
|
||||
|
||||
GST_CAT_DEBUG (GST_CAT_COTHREADS, "making context");
|
||||
|
||||
g_assert (cothread != cothread_main(ctx));
|
||||
g_assert (cothread != cothread_main (ctx));
|
||||
|
||||
getcontext (&ucp);
|
||||
ucp.uc_stack.ss_sp = (void *)cothread->stack_base;
|
||||
ucp.uc_stack.ss_sp = (void *) cothread->stack_base;
|
||||
ucp.uc_stack.ss_size = cothread->stack_size;
|
||||
makecontext (&ucp, cothread_stub, 0);
|
||||
setcontext (&ucp);
|
||||
#else
|
||||
GST_ARCH_SETUP_STACK ((char*)cothread->sp);
|
||||
GST_ARCH_SETUP_STACK ((char *) cothread->sp);
|
||||
GST_ARCH_SET_SP (cothread->sp);
|
||||
/* start it */
|
||||
GST_ARCH_CALL (cothread_stub);
|
||||
|
@ -668,7 +679,8 @@ nocurrent:
|
|||
exit (2);
|
||||
#endif /* COTHREAD_PARANOID */
|
||||
selfswitch:
|
||||
g_warning ("cothread: trying to switch to same thread, legal but not necessary");
|
||||
g_warning
|
||||
("cothread: trying to switch to same thread, legal but not necessary");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -679,7 +691,7 @@ selfswitch:
|
|||
* Locks the cothread state.
|
||||
*/
|
||||
void
|
||||
cothread_lock (cothread_state *cothread)
|
||||
cothread_lock (cothread_state * cothread)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -692,7 +704,7 @@ cothread_lock (cothread_state *cothread)
|
|||
* Returns: TRUE if the cothread could be locked.
|
||||
*/
|
||||
gboolean
|
||||
cothread_trylock (cothread_state *cothread)
|
||||
cothread_trylock (cothread_state * cothread)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -704,6 +716,6 @@ cothread_trylock (cothread_state *cothread)
|
|||
* Unlock the cothread state.
|
||||
*/
|
||||
void
|
||||
cothread_unlock (cothread_state *cothread)
|
||||
cothread_unlock (cothread_state * cothread)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -26,56 +26,56 @@
|
|||
#include <glib.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
typedef struct _cothread_state cothread_state;
|
||||
typedef struct _cothread_context cothread_context;
|
||||
typedef struct _cothread_state cothread_state;
|
||||
typedef struct _cothread_context cothread_context;
|
||||
|
||||
typedef int (*cothread_func) (int argc,char **argv);
|
||||
typedef int (*cothread_func) (int argc, char **argv);
|
||||
|
||||
#define COTHREAD_STARTED 0x01
|
||||
#define COTHREAD_DESTROYED 0x02
|
||||
|
||||
struct _cothread_state {
|
||||
cothread_context *ctx;
|
||||
int cothreadnum;
|
||||
gpointer priv;
|
||||
struct _cothread_state
|
||||
{
|
||||
cothread_context *ctx;
|
||||
int cothreadnum;
|
||||
gpointer priv;
|
||||
|
||||
cothread_func func;
|
||||
int argc;
|
||||
char **argv;
|
||||
cothread_func func;
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
int flags;
|
||||
void *sp;
|
||||
jmp_buf jmp;
|
||||
void *stack_base;
|
||||
unsigned long stack_size;
|
||||
int flags;
|
||||
void *sp;
|
||||
jmp_buf jmp;
|
||||
void *stack_base;
|
||||
unsigned long stack_size;
|
||||
|
||||
int magic_number;
|
||||
int magic_number;
|
||||
};
|
||||
|
||||
|
||||
cothread_context* cothread_context_init (void);
|
||||
void cothread_context_free (cothread_context *ctx);
|
||||
void cothread_context_set_data (cothread_state *cothread,
|
||||
gchar *key, gpointer data);
|
||||
gpointer cothread_context_get_data (cothread_state *cothread, gchar *key);
|
||||
cothread_context *cothread_context_init (void);
|
||||
void cothread_context_free (cothread_context * ctx);
|
||||
void cothread_context_set_data (cothread_state * cothread,
|
||||
gchar * key, gpointer data);
|
||||
gpointer cothread_context_get_data (cothread_state * cothread, gchar * key);
|
||||
|
||||
cothread_state* cothread_create (cothread_context *ctx);
|
||||
void cothread_free (cothread_state *cothread);
|
||||
void cothread_setfunc (cothread_state *cothread, cothread_func func,
|
||||
int argc, char **argv);
|
||||
void cothread_stop (cothread_state *cothread);
|
||||
cothread_state *cothread_create (cothread_context * ctx);
|
||||
void cothread_free (cothread_state * cothread);
|
||||
void cothread_setfunc (cothread_state * cothread, cothread_func func,
|
||||
int argc, char **argv);
|
||||
void cothread_stop (cothread_state * cothread);
|
||||
|
||||
void cothread_switch (cothread_state *cothread);
|
||||
void cothread_set_private (cothread_state *cothread,
|
||||
gpointer data);
|
||||
gpointer cothread_get_private (cothread_state *cothread);
|
||||
void cothread_switch (cothread_state * cothread);
|
||||
void cothread_set_private (cothread_state * cothread, gpointer data);
|
||||
gpointer cothread_get_private (cothread_state * cothread);
|
||||
|
||||
void cothread_lock (cothread_state *cothread);
|
||||
gboolean cothread_trylock (cothread_state *cothread);
|
||||
void cothread_unlock (cothread_state *cothread);
|
||||
void cothread_lock (cothread_state * cothread);
|
||||
gboolean cothread_trylock (cothread_state * cothread);
|
||||
void cothread_unlock (cothread_state * cothread);
|
||||
|
||||
cothread_state* cothread_main (cothread_context *ctx);
|
||||
cothread_state* cothread_current_main (void);
|
||||
cothread_state* cothread_current (void);
|
||||
cothread_state *cothread_main (cothread_context * ctx);
|
||||
cothread_state *cothread_current_main (void);
|
||||
cothread_state *cothread_current (void);
|
||||
|
||||
#endif /* __COTHREAD_H__ */
|
||||
|
|
|
@ -29,20 +29,21 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_aggregator_debug);
|
||||
#define GST_CAT_DEFAULT gst_aggregator_debug
|
||||
|
||||
GstElementDetails gst_aggregator_details = GST_ELEMENT_DETAILS (
|
||||
"Aggregator pipe fitting",
|
||||
"Generic",
|
||||
"N-to-1 pipe fitting",
|
||||
"Wim Taymans <wim.taymans@chello.be>"
|
||||
);
|
||||
GstElementDetails gst_aggregator_details =
|
||||
GST_ELEMENT_DETAILS ("Aggregator pipe fitting",
|
||||
"Generic",
|
||||
"N-to-1 pipe fitting",
|
||||
"Wim Taymans <wim.taymans@chello.be>");
|
||||
|
||||
/* Aggregator signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_NUM_PADS,
|
||||
ARG_SILENT,
|
||||
|
@ -51,12 +52,11 @@ enum {
|
|||
/* FILL ME */
|
||||
};
|
||||
|
||||
GstStaticPadTemplate aggregator_src_template = GST_STATIC_PAD_TEMPLATE (
|
||||
"sink%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
GstStaticPadTemplate aggregator_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
#define GST_TYPE_AGGREGATOR_SCHED (gst_aggregator_sched_get_type())
|
||||
static GType
|
||||
|
@ -64,75 +64,80 @@ gst_aggregator_sched_get_type (void)
|
|||
{
|
||||
static GType aggregator_sched_type = 0;
|
||||
static GEnumValue aggregator_sched[] = {
|
||||
{ AGGREGATOR_LOOP, "1", "Loop Based"},
|
||||
{ AGGREGATOR_LOOP_SELECT, "3", "Loop Based Select"},
|
||||
{ AGGREGATOR_CHAIN, "4", "Chain Based"},
|
||||
{AGGREGATOR_LOOP, "1", "Loop Based"},
|
||||
{AGGREGATOR_LOOP_SELECT, "3", "Loop Based Select"},
|
||||
{AGGREGATOR_CHAIN, "4", "Chain Based"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
if (!aggregator_sched_type) {
|
||||
aggregator_sched_type = g_enum_register_static ("GstAggregatorSched", aggregator_sched);
|
||||
aggregator_sched_type =
|
||||
g_enum_register_static ("GstAggregatorSched", aggregator_sched);
|
||||
}
|
||||
return aggregator_sched_type;
|
||||
}
|
||||
|
||||
#define AGGREGATOR_IS_LOOP_BASED(ag) ((ag)->sched != AGGREGATOR_CHAIN)
|
||||
|
||||
static GstPad* gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *temp, const
|
||||
gchar *unused);
|
||||
static void gst_aggregator_update_functions (GstAggregator *aggregator);
|
||||
static GstPad *gst_aggregator_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * temp, const gchar * unused);
|
||||
static void gst_aggregator_update_functions (GstAggregator * aggregator);
|
||||
|
||||
static void gst_aggregator_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_aggregator_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
static void gst_aggregator_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_aggregator_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static void gst_aggregator_chain (GstPad *pad, GstData *_data);
|
||||
static void gst_aggregator_loop (GstElement *element);
|
||||
static void gst_aggregator_chain (GstPad * pad, GstData * _data);
|
||||
static void gst_aggregator_loop (GstElement * element);
|
||||
|
||||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_aggregator_debug, "aggregator", 0, "aggregator element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstAggregator, gst_aggregator, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
GST_BOILERPLATE_FULL (GstAggregator, gst_aggregator, GstElement,
|
||||
GST_TYPE_ELEMENT, _do_init);
|
||||
|
||||
static void
|
||||
gst_aggregator_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&aggregator_src_template));
|
||||
gst_element_class_set_details (gstelement_class, &gst_aggregator_details);
|
||||
}
|
||||
static void
|
||||
gst_aggregator_class_init (GstAggregatorClass *klass)
|
||||
gst_aggregator_class_init (GstAggregatorClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
||||
gobject_class = (GObjectClass*) klass;
|
||||
gstelement_class = (GstElementClass*) klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_PADS,
|
||||
g_param_spec_int ("num_pads", "Num pads", "The number of source pads",
|
||||
0, G_MAXINT, 0, G_PARAM_READABLE));
|
||||
g_param_spec_int ("num_pads", "Num pads", "The number of source pads",
|
||||
0, G_MAXINT, 0, G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
|
||||
g_param_spec_boolean ("silent", "Silent", "Don't produce messages",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("silent", "Silent", "Don't produce messages",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SCHED,
|
||||
g_param_spec_enum ("sched", "Scheduling", "The type of scheduling this element should use",
|
||||
GST_TYPE_AGGREGATOR_SCHED, AGGREGATOR_CHAIN, G_PARAM_READWRITE));
|
||||
g_param_spec_enum ("sched", "Scheduling",
|
||||
"The type of scheduling this element should use",
|
||||
GST_TYPE_AGGREGATOR_SCHED, AGGREGATOR_CHAIN, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
|
||||
g_param_spec_string ("last_message", "Last message", "The current state of the element",
|
||||
NULL, G_PARAM_READABLE));
|
||||
g_param_spec_string ("last_message", "Last message",
|
||||
"The current state of the element", NULL, G_PARAM_READABLE));
|
||||
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_aggregator_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_aggregator_get_property);
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_aggregator_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_aggregator_get_property);
|
||||
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_aggregator_request_new_pad);
|
||||
gstelement_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_aggregator_request_new_pad);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_aggregator_init (GstAggregator *aggregator)
|
||||
static void
|
||||
gst_aggregator_init (GstAggregator * aggregator)
|
||||
{
|
||||
aggregator->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_pad_set_getcaps_function (aggregator->srcpad, gst_pad_proxy_getcaps);
|
||||
|
@ -146,8 +151,9 @@ gst_aggregator_init (GstAggregator *aggregator)
|
|||
gst_aggregator_update_functions (aggregator);
|
||||
}
|
||||
|
||||
static GstPad*
|
||||
gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
|
||||
static GstPad *
|
||||
gst_aggregator_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
||||
const gchar * unused)
|
||||
{
|
||||
gchar *name;
|
||||
GstPad *sinkpad;
|
||||
|
@ -162,43 +168,42 @@ gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *templ, cons
|
|||
|
||||
aggregator = GST_AGGREGATOR (element);
|
||||
|
||||
name = g_strdup_printf ("sink%d",aggregator->numsinkpads);
|
||||
|
||||
name = g_strdup_printf ("sink%d", aggregator->numsinkpads);
|
||||
|
||||
sinkpad = gst_pad_new_from_template (templ, name);
|
||||
g_free (name);
|
||||
|
||||
|
||||
if (!AGGREGATOR_IS_LOOP_BASED (aggregator)) {
|
||||
gst_pad_set_chain_function (sinkpad, gst_aggregator_chain);
|
||||
}
|
||||
gst_pad_set_getcaps_function (sinkpad, gst_pad_proxy_getcaps);
|
||||
gst_element_add_pad (GST_ELEMENT (aggregator), sinkpad);
|
||||
|
||||
|
||||
aggregator->sinkpads = g_list_prepend (aggregator->sinkpads, sinkpad);
|
||||
aggregator->numsinkpads++;
|
||||
|
||||
|
||||
return sinkpad;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_aggregator_update_functions (GstAggregator *aggregator)
|
||||
gst_aggregator_update_functions (GstAggregator * aggregator)
|
||||
{
|
||||
GList *pads;
|
||||
|
||||
if (AGGREGATOR_IS_LOOP_BASED (aggregator)) {
|
||||
gst_element_set_loop_function (GST_ELEMENT (aggregator), GST_DEBUG_FUNCPTR (gst_aggregator_loop));
|
||||
}
|
||||
else {
|
||||
gst_element_set_loop_function (GST_ELEMENT (aggregator),
|
||||
GST_DEBUG_FUNCPTR (gst_aggregator_loop));
|
||||
} else {
|
||||
gst_element_set_loop_function (GST_ELEMENT (aggregator), NULL);
|
||||
}
|
||||
|
||||
pads = aggregator->sinkpads;
|
||||
while (pads) {
|
||||
GstPad *pad = GST_PAD (pads->data);
|
||||
|
||||
|
||||
if (AGGREGATOR_IS_LOOP_BASED (aggregator)) {
|
||||
gst_pad_set_get_function (pad, NULL);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
gst_element_set_loop_function (GST_ELEMENT (aggregator), NULL);
|
||||
}
|
||||
pads = g_list_next (pads);
|
||||
|
@ -206,7 +211,8 @@ gst_aggregator_update_functions (GstAggregator *aggregator)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_aggregator_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
gst_aggregator_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstAggregator *aggregator;
|
||||
|
||||
|
@ -229,7 +235,8 @@ gst_aggregator_set_property (GObject *object, guint prop_id, const GValue *value
|
|||
}
|
||||
|
||||
static void
|
||||
gst_aggregator_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
gst_aggregator_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstAggregator *aggregator;
|
||||
|
||||
|
@ -256,15 +263,17 @@ gst_aggregator_get_property (GObject *object, guint prop_id, GValue *value, GPar
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_aggregator_push (GstAggregator *aggregator, GstPad *pad, GstBuffer *buf, guchar *debug)
|
||||
static void
|
||||
gst_aggregator_push (GstAggregator * aggregator, GstPad * pad, GstBuffer * buf,
|
||||
guchar * debug)
|
||||
{
|
||||
if (!aggregator->silent) {
|
||||
g_free (aggregator->last_message);
|
||||
|
||||
aggregator->last_message = g_strdup_printf ("%10.10s ******* (%s:%s)a (%d bytes, %"
|
||||
G_GUINT64_FORMAT ")",
|
||||
debug, GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
aggregator->last_message =
|
||||
g_strdup_printf ("%10.10s ******* (%s:%s)a (%d bytes, %"
|
||||
G_GUINT64_FORMAT ")", debug, GST_DEBUG_PAD_NAME (pad),
|
||||
GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
|
||||
g_object_notify (G_OBJECT (aggregator), "last_message");
|
||||
}
|
||||
|
@ -272,8 +281,8 @@ gst_aggregator_push (GstAggregator *aggregator, GstPad *pad, GstBuffer *buf, guc
|
|||
gst_pad_push (aggregator->srcpad, GST_DATA (buf));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_aggregator_loop (GstElement *element)
|
||||
static void
|
||||
gst_aggregator_loop (GstElement * element)
|
||||
{
|
||||
GstAggregator *aggregator;
|
||||
GstBuffer *buf;
|
||||
|
@ -288,6 +297,7 @@ gst_aggregator_loop (GstElement *element)
|
|||
* active ones */
|
||||
while (pads) {
|
||||
GstPad *pad = GST_PAD (pads->data);
|
||||
|
||||
pads = g_list_next (pads);
|
||||
|
||||
/* we need to check is the pad is usable. IS_USABLE will check
|
||||
|
@ -296,15 +306,14 @@ gst_aggregator_loop (GstElement *element)
|
|||
* and that the peer pad is also enabled.
|
||||
*/
|
||||
if (GST_PAD_IS_USABLE (pad)) {
|
||||
buf = GST_BUFFER (gst_pad_pull (pad));
|
||||
debug = "loop";
|
||||
buf = GST_BUFFER (gst_pad_pull (pad));
|
||||
debug = "loop";
|
||||
|
||||
/* then push it forward */
|
||||
gst_aggregator_push (aggregator, pad, buf, debug);
|
||||
gst_aggregator_push (aggregator, pad, buf, debug);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (aggregator->sched == AGGREGATOR_LOOP_SELECT) {
|
||||
GstPad *pad;
|
||||
|
||||
|
@ -314,8 +323,7 @@ gst_aggregator_loop (GstElement *element)
|
|||
buf = GST_BUFFER (gst_pad_pull (pad));
|
||||
|
||||
gst_aggregator_push (aggregator, pad, buf, debug);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
@ -328,8 +336,8 @@ gst_aggregator_loop (GstElement *element)
|
|||
*
|
||||
* Chain a buffer on a pad.
|
||||
*/
|
||||
static void
|
||||
gst_aggregator_chain (GstPad *pad, GstData *_data)
|
||||
static void
|
||||
gst_aggregator_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
GstBuffer *buf = GST_BUFFER (_data);
|
||||
GstAggregator *aggregator;
|
||||
|
@ -343,4 +351,3 @@ gst_aggregator_chain (GstPad *pad, GstData *_data)
|
|||
|
||||
gst_aggregator_push (aggregator, pad, buf, "chain");
|
||||
}
|
||||
|
||||
|
|
|
@ -26,11 +26,9 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
typedef enum {
|
||||
AGGREGATOR_LOOP = 1,
|
||||
G_BEGIN_DECLS typedef enum
|
||||
{
|
||||
AGGREGATOR_LOOP = 1,
|
||||
AGGREGATOR_LOOP_SELECT,
|
||||
AGGREGATOR_CHAIN
|
||||
} GstAggregatorSchedType;
|
||||
|
@ -46,10 +44,11 @@ typedef enum {
|
|||
#define GST_IS_AGGREGATOR_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AGGREGATOR))
|
||||
|
||||
typedef struct _GstAggregator GstAggregator;
|
||||
typedef struct _GstAggregatorClass GstAggregatorClass;
|
||||
typedef struct _GstAggregator GstAggregator;
|
||||
typedef struct _GstAggregatorClass GstAggregatorClass;
|
||||
|
||||
struct _GstAggregator {
|
||||
struct _GstAggregator
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
GstPad *srcpad;
|
||||
|
@ -63,14 +62,14 @@ struct _GstAggregator {
|
|||
gchar *last_message;
|
||||
};
|
||||
|
||||
struct _GstAggregatorClass {
|
||||
struct _GstAggregatorClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_aggregator_get_type (void);
|
||||
GType gst_aggregator_get_type (void);
|
||||
|
||||
gboolean gst_aggregator_factory_init (GstElementFactory *factory);
|
||||
gboolean gst_aggregator_factory_init (GstElementFactory * factory);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_AGGREGATOR_H__ */
|
||||
|
|
|
@ -29,47 +29,53 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_buffer_store_debug);
|
||||
#define GST_CAT_DEFAULT gst_buffer_store_debug
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
CLEARED,
|
||||
BUFFER_ADDED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0
|
||||
};
|
||||
|
||||
|
||||
static void gst_buffer_store_dispose (GObject * object);
|
||||
static void gst_buffer_store_dispose (GObject * object);
|
||||
|
||||
static gboolean gst_buffer_store_add_buffer_func (GstBufferStore * store,
|
||||
GstBuffer * buffer);
|
||||
static void gst_buffer_store_cleared_func (GstBufferStore * store);
|
||||
|
||||
static gboolean gst_buffer_store_add_buffer_func (GstBufferStore * store,
|
||||
GstBuffer * buffer);
|
||||
static void gst_buffer_store_cleared_func (GstBufferStore * store);
|
||||
|
||||
static guint gst_buffer_store_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_buffer_store_debug, "GstBufferStore", 0, "buffer store helper");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstBufferStore, gst_buffer_store, GObject, G_TYPE_OBJECT, _do_init);
|
||||
GST_BOILERPLATE_FULL (GstBufferStore, gst_buffer_store, GObject, G_TYPE_OBJECT,
|
||||
_do_init);
|
||||
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
debug_buffers (GstBufferStore *store)
|
||||
debug_buffers (GstBufferStore * store)
|
||||
{
|
||||
GList *walk = store->buffers;
|
||||
|
||||
|
||||
g_printerr ("BUFFERS in store:\n");
|
||||
while (walk) {
|
||||
g_print ("%15"G_GUINT64_FORMAT" - %7u\n", GST_BUFFER_OFFSET (walk->data), GST_BUFFER_SIZE (walk->data));
|
||||
g_print ("%15" G_GUINT64_FORMAT " - %7u\n", GST_BUFFER_OFFSET (walk->data),
|
||||
GST_BUFFER_SIZE (walk->data));
|
||||
walk = g_list_next (walk);
|
||||
}
|
||||
g_printerr ("\n");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
continue_accu (GSignalInvocationHint *ihint, GValue *return_accu,
|
||||
const GValue *handler_return, gpointer data)
|
||||
continue_accu (GSignalInvocationHint * ihint, GValue * return_accu,
|
||||
const GValue * handler_return, gpointer data)
|
||||
{
|
||||
gboolean do_continue = g_value_get_boolean (handler_return);
|
||||
|
||||
g_value_set_boolean (return_accu, do_continue);
|
||||
|
||||
return do_continue;
|
||||
|
@ -79,31 +85,31 @@ gst_buffer_store_base_init (gpointer g_class)
|
|||
{
|
||||
}
|
||||
static void
|
||||
gst_buffer_store_class_init (GstBufferStoreClass *store_class)
|
||||
gst_buffer_store_class_init (GstBufferStoreClass * store_class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (store_class);
|
||||
|
||||
gobject_class->dispose = gst_buffer_store_dispose;
|
||||
|
||||
gst_buffer_store_signals[CLEARED] = g_signal_new ("cleared",
|
||||
G_TYPE_FROM_CLASS (store_class), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstBufferStoreClass, cleared), NULL, NULL,
|
||||
gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
gst_buffer_store_signals[BUFFER_ADDED] = g_signal_new ("buffer-added",
|
||||
G_TYPE_FROM_CLASS (store_class), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstBufferStoreClass, buffer_added), continue_accu, NULL,
|
||||
gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, GST_TYPE_BUFFER);
|
||||
|
||||
gst_buffer_store_signals[CLEARED] = g_signal_new ("cleared",
|
||||
G_TYPE_FROM_CLASS (store_class), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstBufferStoreClass, cleared), NULL, NULL,
|
||||
gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
gst_buffer_store_signals[BUFFER_ADDED] = g_signal_new ("buffer-added",
|
||||
G_TYPE_FROM_CLASS (store_class), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstBufferStoreClass, buffer_added), continue_accu, NULL,
|
||||
gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, GST_TYPE_BUFFER);
|
||||
|
||||
store_class->cleared = gst_buffer_store_cleared_func;
|
||||
store_class->buffer_added = gst_buffer_store_add_buffer_func;
|
||||
}
|
||||
static void
|
||||
gst_buffer_store_init (GstBufferStore *store)
|
||||
gst_buffer_store_init (GstBufferStore * store)
|
||||
{
|
||||
store->buffers = NULL;
|
||||
}
|
||||
static void
|
||||
gst_buffer_store_dispose (GObject *object)
|
||||
gst_buffer_store_dispose (GObject * object)
|
||||
{
|
||||
GstBufferStore *store = GST_BUFFER_STORE (object);
|
||||
|
||||
|
@ -111,22 +117,24 @@ gst_buffer_store_dispose (GObject *object)
|
|||
|
||||
parent_class->dispose (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_buffer_store_add_buffer_func (GstBufferStore *store, GstBuffer *buffer)
|
||||
gst_buffer_store_add_buffer_func (GstBufferStore * store, GstBuffer * buffer)
|
||||
{
|
||||
g_assert (buffer != NULL);
|
||||
|
||||
|
||||
if (!GST_BUFFER_OFFSET_IS_VALID (buffer) &&
|
||||
store->buffers &&
|
||||
GST_BUFFER_OFFSET_IS_VALID (store->buffers->data)) {
|
||||
store->buffers && GST_BUFFER_OFFSET_IS_VALID (store->buffers->data)) {
|
||||
/* we assumed valid offsets, but suddenly they are not anymore */
|
||||
GST_DEBUG_OBJECT (store, "attempting to add buffer %p with invalid offset to store with valid offset, abort",
|
||||
buffer);
|
||||
GST_DEBUG_OBJECT (store,
|
||||
"attempting to add buffer %p with invalid offset to store with valid offset, abort",
|
||||
buffer);
|
||||
return FALSE;
|
||||
} else if (!store->buffers || !GST_BUFFER_OFFSET_IS_VALID (store->buffers->data)) {
|
||||
} else if (!store->buffers
|
||||
|| !GST_BUFFER_OFFSET_IS_VALID (store->buffers->data)) {
|
||||
/* the starting buffer had an invalid offset, in that case we assume continuous buffers */
|
||||
GST_LOG_OBJECT (store, "adding buffer %p with invalid offset and size %u",
|
||||
buffer, GST_BUFFER_SIZE (buffer));
|
||||
buffer, GST_BUFFER_SIZE (buffer));
|
||||
gst_data_ref (GST_DATA (buffer));
|
||||
store->buffers = g_list_append (store->buffers, buffer);
|
||||
return TRUE;
|
||||
|
@ -134,10 +142,12 @@ gst_buffer_store_add_buffer_func (GstBufferStore *store, GstBuffer *buffer)
|
|||
/* both list and buffer have valid offsets, we can really go wild */
|
||||
GList *walk, *current_list = NULL;
|
||||
GstBuffer *current;
|
||||
|
||||
|
||||
g_assert (GST_BUFFER_OFFSET_IS_VALID (buffer));
|
||||
GST_LOG_OBJECT (store, "attempting to add buffer %p with offset %"G_GUINT64_FORMAT" and size %u",
|
||||
buffer, GST_BUFFER_OFFSET (buffer), GST_BUFFER_SIZE (buffer));
|
||||
GST_LOG_OBJECT (store,
|
||||
"attempting to add buffer %p with offset %" G_GUINT64_FORMAT
|
||||
" and size %u", buffer, GST_BUFFER_OFFSET (buffer),
|
||||
GST_BUFFER_SIZE (buffer));
|
||||
/* we keep a sorted list of non-overlapping buffers */
|
||||
walk = store->buffers;
|
||||
while (walk) {
|
||||
|
@ -148,9 +158,10 @@ gst_buffer_store_add_buffer_func (GstBufferStore *store, GstBuffer *buffer)
|
|||
continue;
|
||||
} else if (GST_BUFFER_OFFSET (current) == GST_BUFFER_OFFSET (buffer)) {
|
||||
guint needed_size;
|
||||
|
||||
if (walk) {
|
||||
needed_size = MIN (GST_BUFFER_SIZE (buffer),
|
||||
GST_BUFFER_OFFSET (walk->data) - GST_BUFFER_OFFSET (current));
|
||||
needed_size = MIN (GST_BUFFER_SIZE (buffer),
|
||||
GST_BUFFER_OFFSET (walk->data) - GST_BUFFER_OFFSET (current));
|
||||
} else {
|
||||
needed_size = GST_BUFFER_SIZE (buffer);
|
||||
}
|
||||
|
@ -161,14 +172,17 @@ gst_buffer_store_add_buffer_func (GstBufferStore *store, GstBuffer *buffer)
|
|||
if (needed_size < GST_BUFFER_SIZE (buffer)) {
|
||||
/* need to create subbuffer to not have overlapping data */
|
||||
GstBuffer *sub = gst_buffer_create_sub (buffer, 0, needed_size);
|
||||
|
||||
g_assert (sub);
|
||||
buffer = sub;
|
||||
} else {
|
||||
gst_data_ref (GST_DATA (buffer));
|
||||
}
|
||||
/* replace current buffer with new one */
|
||||
GST_INFO_OBJECT (store, "replacing buffer %p with buffer %p with offset %"G_GINT64_FORMAT" and size %u",
|
||||
current_list->data, buffer, GST_BUFFER_OFFSET (buffer), GST_BUFFER_SIZE (buffer));
|
||||
GST_INFO_OBJECT (store,
|
||||
"replacing buffer %p with buffer %p with offset %" G_GINT64_FORMAT
|
||||
" and size %u", current_list->data, buffer,
|
||||
GST_BUFFER_OFFSET (buffer), GST_BUFFER_SIZE (buffer));
|
||||
gst_data_unref (GST_DATA (current_list->data));
|
||||
current_list->data = buffer;
|
||||
buffer = NULL;
|
||||
|
@ -176,8 +190,9 @@ gst_buffer_store_add_buffer_func (GstBufferStore *store, GstBuffer *buffer)
|
|||
}
|
||||
} else if (GST_BUFFER_OFFSET (current) > GST_BUFFER_OFFSET (buffer)) {
|
||||
GList *previous = g_list_previous (current_list);
|
||||
guint64 start_offset = previous ?
|
||||
GST_BUFFER_OFFSET (previous->data) + GST_BUFFER_SIZE (previous->data) : 0;
|
||||
guint64 start_offset = previous ?
|
||||
GST_BUFFER_OFFSET (previous->data) +
|
||||
GST_BUFFER_SIZE (previous->data) : 0;
|
||||
|
||||
if (start_offset == GST_BUFFER_OFFSET (current)) {
|
||||
buffer = NULL;
|
||||
|
@ -185,23 +200,28 @@ gst_buffer_store_add_buffer_func (GstBufferStore *store, GstBuffer *buffer)
|
|||
} else {
|
||||
/* we have data to insert */
|
||||
if (start_offset > GST_BUFFER_OFFSET (buffer) ||
|
||||
GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer) > GST_BUFFER_OFFSET (current)) {
|
||||
GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer) >
|
||||
GST_BUFFER_OFFSET (current)) {
|
||||
GstBuffer *sub;
|
||||
|
||||
/* need a subbuffer */
|
||||
start_offset = GST_BUFFER_OFFSET (buffer) > start_offset ? 0 :
|
||||
start_offset - GST_BUFFER_OFFSET (buffer);
|
||||
start_offset = GST_BUFFER_OFFSET (buffer) > start_offset ? 0 :
|
||||
start_offset - GST_BUFFER_OFFSET (buffer);
|
||||
sub = gst_buffer_create_sub (buffer, start_offset,
|
||||
MIN (GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (current) - start_offset - GST_BUFFER_OFFSET (buffer)));
|
||||
MIN (GST_BUFFER_SIZE (buffer),
|
||||
GST_BUFFER_OFFSET (current) - start_offset -
|
||||
GST_BUFFER_OFFSET (buffer)));
|
||||
g_assert (sub);
|
||||
GST_BUFFER_OFFSET (sub) = start_offset + GST_BUFFER_OFFSET (buffer);
|
||||
buffer = sub;
|
||||
} else {
|
||||
gst_data_ref (GST_DATA (buffer));
|
||||
}
|
||||
GST_INFO_OBJECT (store, "adding buffer %p with offset %"G_GINT64_FORMAT" and size %u",
|
||||
buffer, GST_BUFFER_OFFSET (buffer), GST_BUFFER_SIZE (buffer));
|
||||
store->buffers = g_list_insert_before (store->buffers, current_list, buffer);
|
||||
GST_INFO_OBJECT (store,
|
||||
"adding buffer %p with offset %" G_GINT64_FORMAT " and size %u",
|
||||
buffer, GST_BUFFER_OFFSET (buffer), GST_BUFFER_SIZE (buffer));
|
||||
store->buffers =
|
||||
g_list_insert_before (store->buffers, current_list, buffer);
|
||||
buffer = NULL;
|
||||
break;
|
||||
}
|
||||
|
@ -209,8 +229,9 @@ gst_buffer_store_add_buffer_func (GstBufferStore *store, GstBuffer *buffer)
|
|||
}
|
||||
if (buffer) {
|
||||
gst_data_ref (GST_DATA (buffer));
|
||||
GST_INFO_OBJECT (store, "adding buffer %p with offset %"G_GINT64_FORMAT" and size %u",
|
||||
buffer, GST_BUFFER_OFFSET (buffer), GST_BUFFER_SIZE (buffer));
|
||||
GST_INFO_OBJECT (store,
|
||||
"adding buffer %p with offset %" G_GINT64_FORMAT " and size %u",
|
||||
buffer, GST_BUFFER_OFFSET (buffer), GST_BUFFER_SIZE (buffer));
|
||||
if (current_list) {
|
||||
g_list_append (current_list, buffer);
|
||||
} else {
|
||||
|
@ -222,12 +243,13 @@ gst_buffer_store_add_buffer_func (GstBufferStore *store, GstBuffer *buffer)
|
|||
}
|
||||
}
|
||||
static void
|
||||
gst_buffer_store_cleared_func (GstBufferStore *store)
|
||||
gst_buffer_store_cleared_func (GstBufferStore * store)
|
||||
{
|
||||
g_list_foreach (store->buffers, (GFunc) gst_data_unref, NULL);
|
||||
g_list_free (store->buffers);
|
||||
store->buffers = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_buffer_store_new:
|
||||
*
|
||||
|
@ -240,6 +262,7 @@ gst_buffer_store_new (void)
|
|||
{
|
||||
return GST_BUFFER_STORE (g_object_new (GST_TYPE_BUFFER_STORE, NULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_buffer_store_clear:
|
||||
* @store: a bufferstore
|
||||
|
@ -249,12 +272,13 @@ gst_buffer_store_new (void)
|
|||
*/
|
||||
/* FIXME: call this function _reset ? */
|
||||
void
|
||||
gst_buffer_store_clear (GstBufferStore *store)
|
||||
gst_buffer_store_clear (GstBufferStore * store)
|
||||
{
|
||||
g_return_if_fail (GST_IS_BUFFER_STORE (store));
|
||||
|
||||
g_signal_emit (store, gst_buffer_store_signals [CLEARED], 0, NULL);
|
||||
|
||||
g_signal_emit (store, gst_buffer_store_signals[CLEARED], 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_buffer_store_add_buffer:
|
||||
* @store: a bufferstore
|
||||
|
@ -265,10 +289,10 @@ gst_buffer_store_clear (GstBufferStore *store)
|
|||
* Returns: TRUE, if the buffer was added, FALSE if an error occured.
|
||||
*/
|
||||
gboolean
|
||||
gst_buffer_store_add_buffer (GstBufferStore *store, GstBuffer *buffer)
|
||||
gst_buffer_store_add_buffer (GstBufferStore * store, GstBuffer * buffer)
|
||||
{
|
||||
gboolean ret;
|
||||
|
||||
|
||||
g_return_val_if_fail (GST_IS_BUFFER_STORE (store), FALSE);
|
||||
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
|
||||
|
||||
|
@ -276,11 +300,13 @@ gst_buffer_store_add_buffer (GstBufferStore *store, GstBuffer *buffer)
|
|||
GST_BUFFER_OFFSET_IS_VALID (store->buffers->data) &&
|
||||
!GST_BUFFER_OFFSET_IS_VALID (buffer))
|
||||
return FALSE;
|
||||
|
||||
g_signal_emit (store, gst_buffer_store_signals [BUFFER_ADDED], 0, buffer, &ret);
|
||||
|
||||
|
||||
g_signal_emit (store, gst_buffer_store_signals[BUFFER_ADDED], 0, buffer,
|
||||
&ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_buffer_store_get_buffer:
|
||||
* @store: a bufferstore
|
||||
|
@ -295,7 +321,7 @@ gst_buffer_store_add_buffer (GstBufferStore *store, GstBuffer *buffer)
|
|||
* available.
|
||||
*/
|
||||
GstBuffer *
|
||||
gst_buffer_store_get_buffer (GstBufferStore *store, guint64 offset, guint size)
|
||||
gst_buffer_store_get_buffer (GstBufferStore * store, guint64 offset, guint size)
|
||||
{
|
||||
GstBuffer *current;
|
||||
GList *walk;
|
||||
|
@ -324,38 +350,39 @@ gst_buffer_store_get_buffer (GstBufferStore *store, guint64 offset, guint size)
|
|||
if (cur_offset > offset) {
|
||||
/* #include <windows.h>
|
||||
do_nothing_loop (); */
|
||||
} else if (cur_offset == offset &&
|
||||
GST_BUFFER_SIZE (current) == size) {
|
||||
GST_LOG_OBJECT (store, "found matching buffer %p for offset %"G_GUINT64_FORMAT" and size %u",
|
||||
current, offset, size);
|
||||
} else if (cur_offset == offset && GST_BUFFER_SIZE (current) == size) {
|
||||
GST_LOG_OBJECT (store,
|
||||
"found matching buffer %p for offset %" G_GUINT64_FORMAT
|
||||
" and size %u", current, offset, size);
|
||||
ret = current;
|
||||
gst_data_ref (GST_DATA (ret));
|
||||
GST_LOG_OBJECT (store, "refcount %d",
|
||||
GST_DATA_REFCOUNT_VALUE(ret));
|
||||
GST_LOG_OBJECT (store, "refcount %d", GST_DATA_REFCOUNT_VALUE (ret));
|
||||
break;
|
||||
} else if (cur_offset + GST_BUFFER_SIZE (current) > offset) {
|
||||
if (cur_offset + GST_BUFFER_SIZE (current) >= offset + size) {
|
||||
ret = gst_buffer_create_sub (current, offset - cur_offset, size);
|
||||
GST_LOG_OBJECT (store, "created subbuffer %p from buffer %p for offset %llu and size %u",
|
||||
ret, current, offset, size);
|
||||
GST_LOG_OBJECT (store,
|
||||
"created subbuffer %p from buffer %p for offset %llu and size %u",
|
||||
ret, current, offset, size);
|
||||
break;
|
||||
}
|
||||
/* uh, the requested data spans some buffers */
|
||||
ret = gst_buffer_new_and_alloc (size);
|
||||
GST_LOG_OBJECT (store, "created buffer %p for offset %"G_GUINT64_FORMAT
|
||||
" and size %u, will fill with data now",
|
||||
ret, offset, size);
|
||||
GST_LOG_OBJECT (store, "created buffer %p for offset %" G_GUINT64_FORMAT
|
||||
" and size %u, will fill with data now", ret, offset, size);
|
||||
data = GST_BUFFER_DATA (ret);
|
||||
tmp = GST_BUFFER_SIZE (current) - offset + cur_offset;
|
||||
memcpy (data, GST_BUFFER_DATA (current) + offset - cur_offset, tmp);
|
||||
data += tmp;
|
||||
size -= tmp;
|
||||
while (size) {
|
||||
if (walk == NULL ||
|
||||
(have_offset &&
|
||||
GST_BUFFER_OFFSET (current) + GST_BUFFER_SIZE (current) != GST_BUFFER_OFFSET (walk->data))) {
|
||||
GST_DEBUG_OBJECT (store, "not all data for offset %"G_GUINT64_FORMAT" and remaining size %u available, aborting",
|
||||
offset, size);
|
||||
if (walk == NULL ||
|
||||
(have_offset &&
|
||||
GST_BUFFER_OFFSET (current) + GST_BUFFER_SIZE (current) !=
|
||||
GST_BUFFER_OFFSET (walk->data))) {
|
||||
GST_DEBUG_OBJECT (store,
|
||||
"not all data for offset %" G_GUINT64_FORMAT
|
||||
" and remaining size %u available, aborting", offset, size);
|
||||
gst_data_unref (GST_DATA (ret));
|
||||
ret = NULL;
|
||||
goto out;
|
||||
|
@ -373,9 +400,10 @@ gst_buffer_store_get_buffer (GstBufferStore *store, guint64 offset, guint size)
|
|||
}
|
||||
}
|
||||
out:
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_buffer_store_get_size:
|
||||
* @store: a bufferstore
|
||||
|
@ -388,7 +416,7 @@ out:
|
|||
* offset.
|
||||
*/
|
||||
guint
|
||||
gst_buffer_store_get_size (GstBufferStore *store, guint64 offset)
|
||||
gst_buffer_store_get_size (GstBufferStore * store, guint64 offset)
|
||||
{
|
||||
GList *walk;
|
||||
gboolean have_offset;
|
||||
|
@ -408,8 +436,9 @@ gst_buffer_store_get_size (GstBufferStore *store, guint64 offset)
|
|||
have_offset = FALSE;
|
||||
}
|
||||
while (walk) {
|
||||
if (have_offset && counting &&
|
||||
cur_offset + GST_BUFFER_SIZE (current) != GST_BUFFER_OFFSET (walk->data)) {
|
||||
if (have_offset && counting &&
|
||||
cur_offset + GST_BUFFER_SIZE (current) !=
|
||||
GST_BUFFER_OFFSET (walk->data)) {
|
||||
break;
|
||||
}
|
||||
current = GST_BUFFER (walk->data);
|
||||
|
@ -432,6 +461,6 @@ gst_buffer_store_get_size (GstBufferStore *store, guint64 offset)
|
|||
cur_offset += GST_BUFFER_SIZE (current);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -28,46 +28,42 @@
|
|||
#include <gst/gstmarshal.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_BUFFER_STORE (gst_buffer_store_get_type ())
|
||||
#define GST_BUFFER_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_BUFFER_STORE, GstBufferStore))
|
||||
#define GST_IS_BUFFER_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_BUFFER_STORE))
|
||||
#define GST_BUFFER_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_BUFFER_STORE, GstBufferStoreClass))
|
||||
#define GST_IS_BUFFER_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_BUFFER_STORE))
|
||||
#define GST_BUFFER_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BUFFER_STORE, GstBufferStoreClass))
|
||||
typedef struct _GstBufferStore GstBufferStore;
|
||||
typedef struct _GstBufferStoreClass GstBufferStoreClass;
|
||||
|
||||
typedef struct _GstBufferStore GstBufferStore;
|
||||
typedef struct _GstBufferStoreClass GstBufferStoreClass;
|
||||
struct _GstBufferStore
|
||||
{
|
||||
GObject object;
|
||||
|
||||
struct _GstBufferStore {
|
||||
GObject object;
|
||||
|
||||
GList * buffers;
|
||||
GList *buffers;
|
||||
};
|
||||
|
||||
struct _GstBufferStoreClass {
|
||||
GObjectClass parent_class;
|
||||
struct _GstBufferStoreClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (* cleared) (GstBufferStore * store);
|
||||
gboolean (* buffer_added) (GstBufferStore * store,
|
||||
GstBuffer * buffer);
|
||||
void (*cleared) (GstBufferStore * store);
|
||||
gboolean (*buffer_added) (GstBufferStore * store, GstBuffer * buffer);
|
||||
};
|
||||
|
||||
GType gst_buffer_store_get_type (void);
|
||||
GType gst_buffer_store_get_type (void);
|
||||
|
||||
GstBufferStore * gst_buffer_store_new (void);
|
||||
void gst_buffer_store_clear (GstBufferStore * store);
|
||||
GstBufferStore *gst_buffer_store_new (void);
|
||||
void gst_buffer_store_clear (GstBufferStore * store);
|
||||
|
||||
gboolean gst_buffer_store_add_buffer (GstBufferStore * store,
|
||||
GstBuffer * buffer);
|
||||
gboolean gst_buffer_store_add_buffer (GstBufferStore * store,
|
||||
GstBuffer * buffer);
|
||||
|
||||
GstBuffer * gst_buffer_store_get_buffer (GstBufferStore * store,
|
||||
guint64 offset,
|
||||
guint size);
|
||||
guint gst_buffer_store_get_size (GstBufferStore * store,
|
||||
guint64 offset);
|
||||
GstBuffer *gst_buffer_store_get_buffer (GstBufferStore * store,
|
||||
guint64 offset, guint size);
|
||||
guint gst_buffer_store_get_size (GstBufferStore * store, guint64 offset);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_BUFFER_STORE_H__ */
|
||||
|
|
|
@ -44,42 +44,44 @@
|
|||
#include "gsttypefind.h"
|
||||
|
||||
|
||||
struct _elements_entry {
|
||||
struct _elements_entry
|
||||
{
|
||||
gchar *name;
|
||||
guint rank;
|
||||
GType (*type) (void);
|
||||
GType (*type) (void);
|
||||
};
|
||||
|
||||
|
||||
extern GType gst_filesrc_get_type(void);
|
||||
extern GType gst_filesrc_get_type (void);
|
||||
extern GstElementDetails gst_filesrc_details;
|
||||
|
||||
static struct _elements_entry _elements[] = {
|
||||
{ "aggregator", GST_RANK_NONE, gst_aggregator_get_type },
|
||||
{ "fakesrc", GST_RANK_NONE, gst_fakesrc_get_type },
|
||||
{ "fakesink", GST_RANK_NONE, gst_fakesink_get_type },
|
||||
{ "fdsink", GST_RANK_NONE, gst_fdsink_get_type },
|
||||
{ "fdsrc", GST_RANK_NONE, gst_fdsrc_get_type },
|
||||
{ "filesrc", GST_RANK_NONE, gst_filesrc_get_type },
|
||||
{ "filesink", GST_RANK_NONE, gst_filesink_get_type },
|
||||
{ "identity", GST_RANK_NONE, gst_identity_get_type },
|
||||
{ "md5sink", GST_RANK_NONE, gst_md5sink_get_type },
|
||||
{ "multifilesrc", GST_RANK_NONE, gst_multifilesrc_get_type },
|
||||
{ "pipefilter", GST_RANK_NONE, gst_pipefilter_get_type },
|
||||
{ "shaper", GST_RANK_NONE, gst_shaper_get_type },
|
||||
{ "statistics", GST_RANK_NONE, gst_statistics_get_type },
|
||||
{ "tee", GST_RANK_NONE, gst_tee_get_type },
|
||||
{ "typefind", GST_RANK_NONE, gst_type_find_element_get_type },
|
||||
{ NULL, 0 },
|
||||
{"aggregator", GST_RANK_NONE, gst_aggregator_get_type},
|
||||
{"fakesrc", GST_RANK_NONE, gst_fakesrc_get_type},
|
||||
{"fakesink", GST_RANK_NONE, gst_fakesink_get_type},
|
||||
{"fdsink", GST_RANK_NONE, gst_fdsink_get_type},
|
||||
{"fdsrc", GST_RANK_NONE, gst_fdsrc_get_type},
|
||||
{"filesrc", GST_RANK_NONE, gst_filesrc_get_type},
|
||||
{"filesink", GST_RANK_NONE, gst_filesink_get_type},
|
||||
{"identity", GST_RANK_NONE, gst_identity_get_type},
|
||||
{"md5sink", GST_RANK_NONE, gst_md5sink_get_type},
|
||||
{"multifilesrc", GST_RANK_NONE, gst_multifilesrc_get_type},
|
||||
{"pipefilter", GST_RANK_NONE, gst_pipefilter_get_type},
|
||||
{"shaper", GST_RANK_NONE, gst_shaper_get_type},
|
||||
{"statistics", GST_RANK_NONE, gst_statistics_get_type},
|
||||
{"tee", GST_RANK_NONE, gst_tee_get_type},
|
||||
{"typefind", GST_RANK_NONE, gst_type_find_element_get_type},
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin *plugin)
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
struct _elements_entry *my_elements = _elements;
|
||||
|
||||
while ((*my_elements).name) {
|
||||
if (!gst_element_register (plugin, (*my_elements).name, (*my_elements).rank, ((*my_elements).type) ()))
|
||||
|
||||
while ((*my_elements).name) {
|
||||
if (!gst_element_register (plugin, (*my_elements).name, (*my_elements).rank,
|
||||
((*my_elements).type) ()))
|
||||
return FALSE;
|
||||
my_elements++;
|
||||
}
|
||||
|
@ -87,15 +89,8 @@ plugin_init (GstPlugin *plugin)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (
|
||||
GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"gstelements",
|
||||
"standard GStreamer elements",
|
||||
plugin_init,
|
||||
VERSION,
|
||||
GST_LICENSE,
|
||||
GST_PACKAGE,
|
||||
GST_ORIGIN
|
||||
)
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"gstelements",
|
||||
"standard GStreamer elements",
|
||||
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
|
||||
|
|
|
@ -31,22 +31,22 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_fakesink_debug);
|
||||
#define GST_CAT_DEFAULT gst_fakesink_debug
|
||||
|
||||
GstElementDetails gst_fakesink_details = GST_ELEMENT_DETAILS (
|
||||
"Fake Sink",
|
||||
"Sink",
|
||||
"Black hole for data",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>"
|
||||
);
|
||||
GstElementDetails gst_fakesink_details = GST_ELEMENT_DETAILS ("Fake Sink",
|
||||
"Sink",
|
||||
"Black hole for data",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>");
|
||||
|
||||
|
||||
/* FakeSink signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
SIGNAL_HANDOFF,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_STATE_ERROR,
|
||||
ARG_NUM_SINKS,
|
||||
|
@ -57,12 +57,10 @@ enum {
|
|||
ARG_LAST_MESSAGE,
|
||||
};
|
||||
|
||||
GstStaticPadTemplate fakesink_sink_template = GST_STATIC_PAD_TEMPLATE (
|
||||
"sink%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
GstStaticPadTemplate fakesink_sink_template = GST_STATIC_PAD_TEMPLATE ("sink%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
#define GST_TYPE_FAKESINK_STATE_ERROR (gst_fakesink_state_error_get_type())
|
||||
static GType
|
||||
|
@ -70,17 +68,24 @@ gst_fakesink_state_error_get_type (void)
|
|||
{
|
||||
static GType fakesink_state_error_type = 0;
|
||||
static GEnumValue fakesink_state_error[] = {
|
||||
{ FAKESINK_STATE_ERROR_NONE, "0", "No state change errors"},
|
||||
{ FAKESINK_STATE_ERROR_NULL_READY, "1", "Fail state change from NULL to READY"},
|
||||
{ FAKESINK_STATE_ERROR_READY_PAUSED, "2", "Fail state change from READY to PAUSED"},
|
||||
{ FAKESINK_STATE_ERROR_PAUSED_PLAYING, "3", "Fail state change from PAUSED to PLAYING"},
|
||||
{ FAKESINK_STATE_ERROR_PLAYING_PAUSED, "4", "Fail state change from PLAYING to PAUSED"},
|
||||
{ FAKESINK_STATE_ERROR_PAUSED_READY , "5", "Fail state change from PAUSED to READY"},
|
||||
{ FAKESINK_STATE_ERROR_READY_NULL , "6", "Fail state change from READY to NULL"},
|
||||
{FAKESINK_STATE_ERROR_NONE, "0", "No state change errors"},
|
||||
{FAKESINK_STATE_ERROR_NULL_READY, "1",
|
||||
"Fail state change from NULL to READY"},
|
||||
{FAKESINK_STATE_ERROR_READY_PAUSED, "2",
|
||||
"Fail state change from READY to PAUSED"},
|
||||
{FAKESINK_STATE_ERROR_PAUSED_PLAYING, "3",
|
||||
"Fail state change from PAUSED to PLAYING"},
|
||||
{FAKESINK_STATE_ERROR_PLAYING_PAUSED, "4",
|
||||
"Fail state change from PLAYING to PAUSED"},
|
||||
{FAKESINK_STATE_ERROR_PAUSED_READY, "5",
|
||||
"Fail state change from PAUSED to READY"},
|
||||
{FAKESINK_STATE_ERROR_READY_NULL, "6",
|
||||
"Fail state change from READY to NULL"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
if (!fakesink_state_error_type) {
|
||||
fakesink_state_error_type = g_enum_register_static ("GstFakeSinkStateError", fakesink_state_error);
|
||||
fakesink_state_error_type =
|
||||
g_enum_register_static ("GstFakeSinkStateError", fakesink_state_error);
|
||||
}
|
||||
return fakesink_state_error_type;
|
||||
}
|
||||
|
@ -88,82 +93,86 @@ gst_fakesink_state_error_get_type (void)
|
|||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_fakesink_debug, "fakesink", 0, "fakesink element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstFakeSink, gst_fakesink, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
GST_BOILERPLATE_FULL (GstFakeSink, gst_fakesink, GstElement, GST_TYPE_ELEMENT,
|
||||
_do_init);
|
||||
|
||||
static void gst_fakesink_set_clock (GstElement *element, GstClock *clock);
|
||||
static GstPad* gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ, const
|
||||
gchar *unused);
|
||||
static void gst_fakesink_set_clock (GstElement * element, GstClock * clock);
|
||||
static GstPad *gst_fakesink_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * unused);
|
||||
|
||||
static void gst_fakesink_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_fakesink_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
static void gst_fakesink_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_fakesink_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_fakesink_change_state (GstElement *element);
|
||||
static GstElementStateReturn gst_fakesink_change_state (GstElement * element);
|
||||
|
||||
static void gst_fakesink_chain (GstPad *pad, GstData *_data);
|
||||
static void gst_fakesink_chain (GstPad * pad, GstData * _data);
|
||||
|
||||
static guint gst_fakesink_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void
|
||||
gst_fakesink_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &gst_fakesink_details);
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&fakesink_sink_template));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesink_class_init (GstFakeSinkClass *klass)
|
||||
gst_fakesink_class_init (GstFakeSinkClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
||||
gobject_class = (GObjectClass*)klass;
|
||||
gstelement_class = (GstElementClass*)klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SINKS,
|
||||
g_param_spec_int ("num_sinks", "Number of sinks", "The number of sinkpads",
|
||||
1, G_MAXINT, 1, G_PARAM_READABLE));
|
||||
g_param_spec_int ("num_sinks", "Number of sinks",
|
||||
"The number of sinkpads", 1, G_MAXINT, 1, G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STATE_ERROR,
|
||||
g_param_spec_enum ("state_error", "State Error", "Generate a state change error",
|
||||
GST_TYPE_FAKESINK_STATE_ERROR, FAKESINK_STATE_ERROR_NONE, G_PARAM_READWRITE));
|
||||
g_param_spec_enum ("state_error", "State Error",
|
||||
"Generate a state change error", GST_TYPE_FAKESINK_STATE_ERROR,
|
||||
FAKESINK_STATE_ERROR_NONE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
|
||||
g_param_spec_string ("last_message", "Last Message", "The message describing current status",
|
||||
NULL, G_PARAM_READABLE));
|
||||
g_param_spec_string ("last_message", "Last Message",
|
||||
"The message describing current status", NULL, G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SYNC,
|
||||
g_param_spec_boolean ("sync", "Sync", "Sync on the clock",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("sync", "Sync", "Sync on the clock", FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_HANDOFFS,
|
||||
g_param_spec_boolean ("signal-handoffs", "Signal handoffs", "Send a signal before unreffing the buffer",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("signal-handoffs", "Signal handoffs",
|
||||
"Send a signal before unreffing the buffer", FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
|
||||
g_param_spec_boolean ("silent", "Silent", "Don't produce last_message events",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("silent", "Silent",
|
||||
"Don't produce last_message events", FALSE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
|
||||
g_param_spec_boolean ("dump", "Dump", "Dump received bytes to stdout",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("dump", "Dump", "Dump received bytes to stdout",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
|
||||
gst_fakesink_signals[SIGNAL_HANDOFF] =
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstFakeSinkClass, handoff), NULL, NULL,
|
||||
gst_marshal_VOID__POINTER_OBJECT, G_TYPE_NONE, 2,
|
||||
GST_TYPE_BUFFER, GST_TYPE_PAD);
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstFakeSinkClass, handoff), NULL, NULL,
|
||||
gst_marshal_VOID__POINTER_OBJECT, G_TYPE_NONE, 2,
|
||||
GST_TYPE_BUFFER, GST_TYPE_PAD);
|
||||
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesink_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesink_get_property);
|
||||
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_fakesink_request_new_pad);
|
||||
gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_fakesink_set_clock);
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesink_change_state);
|
||||
gstelement_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_fakesink_request_new_pad);
|
||||
gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_fakesink_set_clock);
|
||||
gstelement_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_fakesink_change_state);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesink_init (GstFakeSink *fakesink)
|
||||
static void
|
||||
gst_fakesink_init (GstFakeSink * fakesink)
|
||||
{
|
||||
GstPad *pad;
|
||||
|
||||
|
@ -182,17 +191,18 @@ gst_fakesink_init (GstFakeSink *fakesink)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_fakesink_set_clock (GstElement *element, GstClock *clock)
|
||||
{
|
||||
gst_fakesink_set_clock (GstElement * element, GstClock * clock)
|
||||
{
|
||||
GstFakeSink *sink;
|
||||
|
||||
sink = GST_FAKESINK (element);
|
||||
|
||||
sink->clock = clock;
|
||||
}
|
||||
}
|
||||
|
||||
static GstPad*
|
||||
gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
|
||||
static GstPad *
|
||||
gst_fakesink_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
||||
const gchar * unused)
|
||||
{
|
||||
gchar *name;
|
||||
GstPad *sinkpad;
|
||||
|
@ -212,14 +222,15 @@ gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ, const
|
|||
sinkpad = gst_pad_new_from_template (templ, name);
|
||||
g_free (name);
|
||||
gst_pad_set_chain_function (sinkpad, GST_DEBUG_FUNCPTR (gst_fakesink_chain));
|
||||
|
||||
|
||||
gst_element_add_pad (GST_ELEMENT (fakesink), sinkpad);
|
||||
|
||||
return sinkpad;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
gst_fakesink_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstFakeSink *sink;
|
||||
|
||||
|
@ -247,16 +258,17 @@ gst_fakesink_set_property (GObject *object, guint prop_id, const GValue *value,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_fakesink_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstFakeSink *sink;
|
||||
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_FAKESINK (object));
|
||||
|
||||
|
||||
sink = GST_FAKESINK (object);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_NUM_SINKS:
|
||||
g_value_set_int (value, GST_ELEMENT (sink)->numsinkpads);
|
||||
|
@ -285,8 +297,8 @@ gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesink_chain (GstPad *pad, GstData *_data)
|
||||
static void
|
||||
gst_fakesink_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
GstBuffer *buf = GST_BUFFER (_data);
|
||||
GstFakeSink *fakesink;
|
||||
|
@ -299,51 +311,52 @@ gst_fakesink_chain (GstPad *pad, GstData *_data)
|
|||
|
||||
if (GST_IS_EVENT (buf)) {
|
||||
GstEvent *event = GST_EVENT (buf);
|
||||
|
||||
if (!fakesink->silent) {
|
||||
|
||||
if (!fakesink->silent) {
|
||||
g_free (fakesink->last_message);
|
||||
|
||||
fakesink->last_message = g_strdup_printf ("chain ******* (%s:%s)E (type: %d) %p",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE (event), event);
|
||||
|
||||
fakesink->last_message =
|
||||
g_strdup_printf ("chain ******* (%s:%s)E (type: %d) %p",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE (event), event);
|
||||
|
||||
g_object_notify (G_OBJECT (fakesink), "last_message");
|
||||
}
|
||||
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
if (fakesink->sync && fakesink->clock) {
|
||||
gint64 value = GST_EVENT_DISCONT_OFFSET (event, 0).value;
|
||||
gst_element_set_time (GST_ELEMENT (fakesink), value);
|
||||
if (fakesink->sync && fakesink->clock) {
|
||||
gint64 value = GST_EVENT_DISCONT_OFFSET (event, 0).value;
|
||||
|
||||
gst_element_set_time (GST_ELEMENT (fakesink), value);
|
||||
}
|
||||
default:
|
||||
gst_pad_event_default (pad, event);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (fakesink->sync && fakesink->clock) {
|
||||
if (fakesink->sync && fakesink->clock) {
|
||||
gst_element_wait (GST_ELEMENT (fakesink), GST_BUFFER_TIMESTAMP (buf));
|
||||
}
|
||||
|
||||
if (!fakesink->silent) {
|
||||
if (!fakesink->silent) {
|
||||
g_free (fakesink->last_message);
|
||||
|
||||
fakesink->last_message = g_strdup_printf ("chain ******* (%s:%s)< (%d bytes, timestamp: %"
|
||||
G_GINT64_FORMAT ", duration: %"
|
||||
G_GINT64_FORMAT ", offset: %"
|
||||
G_GINT64_FORMAT ", flags: %d) %p",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf),
|
||||
GST_BUFFER_TIMESTAMP (buf),
|
||||
GST_BUFFER_DURATION (buf),
|
||||
GST_BUFFER_OFFSET (buf),
|
||||
GST_BUFFER_FLAGS (buf), buf);
|
||||
|
||||
fakesink->last_message =
|
||||
g_strdup_printf ("chain ******* (%s:%s)< (%d bytes, timestamp: %"
|
||||
G_GINT64_FORMAT ", duration: %" G_GINT64_FORMAT ", offset: %"
|
||||
G_GINT64_FORMAT ", flags: %d) %p", GST_DEBUG_PAD_NAME (pad),
|
||||
GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf),
|
||||
GST_BUFFER_DURATION (buf), GST_BUFFER_OFFSET (buf),
|
||||
GST_BUFFER_FLAGS (buf), buf);
|
||||
|
||||
g_object_notify (G_OBJECT (fakesink), "last_message");
|
||||
}
|
||||
|
||||
if (fakesink->signal_handoffs)
|
||||
g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0, buf, pad);
|
||||
g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0,
|
||||
buf, pad);
|
||||
|
||||
if (fakesink->dump) {
|
||||
gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||
|
@ -353,7 +366,7 @@ gst_fakesink_chain (GstPad *pad, GstData *_data)
|
|||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_fakesink_change_state (GstElement *element)
|
||||
gst_fakesink_change_state (GstElement * element)
|
||||
{
|
||||
GstFakeSink *fakesink = GST_FAKESINK (element);
|
||||
|
||||
|
@ -395,4 +408,3 @@ error:
|
|||
GST_ELEMENT_ERROR (element, CORE, STATE_CHANGE, (NULL), (NULL));
|
||||
return GST_STATE_FAILURE;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GST_TYPE_FAKESINK \
|
||||
(gst_fakesink_get_type())
|
||||
#define GST_FAKESINK(obj) \
|
||||
|
@ -39,8 +37,8 @@ G_BEGIN_DECLS
|
|||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FAKESINK))
|
||||
#define GST_IS_FAKESINK_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FAKESINK))
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
FAKESINK_STATE_ERROR_NONE = 0,
|
||||
FAKESINK_STATE_ERROR_NULL_READY,
|
||||
FAKESINK_STATE_ERROR_READY_PAUSED,
|
||||
|
@ -53,30 +51,31 @@ typedef enum {
|
|||
typedef struct _GstFakeSink GstFakeSink;
|
||||
typedef struct _GstFakeSinkClass GstFakeSinkClass;
|
||||
|
||||
struct _GstFakeSink {
|
||||
GstElement element;
|
||||
struct _GstFakeSink
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
gboolean silent;
|
||||
gboolean dump;
|
||||
gboolean sync;
|
||||
gboolean signal_handoffs;
|
||||
GstClock *clock;
|
||||
gboolean silent;
|
||||
gboolean dump;
|
||||
gboolean sync;
|
||||
gboolean signal_handoffs;
|
||||
GstClock *clock;
|
||||
GstFakeSinkStateError state_error;
|
||||
|
||||
gchar *last_message;
|
||||
gchar *last_message;
|
||||
};
|
||||
|
||||
struct _GstFakeSinkClass {
|
||||
struct _GstFakeSinkClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*handoff) (GstElement *element, GstBuffer *buf, GstPad *pad);
|
||||
void (*handoff) (GstElement * element, GstBuffer * buf, GstPad * pad);
|
||||
};
|
||||
|
||||
GType gst_fakesink_get_type(void);
|
||||
GType gst_fakesink_get_type (void);
|
||||
|
||||
gboolean gst_fakesink_factory_init (GstElementFactory *factory);
|
||||
gboolean gst_fakesink_factory_init (GstElementFactory * factory);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_FAKESINK_H__ */
|
||||
|
|
|
@ -38,23 +38,23 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_fakesrc_debug);
|
||||
#define GST_CAT_DEFAULT gst_fakesrc_debug
|
||||
|
||||
GstElementDetails gst_fakesrc_details = GST_ELEMENT_DETAILS (
|
||||
"Fake Source",
|
||||
"Source",
|
||||
"Push empty (no data) buffers around",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>, "
|
||||
"Wim Taymans <wim.taymans@chello.be>"
|
||||
);
|
||||
GstElementDetails gst_fakesrc_details = GST_ELEMENT_DETAILS ("Fake Source",
|
||||
"Source",
|
||||
"Push empty (no data) buffers around",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>, "
|
||||
"Wim Taymans <wim.taymans@chello.be>");
|
||||
|
||||
|
||||
/* FakeSrc signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
SIGNAL_HANDOFF,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_NUM_SOURCES,
|
||||
ARG_LOOP_BASED,
|
||||
|
@ -74,43 +74,42 @@ enum {
|
|||
ARG_LAST_MESSAGE,
|
||||
};
|
||||
|
||||
GstStaticPadTemplate fakesrc_src_template = GST_STATIC_PAD_TEMPLATE (
|
||||
"src%d",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
GstStaticPadTemplate fakesrc_src_template = GST_STATIC_PAD_TEMPLATE ("src%d",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
#define GST_TYPE_FAKESRC_OUTPUT (gst_fakesrc_output_get_type())
|
||||
static GType
|
||||
gst_fakesrc_output_get_type (void)
|
||||
gst_fakesrc_output_get_type (void)
|
||||
{
|
||||
static GType fakesrc_output_type = 0;
|
||||
static GEnumValue fakesrc_output[] = {
|
||||
{ FAKESRC_FIRST_LAST_LOOP, "1", "First-Last loop"},
|
||||
{ FAKESRC_LAST_FIRST_LOOP, "2", "Last-First loop"},
|
||||
{ FAKESRC_PING_PONG, "3", "Ping-Pong"},
|
||||
{ FAKESRC_ORDERED_RANDOM, "4", "Ordered Random"},
|
||||
{ FAKESRC_RANDOM, "5", "Random"},
|
||||
{ FAKESRC_PATTERN_LOOP, "6", "Patttern loop"},
|
||||
{ FAKESRC_PING_PONG_PATTERN, "7", "Ping-Pong Pattern"},
|
||||
{ FAKESRC_GET_ALWAYS_SUCEEDS, "8", "'_get' Always succeeds"},
|
||||
{FAKESRC_FIRST_LAST_LOOP, "1", "First-Last loop"},
|
||||
{FAKESRC_LAST_FIRST_LOOP, "2", "Last-First loop"},
|
||||
{FAKESRC_PING_PONG, "3", "Ping-Pong"},
|
||||
{FAKESRC_ORDERED_RANDOM, "4", "Ordered Random"},
|
||||
{FAKESRC_RANDOM, "5", "Random"},
|
||||
{FAKESRC_PATTERN_LOOP, "6", "Patttern loop"},
|
||||
{FAKESRC_PING_PONG_PATTERN, "7", "Ping-Pong Pattern"},
|
||||
{FAKESRC_GET_ALWAYS_SUCEEDS, "8", "'_get' Always succeeds"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
if (!fakesrc_output_type) {
|
||||
fakesrc_output_type = g_enum_register_static ("GstFakeSrcOutput", fakesrc_output);
|
||||
fakesrc_output_type =
|
||||
g_enum_register_static ("GstFakeSrcOutput", fakesrc_output);
|
||||
}
|
||||
return fakesrc_output_type;
|
||||
}
|
||||
|
||||
#define GST_TYPE_FAKESRC_DATA (gst_fakesrc_data_get_type())
|
||||
static GType
|
||||
gst_fakesrc_data_get_type (void)
|
||||
gst_fakesrc_data_get_type (void)
|
||||
{
|
||||
static GType fakesrc_data_type = 0;
|
||||
static GEnumValue fakesrc_data[] = {
|
||||
{ FAKESRC_DATA_ALLOCATE, "1", "Allocate data"},
|
||||
{ FAKESRC_DATA_SUBBUFFER, "2", "Subbuffer data"},
|
||||
{FAKESRC_DATA_ALLOCATE, "1", "Allocate data"},
|
||||
{FAKESRC_DATA_SUBBUFFER, "2", "Subbuffer data"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
if (!fakesrc_data_type) {
|
||||
|
@ -121,36 +120,40 @@ gst_fakesrc_data_get_type (void)
|
|||
|
||||
#define GST_TYPE_FAKESRC_SIZETYPE (gst_fakesrc_sizetype_get_type())
|
||||
static GType
|
||||
gst_fakesrc_sizetype_get_type (void)
|
||||
gst_fakesrc_sizetype_get_type (void)
|
||||
{
|
||||
static GType fakesrc_sizetype_type = 0;
|
||||
static GEnumValue fakesrc_sizetype[] = {
|
||||
{ FAKESRC_SIZETYPE_NULL, "1", "Send empty buffers"},
|
||||
{ FAKESRC_SIZETYPE_FIXED, "2", "Fixed size buffers (sizemax sized)"},
|
||||
{ FAKESRC_SIZETYPE_RANDOM, "3", "Random sized buffers (sizemin <= size <= sizemax)"},
|
||||
{FAKESRC_SIZETYPE_NULL, "1", "Send empty buffers"},
|
||||
{FAKESRC_SIZETYPE_FIXED, "2", "Fixed size buffers (sizemax sized)"},
|
||||
{FAKESRC_SIZETYPE_RANDOM, "3",
|
||||
"Random sized buffers (sizemin <= size <= sizemax)"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
if (!fakesrc_sizetype_type) {
|
||||
fakesrc_sizetype_type = g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype);
|
||||
fakesrc_sizetype_type =
|
||||
g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype);
|
||||
}
|
||||
return fakesrc_sizetype_type;
|
||||
}
|
||||
|
||||
#define GST_TYPE_FAKESRC_FILLTYPE (gst_fakesrc_filltype_get_type())
|
||||
static GType
|
||||
gst_fakesrc_filltype_get_type (void)
|
||||
gst_fakesrc_filltype_get_type (void)
|
||||
{
|
||||
static GType fakesrc_filltype_type = 0;
|
||||
static GEnumValue fakesrc_filltype[] = {
|
||||
{ FAKESRC_FILLTYPE_NOTHING, "1", "Leave data as malloced"},
|
||||
{ FAKESRC_FILLTYPE_NULL, "2", "Fill buffers with zeros"},
|
||||
{ FAKESRC_FILLTYPE_RANDOM, "3", "Fill buffers with random crap"},
|
||||
{ FAKESRC_FILLTYPE_PATTERN, "4", "Fill buffers with pattern 0x00 -> 0xff"},
|
||||
{ FAKESRC_FILLTYPE_PATTERN_CONT, "5", "Fill buffers with pattern 0x00 -> 0xff that spans buffers"},
|
||||
{FAKESRC_FILLTYPE_NOTHING, "1", "Leave data as malloced"},
|
||||
{FAKESRC_FILLTYPE_NULL, "2", "Fill buffers with zeros"},
|
||||
{FAKESRC_FILLTYPE_RANDOM, "3", "Fill buffers with random crap"},
|
||||
{FAKESRC_FILLTYPE_PATTERN, "4", "Fill buffers with pattern 0x00 -> 0xff"},
|
||||
{FAKESRC_FILLTYPE_PATTERN_CONT, "5",
|
||||
"Fill buffers with pattern 0x00 -> 0xff that spans buffers"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
if (!fakesrc_filltype_type) {
|
||||
fakesrc_filltype_type = g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype);
|
||||
fakesrc_filltype_type =
|
||||
g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype);
|
||||
}
|
||||
return fakesrc_filltype_type;
|
||||
}
|
||||
|
@ -158,106 +161,113 @@ gst_fakesrc_filltype_get_type (void)
|
|||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_fakesrc_debug, "fakesrc", 0, "fakesrc element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstFakeSrc, gst_fakesrc, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
GST_BOILERPLATE_FULL (GstFakeSrc, gst_fakesrc, GstElement, GST_TYPE_ELEMENT,
|
||||
_do_init);
|
||||
|
||||
static GstPad* gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ,const gchar *unused);
|
||||
static void gst_fakesrc_update_functions (GstFakeSrc *src);
|
||||
static void gst_fakesrc_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_fakesrc_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
static GstPad *gst_fakesrc_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * unused);
|
||||
static void gst_fakesrc_update_functions (GstFakeSrc * src);
|
||||
static void gst_fakesrc_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_fakesrc_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstElementStateReturn gst_fakesrc_change_state (GstElement *element);
|
||||
static GstElementStateReturn gst_fakesrc_change_state (GstElement * element);
|
||||
|
||||
static GstData* gst_fakesrc_get (GstPad *pad);
|
||||
static void gst_fakesrc_loop (GstElement *element);
|
||||
static GstData *gst_fakesrc_get (GstPad * pad);
|
||||
static void gst_fakesrc_loop (GstElement * element);
|
||||
|
||||
static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void
|
||||
gst_fakesrc_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &gst_fakesrc_details);
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&fakesrc_src_template));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_class_init (GstFakeSrcClass *klass)
|
||||
gst_fakesrc_class_init (GstFakeSrcClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
||||
gobject_class = (GObjectClass*)klass;
|
||||
gstelement_class = (GstElementClass*)klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SOURCES,
|
||||
g_param_spec_int ("num-sources", "num-sources", "Number of sources",
|
||||
1, G_MAXINT, 1, G_PARAM_READABLE));
|
||||
g_param_spec_int ("num-sources", "num-sources", "Number of sources",
|
||||
1, G_MAXINT, 1, G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOOP_BASED,
|
||||
g_param_spec_boolean ("loop-based", "loop-based", "Enable loop-based operation",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("loop-based", "loop-based",
|
||||
"Enable loop-based operation", FALSE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_OUTPUT,
|
||||
g_param_spec_enum ("output", "output", "Output method (currently unused)",
|
||||
GST_TYPE_FAKESRC_OUTPUT, FAKESRC_FIRST_LAST_LOOP, G_PARAM_READWRITE));
|
||||
g_param_spec_enum ("output", "output", "Output method (currently unused)",
|
||||
GST_TYPE_FAKESRC_OUTPUT, FAKESRC_FIRST_LAST_LOOP, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATA,
|
||||
g_param_spec_enum ("data", "data", "Data allocation method",
|
||||
GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE));
|
||||
g_param_spec_enum ("data", "data", "Data allocation method",
|
||||
GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZETYPE,
|
||||
g_param_spec_enum ("sizetype", "sizetype", "How to determine buffer sizes",
|
||||
GST_TYPE_FAKESRC_SIZETYPE, FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE));
|
||||
g_param_spec_enum ("sizetype", "sizetype",
|
||||
"How to determine buffer sizes", GST_TYPE_FAKESRC_SIZETYPE,
|
||||
FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN,
|
||||
g_param_spec_int ("sizemin","sizemin","Minimum buffer size",
|
||||
0, G_MAXINT, DEFAULT_SIZEMIN, G_PARAM_READWRITE));
|
||||
g_param_spec_int ("sizemin", "sizemin", "Minimum buffer size", 0,
|
||||
G_MAXINT, DEFAULT_SIZEMIN, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMAX,
|
||||
g_param_spec_int ("sizemax","sizemax","Maximum buffer size",
|
||||
0, G_MAXINT, DEFAULT_SIZEMAX, G_PARAM_READWRITE));
|
||||
g_param_spec_int ("sizemax", "sizemax", "Maximum buffer size", 0,
|
||||
G_MAXINT, DEFAULT_SIZEMAX, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PARENTSIZE,
|
||||
g_param_spec_int ("parentsize","parentsize","Size of parent buffer for sub-buffered allocation",
|
||||
0, G_MAXINT, DEFAULT_PARENTSIZE, G_PARAM_READWRITE));
|
||||
g_param_spec_int ("parentsize", "parentsize",
|
||||
"Size of parent buffer for sub-buffered allocation", 0, G_MAXINT,
|
||||
DEFAULT_PARENTSIZE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILLTYPE,
|
||||
g_param_spec_enum ("filltype", "filltype", "How to fill the buffer, if at all",
|
||||
GST_TYPE_FAKESRC_FILLTYPE, FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE));
|
||||
g_param_spec_enum ("filltype", "filltype",
|
||||
"How to fill the buffer, if at all", GST_TYPE_FAKESRC_FILLTYPE,
|
||||
FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PATTERN,
|
||||
g_param_spec_string ("pattern", "pattern", "pattern",
|
||||
NULL, G_PARAM_READWRITE));
|
||||
g_param_spec_string ("pattern", "pattern", "pattern", NULL,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_BUFFERS,
|
||||
g_param_spec_int ("num-buffers", "num-buffers", "Number of buffers to output before sending EOS",
|
||||
G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
|
||||
g_param_spec_int ("num-buffers", "num-buffers",
|
||||
"Number of buffers to output before sending EOS", G_MININT, G_MAXINT,
|
||||
0, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EOS,
|
||||
g_param_spec_boolean ("eos", "eos", "Send out the EOS event?",
|
||||
TRUE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("eos", "eos", "Send out the EOS event?", TRUE,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
|
||||
g_param_spec_string ("last-message", "last-message", "The last status message",
|
||||
NULL, G_PARAM_READABLE));
|
||||
g_param_spec_string ("last-message", "last-message",
|
||||
"The last status message", NULL, G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
|
||||
g_param_spec_boolean ("silent", "Silent", "Don't produce last_message events",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("silent", "Silent",
|
||||
"Don't produce last_message events", FALSE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_HANDOFFS,
|
||||
g_param_spec_boolean ("signal-handoffs", "Signal handoffs", "Send a signal before pushing the buffer",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("signal-handoffs", "Signal handoffs",
|
||||
"Send a signal before pushing the buffer", FALSE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
|
||||
g_param_spec_boolean ("dump", "Dump", "Dump produced bytes to stdout",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("dump", "Dump", "Dump produced bytes to stdout",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
|
||||
gst_fakesrc_signals[SIGNAL_HANDOFF] =
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL,
|
||||
gst_marshal_VOID__POINTER_OBJECT, G_TYPE_NONE, 2,
|
||||
GST_TYPE_BUFFER, GST_TYPE_PAD);
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL,
|
||||
gst_marshal_VOID__POINTER_OBJECT, G_TYPE_NONE, 2,
|
||||
GST_TYPE_BUFFER, GST_TYPE_PAD);
|
||||
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property);
|
||||
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state);
|
||||
gstelement_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_init (GstFakeSrc *fakesrc)
|
||||
static void
|
||||
gst_fakesrc_init (GstFakeSrc * fakesrc)
|
||||
{
|
||||
GstPad *pad;
|
||||
|
||||
|
@ -289,8 +299,9 @@ gst_fakesrc_init (GstFakeSrc *fakesrc)
|
|||
fakesrc->last_message = NULL;
|
||||
}
|
||||
|
||||
static GstPad*
|
||||
gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
|
||||
static GstPad *
|
||||
gst_fakesrc_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
||||
const gchar * unused)
|
||||
{
|
||||
gchar *name;
|
||||
GstPad *srcpad;
|
||||
|
@ -317,7 +328,7 @@ gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ, const g
|
|||
}
|
||||
|
||||
static const GstFormat *
|
||||
gst_fakesrc_get_formats (GstPad *pad)
|
||||
gst_fakesrc_get_formats (GstPad * pad)
|
||||
{
|
||||
static const GstFormat formats[] = {
|
||||
GST_FORMAT_DEFAULT,
|
||||
|
@ -327,7 +338,7 @@ gst_fakesrc_get_formats (GstPad *pad)
|
|||
}
|
||||
|
||||
static const GstQueryType *
|
||||
gst_fakesrc_get_query_types (GstPad *pad)
|
||||
gst_fakesrc_get_query_types (GstPad * pad)
|
||||
{
|
||||
static const GstQueryType types[] = {
|
||||
GST_QUERY_TOTAL,
|
||||
|
@ -340,8 +351,8 @@ gst_fakesrc_get_query_types (GstPad *pad)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_fakesrc_query (GstPad *pad, GstQueryType type,
|
||||
GstFormat *format, gint64 *value)
|
||||
gst_fakesrc_query (GstPad * pad, GstQueryType type,
|
||||
GstFormat * format, gint64 * value)
|
||||
{
|
||||
GstFakeSrc *src = GST_FAKESRC (GST_PAD_PARENT (pad));
|
||||
|
||||
|
@ -360,24 +371,24 @@ gst_fakesrc_query (GstPad *pad, GstQueryType type,
|
|||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const GstEventMask *
|
||||
gst_fakesrc_get_event_mask (GstPad *pad)
|
||||
gst_fakesrc_get_event_mask (GstPad * pad)
|
||||
{
|
||||
static const GstEventMask masks[] = {
|
||||
{ GST_EVENT_SEEK, GST_SEEK_FLAG_FLUSH },
|
||||
{ GST_EVENT_SEEK_SEGMENT, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT_LOOP },
|
||||
{ GST_EVENT_FLUSH, 0 },
|
||||
{ 0, 0 },
|
||||
{GST_EVENT_SEEK, GST_SEEK_FLAG_FLUSH},
|
||||
{GST_EVENT_SEEK_SEGMENT, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT_LOOP},
|
||||
{GST_EVENT_FLUSH, 0},
|
||||
{0, 0},
|
||||
};
|
||||
return masks;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
|
||||
gst_fakesrc_event_handler (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstFakeSrc *src;
|
||||
|
||||
|
@ -388,14 +399,15 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
|
|||
src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
|
||||
|
||||
if (!GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) {
|
||||
break;
|
||||
break;
|
||||
}
|
||||
/* else we do a flush too */
|
||||
case GST_EVENT_SEEK_SEGMENT:
|
||||
src->segment_start = GST_EVENT_SEEK_OFFSET (event);
|
||||
src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event);
|
||||
src->buffer_count = src->segment_start;
|
||||
src->segment_loop = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_SEGMENT_LOOP;
|
||||
src->segment_loop =
|
||||
GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_SEGMENT_LOOP;
|
||||
break;
|
||||
case GST_EVENT_FLUSH:
|
||||
src->need_flush = TRUE;
|
||||
|
@ -409,14 +421,14 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_update_functions (GstFakeSrc *src)
|
||||
gst_fakesrc_update_functions (GstFakeSrc * src)
|
||||
{
|
||||
GList *pads;
|
||||
|
||||
if (src->loop_based) {
|
||||
gst_element_set_loop_function (GST_ELEMENT (src), GST_DEBUG_FUNCPTR (gst_fakesrc_loop));
|
||||
}
|
||||
else {
|
||||
gst_element_set_loop_function (GST_ELEMENT (src),
|
||||
GST_DEBUG_FUNCPTR (gst_fakesrc_loop));
|
||||
} else {
|
||||
gst_element_set_loop_function (GST_ELEMENT (src), NULL);
|
||||
}
|
||||
|
||||
|
@ -426,8 +438,7 @@ gst_fakesrc_update_functions (GstFakeSrc *src)
|
|||
|
||||
if (src->loop_based) {
|
||||
gst_pad_set_get_function (pad, NULL);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
|
||||
}
|
||||
|
||||
|
@ -441,7 +452,7 @@ gst_fakesrc_update_functions (GstFakeSrc *src)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_alloc_parent (GstFakeSrc *src)
|
||||
gst_fakesrc_alloc_parent (GstFakeSrc * src)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
|
||||
|
@ -454,13 +465,14 @@ gst_fakesrc_alloc_parent (GstFakeSrc *src)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
gst_fakesrc_set_property (GObject * object, guint prop_id, const GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstFakeSrc *src;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
src = GST_FAKESRC (object);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_LOOP_BASED:
|
||||
src->loop_based = g_value_get_boolean (value);
|
||||
|
@ -473,13 +485,13 @@ gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
|
|||
src->data = g_value_get_enum (value);
|
||||
|
||||
if (src->data == FAKESRC_DATA_SUBBUFFER) {
|
||||
if (!src->parent)
|
||||
gst_fakesrc_alloc_parent (src);
|
||||
if (!src->parent)
|
||||
gst_fakesrc_alloc_parent (src);
|
||||
} else {
|
||||
if (src->parent) {
|
||||
gst_buffer_unref (src->parent);
|
||||
src->parent = NULL;
|
||||
}
|
||||
if (src->parent) {
|
||||
gst_buffer_unref (src->parent);
|
||||
src->parent = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ARG_SIZETYPE:
|
||||
|
@ -504,7 +516,7 @@ gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
|
|||
break;
|
||||
case ARG_EOS:
|
||||
src->eos = g_value_get_boolean (value);
|
||||
GST_INFO ( "will EOS on next buffer");
|
||||
GST_INFO ("will EOS on next buffer");
|
||||
break;
|
||||
case ARG_SILENT:
|
||||
src->silent = g_value_get_boolean (value);
|
||||
|
@ -520,16 +532,17 @@ gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstFakeSrc *src;
|
||||
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_FAKESRC (object));
|
||||
|
||||
|
||||
src = GST_FAKESRC (object);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_NUM_SOURCES:
|
||||
g_value_set_int (value, GST_ELEMENT (src)->numsrcpads);
|
||||
|
@ -586,9 +599,9 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
|
|||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_prepare_buffer (GstFakeSrc *src, GstBuffer *buf)
|
||||
gst_fakesrc_prepare_buffer (GstFakeSrc * src, GstBuffer * buf)
|
||||
{
|
||||
if (GST_BUFFER_SIZE (buf) == 0)
|
||||
if (GST_BUFFER_SIZE (buf) == 0)
|
||||
return;
|
||||
|
||||
switch (src->filltype) {
|
||||
|
@ -601,7 +614,7 @@ gst_fakesrc_prepare_buffer (GstFakeSrc *src, GstBuffer *buf)
|
|||
guint8 *ptr = GST_BUFFER_DATA (buf);
|
||||
|
||||
for (i = GST_BUFFER_SIZE (buf); i; i--) {
|
||||
*ptr++ = (gint8)((255.0)*rand()/(RAND_MAX));
|
||||
*ptr++ = (gint8) ((255.0) * rand () / (RAND_MAX));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -623,29 +636,29 @@ gst_fakesrc_prepare_buffer (GstFakeSrc *src, GstBuffer *buf)
|
|||
}
|
||||
}
|
||||
|
||||
static GstBuffer*
|
||||
gst_fakesrc_alloc_buffer (GstFakeSrc *src, guint size)
|
||||
static GstBuffer *
|
||||
gst_fakesrc_alloc_buffer (GstFakeSrc * src, guint size)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_SIZE(buf) = size;
|
||||
GST_BUFFER_SIZE (buf) = size;
|
||||
|
||||
if (size != 0) {
|
||||
if (size != 0) {
|
||||
switch (src->filltype) {
|
||||
case FAKESRC_FILLTYPE_NOTHING:
|
||||
GST_BUFFER_DATA(buf) = g_malloc (size);
|
||||
break;
|
||||
GST_BUFFER_DATA (buf) = g_malloc (size);
|
||||
break;
|
||||
case FAKESRC_FILLTYPE_NULL:
|
||||
GST_BUFFER_DATA(buf) = g_malloc0 (size);
|
||||
break;
|
||||
GST_BUFFER_DATA (buf) = g_malloc0 (size);
|
||||
break;
|
||||
case FAKESRC_FILLTYPE_RANDOM:
|
||||
case FAKESRC_FILLTYPE_PATTERN:
|
||||
case FAKESRC_FILLTYPE_PATTERN_CONT:
|
||||
default:
|
||||
GST_BUFFER_DATA(buf) = g_malloc (size);
|
||||
gst_fakesrc_prepare_buffer (src, buf);
|
||||
break;
|
||||
GST_BUFFER_DATA (buf) = g_malloc (size);
|
||||
gst_fakesrc_prepare_buffer (src, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -653,7 +666,7 @@ gst_fakesrc_alloc_buffer (GstFakeSrc *src, guint size)
|
|||
}
|
||||
|
||||
static guint
|
||||
gst_fakesrc_get_size (GstFakeSrc *src)
|
||||
gst_fakesrc_get_size (GstFakeSrc * src)
|
||||
{
|
||||
guint size;
|
||||
|
||||
|
@ -662,11 +675,14 @@ gst_fakesrc_get_size (GstFakeSrc *src)
|
|||
size = src->sizemax;
|
||||
break;
|
||||
case FAKESRC_SIZETYPE_RANDOM:
|
||||
size = src->sizemin + (guint8)(((gfloat)src->sizemax)*rand()/(RAND_MAX + (gfloat)src->sizemin));
|
||||
size =
|
||||
src->sizemin +
|
||||
(guint8) (((gfloat) src->sizemax) * rand () / (RAND_MAX +
|
||||
(gfloat) src->sizemin));
|
||||
break;
|
||||
case FAKESRC_SIZETYPE_NULL:
|
||||
default:
|
||||
size = 0;
|
||||
size = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -674,7 +690,7 @@ gst_fakesrc_get_size (GstFakeSrc *src)
|
|||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_fakesrc_create_buffer (GstFakeSrc *src)
|
||||
gst_fakesrc_create_buffer (GstFakeSrc * src)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
guint size;
|
||||
|
@ -682,7 +698,7 @@ gst_fakesrc_create_buffer (GstFakeSrc *src)
|
|||
|
||||
size = gst_fakesrc_get_size (src);
|
||||
if (size == 0)
|
||||
return gst_buffer_new();
|
||||
return gst_buffer_new ();
|
||||
|
||||
switch (src->data) {
|
||||
case FAKESRC_DATA_ALLOCATE:
|
||||
|
@ -696,21 +712,20 @@ gst_fakesrc_create_buffer (GstFakeSrc *src)
|
|||
}
|
||||
/* see if it's large enough */
|
||||
if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) {
|
||||
buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
|
||||
src->parentoffset += size;
|
||||
}
|
||||
else {
|
||||
buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
|
||||
src->parentoffset += size;
|
||||
} else {
|
||||
/* the parent is useless now */
|
||||
gst_buffer_unref (src->parent);
|
||||
src->parent = NULL;
|
||||
/* try again (this will allocate a new parent) */
|
||||
return gst_fakesrc_create_buffer (src);
|
||||
return gst_fakesrc_create_buffer (src);
|
||||
}
|
||||
gst_fakesrc_prepare_buffer (src, buf);
|
||||
break;
|
||||
default:
|
||||
g_warning ("fakesrc: dunno how to allocate buffers !");
|
||||
buf = gst_buffer_new();
|
||||
buf = gst_buffer_new ();
|
||||
break;
|
||||
}
|
||||
if (dump) {
|
||||
|
@ -721,7 +736,7 @@ gst_fakesrc_create_buffer (GstFakeSrc *src)
|
|||
}
|
||||
|
||||
static GstData *
|
||||
gst_fakesrc_get(GstPad *pad)
|
||||
gst_fakesrc_get (GstPad * pad)
|
||||
{
|
||||
GstFakeSrc *src;
|
||||
GstBuffer *buf;
|
||||
|
@ -734,31 +749,29 @@ gst_fakesrc_get(GstPad *pad)
|
|||
|
||||
if (src->need_flush) {
|
||||
src->need_flush = FALSE;
|
||||
return GST_DATA(gst_event_new (GST_EVENT_FLUSH));
|
||||
return GST_DATA (gst_event_new (GST_EVENT_FLUSH));
|
||||
}
|
||||
|
||||
if (src->buffer_count == src->segment_end) {
|
||||
if (src->segment_loop) {
|
||||
return GST_DATA(gst_event_new (GST_EVENT_SEGMENT_DONE));
|
||||
}
|
||||
else {
|
||||
return GST_DATA (gst_event_new (GST_EVENT_SEGMENT_DONE));
|
||||
} else {
|
||||
gst_element_set_eos (GST_ELEMENT (src));
|
||||
return GST_DATA(gst_event_new (GST_EVENT_EOS));
|
||||
return GST_DATA (gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
}
|
||||
|
||||
if (src->rt_num_buffers == 0) {
|
||||
gst_element_set_eos (GST_ELEMENT (src));
|
||||
return GST_DATA(gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
else {
|
||||
return GST_DATA (gst_event_new (GST_EVENT_EOS));
|
||||
} else {
|
||||
if (src->rt_num_buffers > 0)
|
||||
src->rt_num_buffers--;
|
||||
}
|
||||
|
||||
if (src->eos) {
|
||||
GST_INFO ( "fakesrc is setting eos on pad");
|
||||
return GST_DATA(gst_event_new (GST_EVENT_EOS));
|
||||
GST_INFO ("fakesrc is setting eos on pad");
|
||||
return GST_DATA (gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
|
||||
buf = gst_fakesrc_create_buffer (src);
|
||||
|
@ -767,9 +780,10 @@ gst_fakesrc_get(GstPad *pad)
|
|||
if (!src->silent) {
|
||||
g_free (src->last_message);
|
||||
|
||||
src->last_message = g_strdup_printf ("get ******* (%s:%s)> (%d bytes, %"
|
||||
G_GUINT64_FORMAT " ) %p",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
|
||||
src->last_message =
|
||||
g_strdup_printf ("get ******* (%s:%s)> (%d bytes, %"
|
||||
G_GUINT64_FORMAT " ) %p", GST_DEBUG_PAD_NAME (pad),
|
||||
GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
|
||||
|
||||
g_object_notify (G_OBJECT (src), "last_message");
|
||||
}
|
||||
|
@ -777,7 +791,7 @@ gst_fakesrc_get(GstPad *pad)
|
|||
if (src->signal_handoffs) {
|
||||
GST_LOG_OBJECT (src, "pre handoff emit");
|
||||
g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
|
||||
buf, pad);
|
||||
buf, pad);
|
||||
GST_LOG_OBJECT (src, "post handoff emit");
|
||||
}
|
||||
|
||||
|
@ -791,13 +805,13 @@ gst_fakesrc_get(GstPad *pad)
|
|||
* generate an empty buffer and push it to the next element.
|
||||
*/
|
||||
static void
|
||||
gst_fakesrc_loop(GstElement *element)
|
||||
gst_fakesrc_loop (GstElement * element)
|
||||
{
|
||||
GstFakeSrc *src;
|
||||
const GList *pads;
|
||||
|
||||
g_return_if_fail(element != NULL);
|
||||
g_return_if_fail(GST_IS_FAKESRC(element));
|
||||
g_return_if_fail (element != NULL);
|
||||
g_return_if_fail (GST_IS_FAKESRC (element));
|
||||
|
||||
src = GST_FAKESRC (element);
|
||||
|
||||
|
@ -819,7 +833,7 @@ gst_fakesrc_loop(GstElement *element)
|
|||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_fakesrc_change_state (GstElement *element)
|
||||
gst_fakesrc_change_state (GstElement * element)
|
||||
{
|
||||
GstFakeSrc *fakesrc;
|
||||
|
||||
|
@ -842,8 +856,8 @@ gst_fakesrc_change_state (GstElement *element)
|
|||
break;
|
||||
case GST_STATE_PAUSED_TO_READY:
|
||||
if (fakesrc->parent) {
|
||||
gst_buffer_unref (fakesrc->parent);
|
||||
fakesrc->parent = NULL;
|
||||
gst_buffer_unref (fakesrc->parent);
|
||||
fakesrc->parent = NULL;
|
||||
}
|
||||
g_free (fakesrc->last_message);
|
||||
fakesrc->last_message = NULL;
|
||||
|
@ -860,4 +874,3 @@ gst_fakesrc_change_state (GstElement *element)
|
|||
|
||||
return GST_STATE_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,10 +26,8 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
typedef enum {
|
||||
G_BEGIN_DECLS typedef enum
|
||||
{
|
||||
FAKESRC_FIRST_LAST_LOOP = 1,
|
||||
FAKESRC_LAST_FIRST_LOOP,
|
||||
FAKESRC_PING_PONG,
|
||||
|
@ -40,18 +38,21 @@ typedef enum {
|
|||
FAKESRC_GET_ALWAYS_SUCEEDS
|
||||
} GstFakeSrcOutputType;
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
FAKESRC_DATA_ALLOCATE = 1,
|
||||
FAKESRC_DATA_SUBBUFFER,
|
||||
} GstFakeSrcDataType;
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
FAKESRC_SIZETYPE_NULL = 1,
|
||||
FAKESRC_SIZETYPE_FIXED,
|
||||
FAKESRC_SIZETYPE_RANDOM
|
||||
} GstFakeSrcSizeType;
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
FAKESRC_FILLTYPE_NOTHING = 1,
|
||||
FAKESRC_FILLTYPE_NULL,
|
||||
FAKESRC_FILLTYPE_RANDOM,
|
||||
|
@ -73,50 +74,51 @@ typedef enum {
|
|||
typedef struct _GstFakeSrc GstFakeSrc;
|
||||
typedef struct _GstFakeSrcClass GstFakeSrcClass;
|
||||
|
||||
struct _GstFakeSrc {
|
||||
GstElement element;
|
||||
struct _GstFakeSrc
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
gboolean loop_based;
|
||||
gboolean eos;
|
||||
gboolean loop_based;
|
||||
gboolean eos;
|
||||
|
||||
GstFakeSrcOutputType output;
|
||||
GstFakeSrcDataType data;
|
||||
GstFakeSrcSizeType sizetype;
|
||||
GstFakeSrcFillType filltype;
|
||||
GstFakeSrcDataType data;
|
||||
GstFakeSrcSizeType sizetype;
|
||||
GstFakeSrcFillType filltype;
|
||||
|
||||
guint sizemin;
|
||||
guint sizemax;
|
||||
GstBuffer *parent;
|
||||
guint parentsize;
|
||||
guint parentoffset;
|
||||
guint8 pattern_byte;
|
||||
gchar *pattern;
|
||||
GList *patternlist;
|
||||
gint64 segment_start;
|
||||
gint64 segment_end;
|
||||
gboolean segment_loop;
|
||||
gint num_buffers;
|
||||
gint rt_num_buffers; /* we are going to change this at runtime */
|
||||
guint64 buffer_count;
|
||||
gboolean silent;
|
||||
gboolean signal_handoffs;
|
||||
gboolean dump;
|
||||
gboolean need_flush;
|
||||
guint sizemin;
|
||||
guint sizemax;
|
||||
GstBuffer *parent;
|
||||
guint parentsize;
|
||||
guint parentoffset;
|
||||
guint8 pattern_byte;
|
||||
gchar *pattern;
|
||||
GList *patternlist;
|
||||
gint64 segment_start;
|
||||
gint64 segment_end;
|
||||
gboolean segment_loop;
|
||||
gint num_buffers;
|
||||
gint rt_num_buffers; /* we are going to change this at runtime */
|
||||
guint64 buffer_count;
|
||||
gboolean silent;
|
||||
gboolean signal_handoffs;
|
||||
gboolean dump;
|
||||
gboolean need_flush;
|
||||
|
||||
gchar *last_message;
|
||||
gchar *last_message;
|
||||
};
|
||||
|
||||
struct _GstFakeSrcClass {
|
||||
struct _GstFakeSrcClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*handoff) (GstElement *element, GstBuffer *buf, GstPad *pad);
|
||||
void (*handoff) (GstElement * element, GstBuffer * buf, GstPad * pad);
|
||||
};
|
||||
|
||||
GType gst_fakesrc_get_type(void);
|
||||
GType gst_fakesrc_get_type (void);
|
||||
|
||||
gboolean gst_fakesrc_factory_init (GstElementFactory *factory);
|
||||
gboolean gst_fakesrc_factory_init (GstElementFactory * factory);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_FAKESRC_H__ */
|
||||
|
|
|
@ -30,21 +30,22 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_fdsink_debug);
|
||||
#define GST_CAT_DEFAULT gst_fdsink_debug
|
||||
|
||||
GstElementDetails gst_fdsink_details = GST_ELEMENT_DETAILS (
|
||||
"Filedescriptor Sink",
|
||||
"Sink/File",
|
||||
"Write data to a file descriptor",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>"
|
||||
);
|
||||
GstElementDetails gst_fdsink_details =
|
||||
GST_ELEMENT_DETAILS ("Filedescriptor Sink",
|
||||
"Sink/File",
|
||||
"Write data to a file descriptor",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>");
|
||||
|
||||
|
||||
/* FdSink signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_FD
|
||||
};
|
||||
|
@ -53,25 +54,26 @@ enum {
|
|||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_fdsink_debug, "fdsink", 0, "fdsink element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstFdSink, gst_fdsink, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
GST_BOILERPLATE_FULL (GstFdSink, gst_fdsink, GstElement, GST_TYPE_ELEMENT,
|
||||
_do_init);
|
||||
|
||||
static void gst_fdsink_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_fdsink_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
static void gst_fdsink_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_fdsink_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static void gst_fdsink_chain (GstPad *pad,GstData *_data);
|
||||
static void gst_fdsink_chain (GstPad * pad, GstData * _data);
|
||||
|
||||
|
||||
static void
|
||||
gst_fdsink_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &gst_fdsink_details);
|
||||
}
|
||||
static void
|
||||
gst_fdsink_class_init (GstFdSinkClass *klass)
|
||||
gst_fdsink_class_init (GstFdSinkClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
|
||||
|
@ -79,15 +81,15 @@ gst_fdsink_class_init (GstFdSinkClass *klass)
|
|||
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FD,
|
||||
g_param_spec_int ("fd", "fd", "An open file descriptor to write to",
|
||||
0, G_MAXINT, 1, G_PARAM_READWRITE));
|
||||
g_param_spec_int ("fd", "fd", "An open file descriptor to write to",
|
||||
0, G_MAXINT, 1, G_PARAM_READWRITE));
|
||||
|
||||
gobject_class->set_property = gst_fdsink_set_property;
|
||||
gobject_class->get_property = gst_fdsink_get_property;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fdsink_init (GstFdSink *fdsink)
|
||||
static void
|
||||
gst_fdsink_init (GstFdSink * fdsink)
|
||||
{
|
||||
fdsink->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (fdsink), fdsink->sinkpad);
|
||||
|
@ -96,8 +98,8 @@ gst_fdsink_init (GstFdSink *fdsink)
|
|||
fdsink->fd = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fdsink_chain (GstPad *pad, GstData *_data)
|
||||
static void
|
||||
gst_fdsink_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
GstBuffer *buf = GST_BUFFER (_data);
|
||||
GstFdSink *fdsink;
|
||||
|
@ -107,25 +109,27 @@ gst_fdsink_chain (GstPad *pad, GstData *_data)
|
|||
g_return_if_fail (buf != NULL);
|
||||
|
||||
fdsink = GST_FDSINK (gst_pad_get_parent (pad));
|
||||
|
||||
|
||||
g_return_if_fail (fdsink->fd >= 0);
|
||||
|
||||
|
||||
if (GST_BUFFER_DATA (buf)) {
|
||||
GST_DEBUG ("writing %d bytes to file descriptor %d",GST_BUFFER_SIZE (buf), fdsink->fd);
|
||||
GST_DEBUG ("writing %d bytes to file descriptor %d", GST_BUFFER_SIZE (buf),
|
||||
fdsink->fd);
|
||||
write (fdsink->fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||
}
|
||||
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fdsink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_fdsink_set_property (GObject * object, guint prop_id, const GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstFdSink *fdsink;
|
||||
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_FDSINK (object));
|
||||
|
||||
|
||||
fdsink = GST_FDSINK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
|
@ -137,14 +141,15 @@ gst_fdsink_set_property (GObject *object, guint prop_id, const GValue *value, GP
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fdsink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_fdsink_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstFdSink *fdsink;
|
||||
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_FDSINK (object));
|
||||
|
||||
|
||||
fdsink = GST_FDSINK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GST_TYPE_FDSINK \
|
||||
(gst_fdsink_get_type())
|
||||
#define GST_FDSINK(obj) \
|
||||
|
@ -39,11 +37,11 @@ G_BEGIN_DECLS
|
|||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FDSINK))
|
||||
#define GST_IS_FDSINK_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FDSINK))
|
||||
|
||||
typedef struct _GstFdSink GstFdSink;
|
||||
typedef struct _GstFdSinkClass GstFdSinkClass;
|
||||
|
||||
struct _GstFdSink {
|
||||
struct _GstFdSink
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
GstPad *sinkpad;
|
||||
|
@ -51,12 +49,12 @@ struct _GstFdSink {
|
|||
int fd;
|
||||
};
|
||||
|
||||
struct _GstFdSinkClass {
|
||||
struct _GstFdSinkClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_fdsink_get_type(void);
|
||||
GType gst_fdsink_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_FDSINK_H__ */
|
||||
|
|
|
@ -39,21 +39,21 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_fdsrc_debug);
|
||||
#define GST_CAT_DEFAULT gst_fdsrc_debug
|
||||
|
||||
GstElementDetails gst_fdsrc_details = GST_ELEMENT_DETAILS (
|
||||
"Disk Source",
|
||||
"Source/File",
|
||||
"Synchronous read from a file",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>"
|
||||
);
|
||||
GstElementDetails gst_fdsrc_details = GST_ELEMENT_DETAILS ("Disk Source",
|
||||
"Source/File",
|
||||
"Synchronous read from a file",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>");
|
||||
|
||||
|
||||
/* FdSrc signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
SIGNAL_TIMEOUT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_FD,
|
||||
ARG_BLOCKSIZE,
|
||||
|
@ -65,52 +65,56 @@ static guint gst_fdsrc_signals[LAST_SIGNAL] = { 0 };
|
|||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_fdsrc_debug, "fdsrc", 0, "fdsrc element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstFdSrc, gst_fdsrc, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
GST_BOILERPLATE_FULL (GstFdSrc, gst_fdsrc, GstElement, GST_TYPE_ELEMENT,
|
||||
_do_init);
|
||||
|
||||
static void gst_fdsrc_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_fdsrc_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
static void gst_fdsrc_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_fdsrc_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstData * gst_fdsrc_get (GstPad *pad);
|
||||
static GstData *gst_fdsrc_get (GstPad * pad);
|
||||
|
||||
|
||||
static void
|
||||
gst_fdsrc_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &gst_fdsrc_details);
|
||||
}
|
||||
static void
|
||||
gst_fdsrc_class_init (GstFdSrcClass *klass)
|
||||
gst_fdsrc_class_init (GstFdSrcClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
|
||||
gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FD,
|
||||
g_param_spec_int ("fd", "fd", "An open file descriptor to read from",
|
||||
0, G_MAXINT, 0, G_PARAM_READWRITE));
|
||||
g_param_spec_int ("fd", "fd", "An open file descriptor to read from",
|
||||
0, G_MAXINT, 0, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BLOCKSIZE,
|
||||
g_param_spec_ulong ("blocksize", "Block size", "Size in bytes to read per buffer",
|
||||
1, G_MAXULONG, DEFAULT_BLOCKSIZE, G_PARAM_READWRITE));
|
||||
g_param_spec_ulong ("blocksize", "Block size",
|
||||
"Size in bytes to read per buffer", 1, G_MAXULONG, DEFAULT_BLOCKSIZE,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TIMEOUT,
|
||||
g_param_spec_uint64 ("timeout", "Timeout", "Read timeout in nanoseconds",
|
||||
0, G_MAXUINT64, 0, G_PARAM_READWRITE));
|
||||
g_param_spec_uint64 ("timeout", "Timeout", "Read timeout in nanoseconds",
|
||||
0, G_MAXUINT64, 0, G_PARAM_READWRITE));
|
||||
|
||||
gst_fdsrc_signals[SIGNAL_TIMEOUT] =
|
||||
g_signal_new ("timeout", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstFdSrcClass, timeout), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
g_signal_new ("timeout", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstFdSrcClass, timeout), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
|
||||
gobject_class->set_property = gst_fdsrc_set_property;
|
||||
gobject_class->get_property = gst_fdsrc_get_property;
|
||||
}
|
||||
|
||||
static void gst_fdsrc_init(GstFdSrc *fdsrc) {
|
||||
static void
|
||||
gst_fdsrc_init (GstFdSrc * fdsrc)
|
||||
{
|
||||
fdsrc->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
|
||||
|
||||
gst_pad_set_get_function (fdsrc->srcpad, gst_fdsrc_get);
|
||||
gst_element_add_pad (GST_ELEMENT (fdsrc), fdsrc->srcpad);
|
||||
|
||||
|
@ -122,14 +126,15 @@ static void gst_fdsrc_init(GstFdSrc *fdsrc) {
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
gst_fdsrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_fdsrc_set_property (GObject * object, guint prop_id, const GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstFdSrc *src;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_FDSRC (object));
|
||||
|
||||
|
||||
src = GST_FDSRC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
|
@ -147,14 +152,15 @@ gst_fdsrc_set_property (GObject *object, guint prop_id, const GValue *value, GPa
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fdsrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_fdsrc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstFdSrc *src;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_FDSRC (object));
|
||||
|
||||
|
||||
src = GST_FDSRC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
|
@ -174,7 +180,7 @@ gst_fdsrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpe
|
|||
}
|
||||
|
||||
static GstData *
|
||||
gst_fdsrc_get(GstPad *pad)
|
||||
gst_fdsrc_get (GstPad * pad)
|
||||
{
|
||||
GstFdSrc *src;
|
||||
GstBuffer *buf;
|
||||
|
@ -191,38 +197,31 @@ gst_fdsrc_get(GstPad *pad)
|
|||
FD_ZERO (&readfds);
|
||||
FD_SET (src->fd, &readfds);
|
||||
|
||||
if (src->timeout != 0)
|
||||
{
|
||||
if (src->timeout != 0) {
|
||||
GST_TIME_TO_TIMEVAL (src->timeout, t);
|
||||
}
|
||||
else
|
||||
} else
|
||||
tp = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
retval = select (1, &readfds, NULL, NULL, tp);
|
||||
} while (retval == -1 && errno == EINTR); /* retry if interrupted */
|
||||
} while (retval == -1 && errno == EINTR); /* retry if interrupted */
|
||||
|
||||
if (retval == -1)
|
||||
{
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("select on file descriptor: %s.", g_strerror(errno)));
|
||||
if (retval == -1) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
|
||||
("select on file descriptor: %s.", g_strerror (errno)));
|
||||
gst_element_set_eos (GST_ELEMENT (src));
|
||||
return GST_DATA (gst_event_new (GST_EVENT_EOS));
|
||||
} else if (retval == 0) {
|
||||
g_signal_emit (G_OBJECT (src), gst_fdsrc_signals[SIGNAL_TIMEOUT], 0);
|
||||
gst_element_set_eos (GST_ELEMENT (src));
|
||||
return GST_DATA (gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
else if (retval == 0)
|
||||
{
|
||||
g_signal_emit (G_OBJECT (src), gst_fdsrc_signals[SIGNAL_TIMEOUT], 0);
|
||||
gst_element_set_eos (GST_ELEMENT (src));
|
||||
return GST_DATA(gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
readbytes = read (src->fd, GST_BUFFER_DATA (buf), src->blocksize);
|
||||
} while (readbytes == -1 && errno == EINTR); /* retry if interrupted */
|
||||
} while (readbytes == -1 && errno == EINTR); /* retry if interrupted */
|
||||
|
||||
if (readbytes > 0)
|
||||
{
|
||||
if (readbytes > 0) {
|
||||
GST_BUFFER_OFFSET (buf) = src->curoffset;
|
||||
GST_BUFFER_SIZE (buf) = readbytes;
|
||||
GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
|
||||
|
@ -230,15 +229,12 @@ gst_fdsrc_get(GstPad *pad)
|
|||
|
||||
/* we're done, return the buffer */
|
||||
return GST_DATA (buf);
|
||||
}
|
||||
else if (readbytes == 0)
|
||||
{
|
||||
} else if (readbytes == 0) {
|
||||
gst_element_set_eos (GST_ELEMENT (src));
|
||||
return GST_DATA (gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
else
|
||||
{
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("read on file descriptor: %s.", g_strerror(errno)));
|
||||
} else {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
|
||||
("read on file descriptor: %s.", g_strerror (errno)));
|
||||
gst_element_set_eos (GST_ELEMENT (src));
|
||||
return GST_DATA (gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GST_TYPE_FDSRC \
|
||||
(gst_fdsrc_get_type())
|
||||
#define GST_FDSRC(obj) \
|
||||
|
@ -39,12 +37,11 @@ G_BEGIN_DECLS
|
|||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FDSRC))
|
||||
#define GST_IS_FDSRC_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FDSRC))
|
||||
|
||||
|
||||
typedef struct _GstFdSrc GstFdSrc;
|
||||
typedef struct _GstFdSrcClass GstFdSrcClass;
|
||||
|
||||
struct _GstFdSrc {
|
||||
struct _GstFdSrc
|
||||
{
|
||||
GstElement element;
|
||||
/* pads */
|
||||
GstPad *srcpad;
|
||||
|
@ -52,22 +49,22 @@ struct _GstFdSrc {
|
|||
/* fd */
|
||||
gint fd;
|
||||
|
||||
gulong curoffset; /* current offset in file */
|
||||
gulong blocksize; /* bytes per read */
|
||||
guint64 timeout; /* read timeout, in nanoseconds */
|
||||
|
||||
gulong seq; /* buffer sequence number */
|
||||
gulong curoffset; /* current offset in file */
|
||||
gulong blocksize; /* bytes per read */
|
||||
guint64 timeout; /* read timeout, in nanoseconds */
|
||||
|
||||
gulong seq; /* buffer sequence number */
|
||||
};
|
||||
|
||||
struct _GstFdSrcClass {
|
||||
struct _GstFdSrcClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*timeout) (GstElement *element);
|
||||
void (*timeout) (GstElement * element);
|
||||
};
|
||||
|
||||
GType gst_fdsrc_get_type(void);
|
||||
GType gst_fdsrc_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_FDSRC_H__ */
|
||||
|
|
|
@ -39,28 +39,28 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_filesink_debug);
|
||||
#define GST_CAT_DEFAULT gst_filesink_debug
|
||||
|
||||
GstElementDetails gst_filesink_details = GST_ELEMENT_DETAILS (
|
||||
"File Sink",
|
||||
"Sink/File",
|
||||
"Write stream to a file",
|
||||
"Thomas <thomas@apestaart.org>"
|
||||
);
|
||||
GstElementDetails gst_filesink_details = GST_ELEMENT_DETAILS ("File Sink",
|
||||
"Sink/File",
|
||||
"Write stream to a file",
|
||||
"Thomas <thomas@apestaart.org>");
|
||||
|
||||
|
||||
/* FileSink signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
SIGNAL_HANDOFF,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_LOCATION
|
||||
};
|
||||
|
||||
static const GstFormat *
|
||||
gst_filesink_get_formats (GstPad *pad)
|
||||
gst_filesink_get_formats (GstPad * pad)
|
||||
{
|
||||
static const GstFormat formats[] = {
|
||||
GST_FORMAT_BYTES,
|
||||
|
@ -70,7 +70,7 @@ gst_filesink_get_formats (GstPad *pad)
|
|||
}
|
||||
|
||||
static const GstQueryType *
|
||||
gst_filesink_get_query_types (GstPad *pad)
|
||||
gst_filesink_get_query_types (GstPad * pad)
|
||||
{
|
||||
static const GstQueryType types[] = {
|
||||
GST_QUERY_TOTAL,
|
||||
|
@ -80,24 +80,25 @@ gst_filesink_get_query_types (GstPad *pad)
|
|||
return types;
|
||||
}
|
||||
|
||||
static void gst_filesink_dispose (GObject *object);
|
||||
static void gst_filesink_dispose (GObject * object);
|
||||
|
||||
static void gst_filesink_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_filesink_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
static void gst_filesink_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_filesink_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static gboolean gst_filesink_open_file (GstFileSink *sink);
|
||||
static void gst_filesink_close_file (GstFileSink *sink);
|
||||
static gboolean gst_filesink_open_file (GstFileSink * sink);
|
||||
static void gst_filesink_close_file (GstFileSink * sink);
|
||||
|
||||
static gboolean gst_filesink_handle_event (GstPad *pad, GstEvent *event);
|
||||
static gboolean gst_filesink_pad_query (GstPad *pad, GstQueryType type,
|
||||
GstFormat *format, gint64 *value);
|
||||
static void gst_filesink_chain (GstPad *pad,GstData *_data);
|
||||
static gboolean gst_filesink_handle_event (GstPad * pad, GstEvent * event);
|
||||
static gboolean gst_filesink_pad_query (GstPad * pad, GstQueryType type,
|
||||
GstFormat * format, gint64 * value);
|
||||
static void gst_filesink_chain (GstPad * pad, GstData * _data);
|
||||
|
||||
static void gst_filesink_uri_handler_init (gpointer g_iface, gpointer iface_data);
|
||||
|
||||
static GstElementStateReturn gst_filesink_change_state (GstElement *element);
|
||||
static void gst_filesink_uri_handler_init (gpointer g_iface,
|
||||
gpointer iface_data);
|
||||
|
||||
static GstElementStateReturn gst_filesink_change_state (GstElement * element);
|
||||
|
||||
static guint gst_filesink_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
@ -109,12 +110,15 @@ _do_init (GType filesink_type)
|
|||
NULL,
|
||||
NULL
|
||||
};
|
||||
g_type_add_interface_static (filesink_type, GST_TYPE_URI_HANDLER, &urihandler_info);
|
||||
GST_DEBUG_CATEGORY_INIT (gst_filesink_debug, "filesink", 0, "filesink element");
|
||||
g_type_add_interface_static (filesink_type, GST_TYPE_URI_HANDLER,
|
||||
&urihandler_info);
|
||||
GST_DEBUG_CATEGORY_INIT (gst_filesink_debug, "filesink", 0,
|
||||
"filesink element");
|
||||
}
|
||||
|
||||
GST_BOILERPLATE_FULL (GstFileSink, gst_filesink, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
|
||||
GST_BOILERPLATE_FULL (GstFileSink, gst_filesink, GstElement, GST_TYPE_ELEMENT,
|
||||
_do_init);
|
||||
|
||||
|
||||
static void
|
||||
gst_filesink_base_init (gpointer g_class)
|
||||
|
@ -125,26 +129,26 @@ gst_filesink_base_init (gpointer g_class)
|
|||
gst_element_class_set_details (gstelement_class, &gst_filesink_details);
|
||||
}
|
||||
static void
|
||||
gst_filesink_class_init (GstFileSinkClass *klass)
|
||||
gst_filesink_class_init (GstFileSinkClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATION,
|
||||
g_param_spec_string ("location", "File Location", "Location of the file to write",
|
||||
NULL, G_PARAM_READWRITE));
|
||||
g_param_spec_string ("location", "File Location",
|
||||
"Location of the file to write", NULL, G_PARAM_READWRITE));
|
||||
|
||||
gst_filesink_signals[SIGNAL_HANDOFF] =
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstFileSinkClass, handoff), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstFileSinkClass, handoff), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
|
||||
gobject_class->set_property = gst_filesink_set_property;
|
||||
gobject_class->get_property = gst_filesink_get_property;
|
||||
gobject_class->dispose = gst_filesink_dispose;
|
||||
gobject_class->dispose = gst_filesink_dispose;
|
||||
}
|
||||
static void
|
||||
gst_filesink_init (GstFileSink *filesink)
|
||||
static void
|
||||
gst_filesink_init (GstFileSink * filesink)
|
||||
{
|
||||
GstPad *pad;
|
||||
|
||||
|
@ -152,7 +156,7 @@ gst_filesink_init (GstFileSink *filesink)
|
|||
gst_element_add_pad (GST_ELEMENT (filesink), pad);
|
||||
gst_pad_set_chain_function (pad, gst_filesink_chain);
|
||||
|
||||
GST_FLAG_SET (GST_ELEMENT(filesink), GST_ELEMENT_EVENT_AWARE);
|
||||
GST_FLAG_SET (GST_ELEMENT (filesink), GST_ELEMENT_EVENT_AWARE);
|
||||
|
||||
gst_pad_set_query_function (pad, gst_filesink_pad_query);
|
||||
gst_pad_set_query_type_function (pad, gst_filesink_get_query_types);
|
||||
|
@ -162,19 +166,20 @@ gst_filesink_init (GstFileSink *filesink)
|
|||
filesink->file = NULL;
|
||||
}
|
||||
static void
|
||||
gst_filesink_dispose (GObject *object)
|
||||
gst_filesink_dispose (GObject * object)
|
||||
{
|
||||
GstFileSink *sink = GST_FILESINK (object);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
|
||||
|
||||
g_free (sink->uri);
|
||||
sink->uri = NULL;
|
||||
g_free (sink->filename);
|
||||
sink->filename = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_filesink_set_location (GstFileSink *sink, const gchar *location)
|
||||
gst_filesink_set_location (GstFileSink * sink, const gchar * location)
|
||||
{
|
||||
/* the element must be stopped or paused in order to do this */
|
||||
if (GST_STATE (sink) > GST_STATE_PAUSED)
|
||||
|
@ -192,14 +197,15 @@ gst_filesink_set_location (GstFileSink *sink, const gchar *location)
|
|||
sink->filename = NULL;
|
||||
sink->uri = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (GST_STATE (sink) == GST_STATE_PAUSED)
|
||||
gst_filesink_open_file (sink);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
static void
|
||||
gst_filesink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
gst_filesink_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstFileSink *sink;
|
||||
|
||||
|
@ -216,16 +222,17 @@ gst_filesink_set_property (GObject *object, guint prop_id, const GValue *value,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_filesink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_filesink_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstFileSink *sink;
|
||||
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_FILESINK (object));
|
||||
|
||||
|
||||
sink = GST_FILESINK (object);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_LOCATION:
|
||||
g_value_set_string (value, sink->filename);
|
||||
|
@ -237,23 +244,22 @@ gst_filesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_filesink_open_file (GstFileSink *sink)
|
||||
gst_filesink_open_file (GstFileSink * sink)
|
||||
{
|
||||
g_return_val_if_fail (!GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN), FALSE);
|
||||
|
||||
/* open the file */
|
||||
if (sink->filename == NULL || sink->filename[0] == '\0')
|
||||
{
|
||||
if (sink->filename == NULL || sink->filename[0] == '\0') {
|
||||
GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND,
|
||||
(_("No file name specified for writing.")), (NULL));
|
||||
(_("No file name specified for writing.")), (NULL));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sink->file = fopen (sink->filename, "w");
|
||||
if (sink->file == NULL) {
|
||||
GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE,
|
||||
(_("Could not open file \"%s\" for writing."), sink->filename),
|
||||
GST_ERROR_SYSTEM);
|
||||
(_("Could not open file \"%s\" for writing."), sink->filename),
|
||||
GST_ERROR_SYSTEM);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -265,24 +271,21 @@ gst_filesink_open_file (GstFileSink *sink)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_filesink_close_file (GstFileSink *sink)
|
||||
gst_filesink_close_file (GstFileSink * sink)
|
||||
{
|
||||
g_return_if_fail (GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN));
|
||||
|
||||
if (fclose (sink->file) != 0)
|
||||
{
|
||||
if (fclose (sink->file) != 0) {
|
||||
GST_ELEMENT_ERROR (sink, RESOURCE, CLOSE,
|
||||
(_("Error closing file \"%s\"."), sink->filename),
|
||||
GST_ERROR_SYSTEM);
|
||||
}
|
||||
else {
|
||||
(_("Error closing file \"%s\"."), sink->filename), GST_ERROR_SYSTEM);
|
||||
} else {
|
||||
GST_FLAG_UNSET (sink, GST_FILESINK_OPEN);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_filesink_pad_query (GstPad *pad, GstQueryType type,
|
||||
GstFormat *format, gint64 *value)
|
||||
gst_filesink_pad_query (GstPad * pad, GstQueryType type,
|
||||
GstFormat * format, gint64 * value)
|
||||
{
|
||||
GstFileSink *sink = GST_FILESINK (GST_PAD_PARENT (pad));
|
||||
|
||||
|
@ -290,23 +293,23 @@ gst_filesink_pad_query (GstPad *pad, GstQueryType type,
|
|||
case GST_QUERY_TOTAL:
|
||||
switch (*format) {
|
||||
case GST_FORMAT_BYTES:
|
||||
if (GST_FLAG_IS_SET (GST_ELEMENT(sink), GST_FILESINK_OPEN)) {
|
||||
*value = sink->data_written; /* FIXME - doesn't the kernel provide
|
||||
such a function? */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (GST_FLAG_IS_SET (GST_ELEMENT (sink), GST_FILESINK_OPEN)) {
|
||||
*value = sink->data_written; /* FIXME - doesn't the kernel provide
|
||||
such a function? */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case GST_QUERY_POSITION:
|
||||
switch (*format) {
|
||||
case GST_FORMAT_BYTES:
|
||||
if (GST_FLAG_IS_SET (GST_ELEMENT(sink), GST_FILESINK_OPEN)) {
|
||||
*value = ftell (sink->file);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (GST_FLAG_IS_SET (GST_ELEMENT (sink), GST_FILESINK_OPEN)) {
|
||||
*value = ftell (sink->file);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
@ -319,60 +322,58 @@ gst_filesink_pad_query (GstPad *pad, GstQueryType type,
|
|||
|
||||
/* handle events (search) */
|
||||
static gboolean
|
||||
gst_filesink_handle_event (GstPad *pad, GstEvent *event)
|
||||
gst_filesink_handle_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstEventType type;
|
||||
GstFileSink *filesink;
|
||||
|
||||
filesink = GST_FILESINK (gst_pad_get_parent (pad));
|
||||
|
||||
g_return_val_if_fail (GST_FLAG_IS_SET (filesink, GST_FILESINK_OPEN),
|
||||
FALSE);
|
||||
g_return_val_if_fail (GST_FLAG_IS_SET (filesink, GST_FILESINK_OPEN), FALSE);
|
||||
|
||||
type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
|
||||
|
||||
switch (type) {
|
||||
case GST_EVENT_SEEK:
|
||||
g_return_val_if_fail (GST_EVENT_SEEK_FORMAT (event) == GST_FORMAT_BYTES,
|
||||
FALSE);
|
||||
FALSE);
|
||||
|
||||
if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH)
|
||||
if (fflush (filesink->file))
|
||||
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
|
||||
(_("Error while writing to file \"%s\"."), filesink->filename),
|
||||
GST_ERROR_SYSTEM);
|
||||
if (fflush (filesink->file))
|
||||
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
|
||||
(_("Error while writing to file \"%s\"."), filesink->filename),
|
||||
GST_ERROR_SYSTEM);
|
||||
|
||||
switch (GST_EVENT_SEEK_METHOD(event))
|
||||
{
|
||||
case GST_SEEK_METHOD_SET:
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_SET);
|
||||
break;
|
||||
case GST_SEEK_METHOD_CUR:
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_CUR);
|
||||
break;
|
||||
case GST_SEEK_METHOD_END:
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_END);
|
||||
break;
|
||||
default:
|
||||
g_warning ("unknown seek method!");
|
||||
break;
|
||||
switch (GST_EVENT_SEEK_METHOD (event)) {
|
||||
case GST_SEEK_METHOD_SET:
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_SET);
|
||||
break;
|
||||
case GST_SEEK_METHOD_CUR:
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_CUR);
|
||||
break;
|
||||
case GST_SEEK_METHOD_END:
|
||||
fseek (filesink->file, GST_EVENT_SEEK_OFFSET (event), SEEK_END);
|
||||
break;
|
||||
default:
|
||||
g_warning ("unknown seek method!");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
{
|
||||
gint64 offset;
|
||||
|
||||
|
||||
if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &offset))
|
||||
fseek (filesink->file, offset, SEEK_SET);
|
||||
fseek (filesink->file, offset, SEEK_SET);
|
||||
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_FLUSH:
|
||||
if (fflush (filesink->file)) {
|
||||
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
|
||||
(_("Error while writing to file \"%s\"."), filesink->filename),
|
||||
GST_ERROR_SYSTEM);
|
||||
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
|
||||
(_("Error while writing to file \"%s\"."), filesink->filename),
|
||||
GST_ERROR_SYSTEM);
|
||||
}
|
||||
break;
|
||||
case GST_EVENT_EOS:
|
||||
|
@ -394,8 +395,8 @@ gst_filesink_handle_event (GstPad *pad, GstEvent *event)
|
|||
*
|
||||
* take the buffer from the pad and write to file if it's open
|
||||
*/
|
||||
static void
|
||||
gst_filesink_chain (GstPad *pad, GstData *_data)
|
||||
static void
|
||||
gst_filesink_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
GstBuffer *buf = GST_BUFFER (_data);
|
||||
GstFileSink *filesink;
|
||||
|
@ -406,27 +407,26 @@ gst_filesink_chain (GstPad *pad, GstData *_data)
|
|||
|
||||
filesink = GST_FILESINK (gst_pad_get_parent (pad));
|
||||
|
||||
if (GST_IS_EVENT(buf))
|
||||
{
|
||||
gst_filesink_handle_event(pad, GST_EVENT(buf));
|
||||
if (GST_IS_EVENT (buf)) {
|
||||
gst_filesink_handle_event (pad, GST_EVENT (buf));
|
||||
return;
|
||||
}
|
||||
|
||||
if (GST_FLAG_IS_SET (filesink, GST_FILESINK_OPEN))
|
||||
{
|
||||
if (GST_FLAG_IS_SET (filesink, GST_FILESINK_OPEN)) {
|
||||
guint bytes_written = 0, back_pending = 0;
|
||||
if (ftell(filesink->file) < filesink->data_written)
|
||||
back_pending = filesink->data_written - ftell(filesink->file);
|
||||
|
||||
if (ftell (filesink->file) < filesink->data_written)
|
||||
back_pending = filesink->data_written - ftell (filesink->file);
|
||||
while (bytes_written < GST_BUFFER_SIZE (buf)) {
|
||||
size_t wrote = fwrite (GST_BUFFER_DATA (buf) + bytes_written, 1,
|
||||
GST_BUFFER_SIZE (buf) - bytes_written,
|
||||
filesink->file);
|
||||
GST_BUFFER_SIZE (buf) - bytes_written,
|
||||
filesink->file);
|
||||
|
||||
if (wrote <= 0) {
|
||||
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
|
||||
(_("Error while writing to file \"%s\"."), filesink->filename),
|
||||
("Only %d of %d bytes written: %s",
|
||||
bytes_written, GST_BUFFER_SIZE (buf),
|
||||
strerror (errno)));
|
||||
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
|
||||
(_("Error while writing to file \"%s\"."), filesink->filename),
|
||||
("Only %d of %d bytes written: %s",
|
||||
bytes_written, GST_BUFFER_SIZE (buf), strerror (errno)));
|
||||
break;
|
||||
}
|
||||
bytes_written += wrote;
|
||||
|
@ -438,25 +438,24 @@ gst_filesink_chain (GstPad *pad, GstData *_data)
|
|||
gst_buffer_unref (buf);
|
||||
|
||||
g_signal_emit (G_OBJECT (filesink),
|
||||
gst_filesink_signals[SIGNAL_HANDOFF], 0,
|
||||
filesink);
|
||||
gst_filesink_signals[SIGNAL_HANDOFF], 0, filesink);
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_filesink_change_state (GstElement *element)
|
||||
gst_filesink_change_state (GstElement * element)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_FILESINK (element), GST_STATE_FAILURE);
|
||||
|
||||
switch (GST_STATE_TRANSITION (element)) {
|
||||
case GST_STATE_PAUSED_TO_READY:
|
||||
if (GST_FLAG_IS_SET (element, GST_FILESINK_OPEN))
|
||||
gst_filesink_close_file (GST_FILESINK (element));
|
||||
gst_filesink_close_file (GST_FILESINK (element));
|
||||
break;
|
||||
|
||||
case GST_STATE_READY_TO_PAUSED:
|
||||
if (!GST_FLAG_IS_SET (element, GST_FILESINK_OPEN)) {
|
||||
if (!gst_filesink_open_file (GST_FILESINK (element)))
|
||||
return GST_STATE_FAILURE;
|
||||
if (!gst_filesink_open_file (GST_FILESINK (element)))
|
||||
return GST_STATE_FAILURE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -475,20 +474,21 @@ gst_filesink_uri_get_type (void)
|
|||
return GST_URI_SINK;
|
||||
}
|
||||
static gchar **
|
||||
gst_filesink_uri_get_protocols(void)
|
||||
gst_filesink_uri_get_protocols (void)
|
||||
{
|
||||
static gchar *protocols[] = {"file", NULL};
|
||||
static gchar *protocols[] = { "file", NULL };
|
||||
return protocols;
|
||||
}
|
||||
static const gchar *
|
||||
gst_filesink_uri_get_uri (GstURIHandler *handler)
|
||||
gst_filesink_uri_get_uri (GstURIHandler * handler)
|
||||
{
|
||||
GstFileSink *sink = GST_FILESINK (handler);
|
||||
|
||||
|
||||
return sink->uri;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_filesink_uri_set_uri (GstURIHandler *handler, const gchar *uri)
|
||||
gst_filesink_uri_set_uri (GstURIHandler * handler, const gchar * uri)
|
||||
{
|
||||
gchar *protocol, *location;
|
||||
gboolean ret;
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GST_TYPE_FILESINK \
|
||||
(gst_filesink_get_type())
|
||||
#define GST_FILESINK(obj) \
|
||||
|
@ -39,17 +37,18 @@ G_BEGIN_DECLS
|
|||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FILESINK))
|
||||
#define GST_IS_FILESINK_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FILESINK))
|
||||
|
||||
typedef struct _GstFileSink GstFileSink;
|
||||
typedef struct _GstFileSinkClass GstFileSinkClass;
|
||||
|
||||
typedef enum {
|
||||
GST_FILESINK_OPEN = GST_ELEMENT_FLAG_LAST,
|
||||
typedef enum
|
||||
{
|
||||
GST_FILESINK_OPEN = GST_ELEMENT_FLAG_LAST,
|
||||
|
||||
GST_FILESINK_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2
|
||||
GST_FILESINK_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2
|
||||
} GstFileSinkFlags;
|
||||
|
||||
struct _GstFileSink {
|
||||
struct _GstFileSink
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
gchar *filename;
|
||||
|
@ -59,15 +58,15 @@ struct _GstFileSink {
|
|||
guint64 data_written;
|
||||
};
|
||||
|
||||
struct _GstFileSinkClass {
|
||||
struct _GstFileSinkClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*handoff) (GstElement *element, GstPad *pad);
|
||||
void (*handoff) (GstElement * element, GstPad * pad);
|
||||
};
|
||||
|
||||
GType gst_filesink_get_type(void);
|
||||
GType gst_filesink_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_FILESINK_H__ */
|
||||
|
|
|
@ -77,23 +77,23 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_filesrc_debug);
|
||||
#define GST_CAT_DEFAULT gst_filesrc_debug
|
||||
|
||||
GstElementDetails gst_filesrc_details = GST_ELEMENT_DETAILS (
|
||||
"File Source",
|
||||
"Source/File",
|
||||
"Read from arbitrary point in a file",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>"
|
||||
);
|
||||
GstElementDetails gst_filesrc_details = GST_ELEMENT_DETAILS ("File Source",
|
||||
"Source/File",
|
||||
"Read from arbitrary point in a file",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>");
|
||||
|
||||
#define DEFAULT_BLOCKSIZE 4*1024
|
||||
#define DEFAULT_MMAPSIZE 4*1024*1024
|
||||
|
||||
/* FileSrc signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_LOCATION,
|
||||
ARG_FD,
|
||||
|
@ -103,22 +103,20 @@ enum {
|
|||
};
|
||||
|
||||
static const GstEventMask *
|
||||
gst_filesrc_get_event_mask (GstPad *pad)
|
||||
gst_filesrc_get_event_mask (GstPad * pad)
|
||||
{
|
||||
static const GstEventMask masks[] = {
|
||||
{ GST_EVENT_SEEK, GST_SEEK_METHOD_CUR |
|
||||
GST_SEEK_METHOD_SET |
|
||||
GST_SEEK_METHOD_END |
|
||||
GST_SEEK_FLAG_FLUSH },
|
||||
{ GST_EVENT_FLUSH, 0 },
|
||||
{ GST_EVENT_SIZE, 0 },
|
||||
{ 0, 0 }
|
||||
{GST_EVENT_SEEK, GST_SEEK_METHOD_CUR |
|
||||
GST_SEEK_METHOD_SET | GST_SEEK_METHOD_END | GST_SEEK_FLAG_FLUSH},
|
||||
{GST_EVENT_FLUSH, 0},
|
||||
{GST_EVENT_SIZE, 0},
|
||||
{0, 0}
|
||||
};
|
||||
return masks;
|
||||
}
|
||||
|
||||
static const GstQueryType *
|
||||
gst_filesrc_get_query_types (GstPad *pad)
|
||||
gst_filesrc_get_query_types (GstPad * pad)
|
||||
{
|
||||
static const GstQueryType types[] = {
|
||||
GST_QUERY_TOTAL,
|
||||
|
@ -129,7 +127,7 @@ gst_filesrc_get_query_types (GstPad *pad)
|
|||
}
|
||||
|
||||
static const GstFormat *
|
||||
gst_filesrc_get_formats (GstPad *pad)
|
||||
gst_filesrc_get_formats (GstPad * pad)
|
||||
{
|
||||
static const GstFormat formats[] = {
|
||||
GST_FORMAT_BYTES,
|
||||
|
@ -138,22 +136,23 @@ gst_filesrc_get_formats (GstPad *pad)
|
|||
return formats;
|
||||
}
|
||||
|
||||
static void gst_filesrc_dispose (GObject *object);
|
||||
static void gst_filesrc_dispose (GObject * object);
|
||||
|
||||
static void gst_filesrc_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_filesrc_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
static void gst_filesrc_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_filesrc_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static gboolean gst_filesrc_check_filesize (GstFileSrc *src);
|
||||
static GstData * gst_filesrc_get (GstPad *pad);
|
||||
static gboolean gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event);
|
||||
static gboolean gst_filesrc_srcpad_query (GstPad *pad, GstQueryType type,
|
||||
GstFormat *format, gint64 *value);
|
||||
static gboolean gst_filesrc_check_filesize (GstFileSrc * src);
|
||||
static GstData *gst_filesrc_get (GstPad * pad);
|
||||
static gboolean gst_filesrc_srcpad_event (GstPad * pad, GstEvent * event);
|
||||
static gboolean gst_filesrc_srcpad_query (GstPad * pad, GstQueryType type,
|
||||
GstFormat * format, gint64 * value);
|
||||
|
||||
static GstElementStateReturn gst_filesrc_change_state (GstElement *element);
|
||||
static GstElementStateReturn gst_filesrc_change_state (GstElement * element);
|
||||
|
||||
static void gst_filesrc_uri_handler_init (gpointer g_iface, gpointer iface_data);
|
||||
static void gst_filesrc_uri_handler_init (gpointer g_iface,
|
||||
gpointer iface_data);
|
||||
|
||||
static void
|
||||
_do_init (GType filesrc_type)
|
||||
|
@ -163,12 +162,14 @@ _do_init (GType filesrc_type)
|
|||
NULL,
|
||||
NULL
|
||||
};
|
||||
g_type_add_interface_static (filesrc_type, GST_TYPE_URI_HANDLER, &urihandler_info);
|
||||
g_type_add_interface_static (filesrc_type, GST_TYPE_URI_HANDLER,
|
||||
&urihandler_info);
|
||||
GST_DEBUG_CATEGORY_INIT (gst_filesrc_debug, "filesrc", 0, "filesrc element");
|
||||
}
|
||||
|
||||
GST_BOILERPLATE_FULL (GstFileSrc, gst_filesrc, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
|
||||
GST_BOILERPLATE_FULL (GstFileSrc, gst_filesrc, GstElement, GST_TYPE_ELEMENT,
|
||||
_do_init);
|
||||
|
||||
static void
|
||||
gst_filesrc_base_init (gpointer g_class)
|
||||
{
|
||||
|
@ -177,41 +178,42 @@ gst_filesrc_base_init (gpointer g_class)
|
|||
gst_element_class_set_details (gstelement_class, &gst_filesrc_details);
|
||||
}
|
||||
static void
|
||||
gst_filesrc_class_init (GstFileSrcClass *klass)
|
||||
gst_filesrc_class_init (GstFileSrcClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
gobject_class = (GObjectClass*)klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FD,
|
||||
g_param_spec_int ("fd", "File-descriptor", "File-descriptor for the file being mmap()d",
|
||||
0, G_MAXINT, 0, G_PARAM_READABLE));
|
||||
g_param_spec_int ("fd", "File-descriptor",
|
||||
"File-descriptor for the file being mmap()d", 0, G_MAXINT, 0,
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATION,
|
||||
g_param_spec_string ("location", "File Location", "Location of the file to read",
|
||||
NULL, G_PARAM_READWRITE));
|
||||
g_param_spec_string ("location", "File Location",
|
||||
"Location of the file to read", NULL, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BLOCKSIZE,
|
||||
g_param_spec_ulong ("blocksize", "Block size", "Size in bytes to read per buffer",
|
||||
1, G_MAXULONG, DEFAULT_BLOCKSIZE, G_PARAM_READWRITE));
|
||||
g_param_spec_ulong ("blocksize", "Block size",
|
||||
"Size in bytes to read per buffer", 1, G_MAXULONG, DEFAULT_BLOCKSIZE,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MMAPSIZE,
|
||||
g_param_spec_ulong ("mmapsize", "mmap() Block Size",
|
||||
"Size in bytes of mmap()d regions",
|
||||
0, G_MAXULONG, DEFAULT_MMAPSIZE, G_PARAM_READWRITE));
|
||||
g_param_spec_ulong ("mmapsize", "mmap() Block Size",
|
||||
"Size in bytes of mmap()d regions", 0, G_MAXULONG, DEFAULT_MMAPSIZE,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TOUCH,
|
||||
g_param_spec_boolean ("touch", "Touch read data",
|
||||
"Touch data to force disk read",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("touch", "Touch read data",
|
||||
"Touch data to force disk read", FALSE, G_PARAM_READWRITE));
|
||||
|
||||
gobject_class->dispose = gst_filesrc_dispose;
|
||||
gobject_class->set_property = gst_filesrc_set_property;
|
||||
gobject_class->get_property = gst_filesrc_get_property;
|
||||
gobject_class->dispose = gst_filesrc_dispose;
|
||||
gobject_class->set_property = gst_filesrc_set_property;
|
||||
gobject_class->get_property = gst_filesrc_get_property;
|
||||
|
||||
gstelement_class->change_state = gst_filesrc_change_state;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_filesrc_init (GstFileSrc *src)
|
||||
gst_filesrc_init (GstFileSrc * src)
|
||||
{
|
||||
src->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_pad_set_get_function (src->srcpad, gst_filesrc_get);
|
||||
|
@ -222,7 +224,7 @@ gst_filesrc_init (GstFileSrc *src)
|
|||
gst_pad_set_formats_function (src->srcpad, gst_filesrc_get_formats);
|
||||
gst_element_add_pad (GST_ELEMENT (src), src->srcpad);
|
||||
|
||||
src->pagesize = getpagesize();
|
||||
src->pagesize = getpagesize ();
|
||||
|
||||
src->filename = NULL;
|
||||
src->fd = 0;
|
||||
|
@ -233,13 +235,13 @@ gst_filesrc_init (GstFileSrc *src)
|
|||
src->touch = FALSE;
|
||||
|
||||
src->mapbuf = NULL;
|
||||
src->mapsize = DEFAULT_MMAPSIZE; /* default is 4MB */
|
||||
src->mapsize = DEFAULT_MMAPSIZE; /* default is 4MB */
|
||||
|
||||
src->seek_happened = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_filesrc_dispose (GObject *object)
|
||||
gst_filesrc_dispose (GObject * object)
|
||||
{
|
||||
GstFileSrc *src;
|
||||
|
||||
|
@ -254,15 +256,16 @@ gst_filesrc_dispose (GObject *object)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_filesrc_set_location (GstFileSrc *src, const gchar *location)
|
||||
gst_filesrc_set_location (GstFileSrc * src, const gchar * location)
|
||||
{
|
||||
/* the element must be stopped in order to do this */
|
||||
if (GST_STATE (src) != GST_STATE_READY &&
|
||||
GST_STATE (src) != GST_STATE_NULL)
|
||||
if (GST_STATE (src) != GST_STATE_READY && GST_STATE (src) != GST_STATE_NULL)
|
||||
return FALSE;
|
||||
|
||||
if (src->filename) g_free (src->filename);
|
||||
if (src->uri) g_free (src->uri);
|
||||
if (src->filename)
|
||||
g_free (src->filename);
|
||||
if (src->uri)
|
||||
g_free (src->uri);
|
||||
/* clear the filename if we get a NULL (is that possible?) */
|
||||
if (location == NULL) {
|
||||
src->filename = NULL;
|
||||
|
@ -278,7 +281,8 @@ gst_filesrc_set_location (GstFileSrc *src, const gchar *location)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_filesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
gst_filesrc_set_property (GObject * object, guint prop_id, const GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstFileSrc *src;
|
||||
|
||||
|
@ -297,11 +301,12 @@ gst_filesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
|
|||
break;
|
||||
case ARG_MMAPSIZE:
|
||||
if ((src->mapsize % src->pagesize) == 0) {
|
||||
src->mapsize = g_value_get_ulong (value);
|
||||
g_object_notify (G_OBJECT (src), "mmapsize");
|
||||
src->mapsize = g_value_get_ulong (value);
|
||||
g_object_notify (G_OBJECT (src), "mmapsize");
|
||||
} else {
|
||||
GST_INFO_OBJECT (src, "invalid mapsize, must be a multiple of pagesize, which is %d",
|
||||
src->pagesize);
|
||||
GST_INFO_OBJECT (src,
|
||||
"invalid mapsize, must be a multiple of pagesize, which is %d",
|
||||
src->pagesize);
|
||||
}
|
||||
break;
|
||||
case ARG_TOUCH:
|
||||
|
@ -314,7 +319,8 @@ gst_filesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
|
|||
}
|
||||
|
||||
static void
|
||||
gst_filesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
gst_filesrc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstFileSrc *src;
|
||||
|
||||
|
@ -346,9 +352,9 @@ gst_filesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
|
|||
}
|
||||
|
||||
static void
|
||||
gst_filesrc_free_parent_mmap (GstBuffer *buf)
|
||||
gst_filesrc_free_parent_mmap (GstBuffer * buf)
|
||||
{
|
||||
GST_LOG ("freeing mmap()d buffer at %"G_GUINT64_FORMAT"+%u",
|
||||
GST_LOG ("freeing mmap()d buffer at %" G_GUINT64_FORMAT "+%u",
|
||||
GST_BUFFER_OFFSET (buf), GST_BUFFER_SIZE (buf));
|
||||
|
||||
#ifdef MADV_DONTNEED
|
||||
|
@ -359,16 +365,15 @@ gst_filesrc_free_parent_mmap (GstBuffer *buf)
|
|||
munmap (GST_BUFFER_DATA (buf), GST_BUFFER_MAXSIZE (buf));
|
||||
/* cast to unsigned long, since there's no gportable way to print
|
||||
* guint64 as hex */
|
||||
GST_LOG ("unmapped region %08lx+%08lx at %p",
|
||||
GST_LOG ("unmapped region %08lx+%08lx at %p",
|
||||
(unsigned long) GST_BUFFER_OFFSET (buf),
|
||||
(unsigned long) GST_BUFFER_MAXSIZE (buf),
|
||||
GST_BUFFER_DATA (buf));
|
||||
(unsigned long) GST_BUFFER_MAXSIZE (buf), GST_BUFFER_DATA (buf));
|
||||
|
||||
GST_BUFFER_DATA (buf) = NULL;
|
||||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_filesrc_map_region (GstFileSrc *src, off_t offset, size_t size)
|
||||
gst_filesrc_map_region (GstFileSrc * src, off_t offset, size_t size)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
gint retval;
|
||||
|
@ -376,20 +381,20 @@ gst_filesrc_map_region (GstFileSrc *src, off_t offset, size_t size)
|
|||
|
||||
g_return_val_if_fail (offset >= 0, NULL);
|
||||
|
||||
GST_LOG_OBJECT (src, "mapping region %08llx+%08lx from file into memory",offset,(unsigned long)size);
|
||||
GST_LOG_OBJECT (src, "mapping region %08llx+%08lx from file into memory",
|
||||
offset, (unsigned long) size);
|
||||
mmapregion = mmap (NULL, size, PROT_READ, MAP_SHARED, src->fd, offset);
|
||||
|
||||
if (mmapregion == NULL) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, TOO_LAZY, (NULL), ("mmap call failed."));
|
||||
return NULL;
|
||||
}
|
||||
else if (mmapregion == MAP_FAILED) {
|
||||
} else if (mmapregion == MAP_FAILED) {
|
||||
GST_WARNING_OBJECT (src, "mmap (0x%08lx, %d, 0x%llx) failed: %s",
|
||||
(unsigned long)size, src->fd, offset, strerror (errno));
|
||||
(unsigned long) size, src->fd, offset, strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
GST_LOG_OBJECT (src, "mapped region %08lx+%08lx from file into memory at %p",
|
||||
(unsigned long)offset, (unsigned long)size, mmapregion);
|
||||
GST_LOG_OBJECT (src, "mapped region %08lx+%08lx from file into memory at %p",
|
||||
(unsigned long) offset, (unsigned long) size, mmapregion);
|
||||
|
||||
/* time to allocate a new mapbuf */
|
||||
buf = gst_buffer_new ();
|
||||
|
@ -398,7 +403,8 @@ gst_filesrc_map_region (GstFileSrc *src, off_t offset, size_t size)
|
|||
|
||||
#ifdef MADV_SEQUENTIAL
|
||||
/* madvise to tell the kernel what to do with it */
|
||||
retval = madvise (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), MADV_SEQUENTIAL);
|
||||
retval =
|
||||
madvise (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), MADV_SEQUENTIAL);
|
||||
#endif
|
||||
/* fill in the rest of the fields */
|
||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_READONLY);
|
||||
|
@ -415,7 +421,7 @@ gst_filesrc_map_region (GstFileSrc *src, off_t offset, size_t size)
|
|||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_filesrc_map_small_region (GstFileSrc *src, off_t offset, size_t size)
|
||||
gst_filesrc_map_small_region (GstFileSrc * src, off_t offset, size_t size)
|
||||
{
|
||||
size_t mapsize;
|
||||
off_t mod, mapbase;
|
||||
|
@ -428,9 +434,10 @@ gst_filesrc_map_small_region (GstFileSrc *src, off_t offset, size_t size)
|
|||
GstBuffer *ret;
|
||||
|
||||
mapbase = offset - mod;
|
||||
mapsize = ((size + mod + src->pagesize - 1) / src->pagesize) * src->pagesize;
|
||||
mapsize =
|
||||
((size + mod + src->pagesize - 1) / src->pagesize) * src->pagesize;
|
||||
/* printf("not on page boundaries, resizing map to %d+%d\n",mapbase,mapsize);*/
|
||||
map = gst_filesrc_map_region(src, mapbase, mapsize);
|
||||
map = gst_filesrc_map_region (src, mapbase, mapsize);
|
||||
if (map == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -442,7 +449,7 @@ gst_filesrc_map_small_region (GstFileSrc *src, off_t offset, size_t size)
|
|||
return ret;
|
||||
}
|
||||
|
||||
return gst_filesrc_map_region(src,offset,size);
|
||||
return gst_filesrc_map_region (src, offset, size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -452,19 +459,19 @@ gst_filesrc_map_small_region (GstFileSrc *src, off_t offset, size_t size)
|
|||
* Push a new buffer from the filesrc at the current offset.
|
||||
*/
|
||||
static GstBuffer *
|
||||
gst_filesrc_get_mmap (GstFileSrc *src)
|
||||
gst_filesrc_get_mmap (GstFileSrc * src)
|
||||
{
|
||||
GstBuffer *buf = NULL;
|
||||
size_t readsize, mapsize;
|
||||
off_t readend,mapstart,mapend;
|
||||
off_t readend, mapstart, mapend;
|
||||
int i;
|
||||
|
||||
/* calculate end pointers so we don't have to do so repeatedly later */
|
||||
readsize = src->block_size;
|
||||
readend = src->curoffset + src->block_size; /* note this is the byte *after* the read */
|
||||
readend = src->curoffset + src->block_size; /* note this is the byte *after* the read */
|
||||
mapstart = GST_BUFFER_OFFSET (src->mapbuf);
|
||||
mapsize = GST_BUFFER_SIZE (src->mapbuf);
|
||||
mapend = mapstart + mapsize; /* note this is the byte *after* the map */
|
||||
mapend = mapstart + mapsize; /* note this is the byte *after* the map */
|
||||
|
||||
/* check to see if we're going to overflow the end of the file */
|
||||
if (readend > src->filelen) {
|
||||
|
@ -474,40 +481,46 @@ gst_filesrc_get_mmap (GstFileSrc *src)
|
|||
}
|
||||
}
|
||||
|
||||
GST_LOG ("attempting to read %08lx, %08lx, %08lx, %08lx",
|
||||
(unsigned long)readsize, (unsigned long)readend,
|
||||
(unsigned long)mapstart, (unsigned long)mapend);
|
||||
GST_LOG ("attempting to read %08lx, %08lx, %08lx, %08lx",
|
||||
(unsigned long) readsize, (unsigned long) readend,
|
||||
(unsigned long) mapstart, (unsigned long) mapend);
|
||||
|
||||
/* if the start is past the mapstart */
|
||||
if (src->curoffset >= mapstart) {
|
||||
/* if the end is before the mapend, the buffer is in current mmap region... */
|
||||
/* ('cause by definition if readend is in the buffer, so's readstart) */
|
||||
if (readend <= mapend) {
|
||||
GST_LOG_OBJECT (src, "read buf %llu+%d lives in current mapbuf %lld+%d, creating subbuffer of mapbuf",
|
||||
src->curoffset, (int)readsize, mapstart, mapsize);
|
||||
buf = gst_buffer_create_sub (src->mapbuf, src->curoffset - mapstart,
|
||||
readsize);
|
||||
GST_LOG_OBJECT (src,
|
||||
"read buf %llu+%d lives in current mapbuf %lld+%d, creating subbuffer of mapbuf",
|
||||
src->curoffset, (int) readsize, mapstart, mapsize);
|
||||
buf =
|
||||
gst_buffer_create_sub (src->mapbuf, src->curoffset - mapstart,
|
||||
readsize);
|
||||
GST_BUFFER_OFFSET (buf) = src->curoffset;
|
||||
|
||||
/* if the start actually is within the current mmap region, map an overlap buffer */
|
||||
/* if the start actually is within the current mmap region, map an overlap buffer */
|
||||
} else if (src->curoffset < mapend) {
|
||||
GST_LOG_OBJECT (src, "read buf %llu+%d starts in mapbuf %d+%d but ends outside, creating new mmap",
|
||||
(unsigned long long) src->curoffset, (gint) readsize, (gint) mapstart, (gint) mapsize);
|
||||
GST_LOG_OBJECT (src,
|
||||
"read buf %llu+%d starts in mapbuf %d+%d but ends outside, creating new mmap",
|
||||
(unsigned long long) src->curoffset, (gint) readsize, (gint) mapstart,
|
||||
(gint) mapsize);
|
||||
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* the only other option is that buffer is totally outside, which means we search for it */
|
||||
|
||||
/* now we can assume that the start is *before* the current mmap region */
|
||||
/* if the readend is past mapstart, we have two options */
|
||||
/* now we can assume that the start is *before* the current mmap region */
|
||||
/* if the readend is past mapstart, we have two options */
|
||||
} else if (readend >= mapstart) {
|
||||
/* either the read buffer overlaps the start of the mmap region */
|
||||
/* or the read buffer fully contains the current mmap region */
|
||||
/* either way, it's really not relevant, we just create a new region anyway*/
|
||||
GST_LOG_OBJECT (src, "read buf %llu+%d starts before mapbuf %d+%d, but overlaps it",
|
||||
(unsigned long long) src->curoffset, (gint) readsize, (gint) mapstart, (gint) mapsize);
|
||||
/* either way, it's really not relevant, we just create a new region anyway */
|
||||
GST_LOG_OBJECT (src,
|
||||
"read buf %llu+%d starts before mapbuf %d+%d, but overlaps it",
|
||||
(unsigned long long) src->curoffset, (gint) readsize, (gint) mapstart,
|
||||
(gint) mapsize);
|
||||
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
@ -517,32 +530,35 @@ gst_filesrc_get_mmap (GstFileSrc *src)
|
|||
if (buf == NULL) {
|
||||
/* first check to see if there's a map that covers the right region already */
|
||||
GST_LOG_OBJECT (src, "searching for mapbuf to cover %llu+%d",
|
||||
src->curoffset,(int)readsize);
|
||||
|
||||
src->curoffset, (int) readsize);
|
||||
|
||||
/* if the read buffer crosses a mmap region boundary, create a one-off region */
|
||||
if ((src->curoffset / src->mapsize) != (readend / src->mapsize)) {
|
||||
GST_LOG_OBJECT (src, "read buf %llu+%d crosses a %d-byte boundary, creating a one-off",
|
||||
src->curoffset,(int)readsize,(int)src->mapsize);
|
||||
GST_LOG_OBJECT (src,
|
||||
"read buf %llu+%d crosses a %d-byte boundary, creating a one-off",
|
||||
src->curoffset, (int) readsize, (int) src->mapsize);
|
||||
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
/* otherwise we will create a new mmap region and set it to the default */
|
||||
/* otherwise we will create a new mmap region and set it to the default */
|
||||
} else {
|
||||
size_t mapsize;
|
||||
|
||||
off_t nextmap = src->curoffset - (src->curoffset % src->mapsize);
|
||||
GST_LOG_OBJECT (src, "read buf %llu+%d in new mapbuf at %llu+%d, mapping and subbuffering",
|
||||
src->curoffset, readsize, nextmap, src->mapsize);
|
||||
|
||||
GST_LOG_OBJECT (src,
|
||||
"read buf %llu+%d in new mapbuf at %llu+%d, mapping and subbuffering",
|
||||
src->curoffset, readsize, nextmap, src->mapsize);
|
||||
/* first, we're done with the old mapbuf */
|
||||
gst_buffer_unref(src->mapbuf);
|
||||
gst_buffer_unref (src->mapbuf);
|
||||
mapsize = src->mapsize;
|
||||
|
||||
/* double the mapsize as long as the readsize is smaller */
|
||||
while (readsize - (src->curoffset - nextmap) > mapsize) {
|
||||
GST_LOG_OBJECT (src, "readsize smaller then mapsize %08x %d",
|
||||
readsize, (int)mapsize);
|
||||
mapsize <<=1;
|
||||
readsize, (int) mapsize);
|
||||
mapsize <<= 1;
|
||||
}
|
||||
/* create a new one */
|
||||
src->mapbuf = gst_filesrc_map_region (src, nextmap, mapsize);
|
||||
|
@ -550,8 +566,11 @@ gst_filesrc_get_mmap (GstFileSrc *src)
|
|||
return NULL;
|
||||
|
||||
/* subbuffer it */
|
||||
buf = gst_buffer_create_sub (src->mapbuf, src->curoffset - nextmap, readsize);
|
||||
GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET (src->mapbuf) + src->curoffset - nextmap;
|
||||
buf =
|
||||
gst_buffer_create_sub (src->mapbuf, src->curoffset - nextmap,
|
||||
readsize);
|
||||
GST_BUFFER_OFFSET (buf) =
|
||||
GST_BUFFER_OFFSET (src->mapbuf) + src->curoffset - nextmap;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -559,18 +578,18 @@ gst_filesrc_get_mmap (GstFileSrc *src)
|
|||
if (src->touch) {
|
||||
volatile guchar *p = GST_BUFFER_DATA (buf), c;
|
||||
|
||||
for (i=0; i < GST_BUFFER_SIZE (buf); i += src->pagesize)
|
||||
for (i = 0; i < GST_BUFFER_SIZE (buf); i += src->pagesize)
|
||||
c = p[i];
|
||||
}
|
||||
|
||||
/* we're done, return the buffer */
|
||||
g_assert (src->curoffset == GST_BUFFER_OFFSET (buf));
|
||||
src->curoffset += GST_BUFFER_SIZE(buf);
|
||||
src->curoffset += GST_BUFFER_SIZE (buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_filesrc_get_read (GstFileSrc *src)
|
||||
gst_filesrc_get_read (GstFileSrc * src)
|
||||
{
|
||||
GstBuffer *buf = NULL;
|
||||
size_t readsize;
|
||||
|
@ -578,7 +597,8 @@ gst_filesrc_get_read (GstFileSrc *src)
|
|||
|
||||
readsize = src->block_size;
|
||||
if (src->curoffset + readsize > src->filelen) {
|
||||
if (!gst_filesrc_check_filesize (src) || src->curoffset + readsize > src->filelen) {
|
||||
if (!gst_filesrc_check_filesize (src)
|
||||
|| src->curoffset + readsize > src->filelen) {
|
||||
readsize = src->filelen - src->curoffset;
|
||||
}
|
||||
}
|
||||
|
@ -587,12 +607,13 @@ gst_filesrc_get_read (GstFileSrc *src)
|
|||
g_return_val_if_fail (buf != NULL, NULL);
|
||||
|
||||
ret = read (src->fd, GST_BUFFER_DATA (buf), readsize);
|
||||
if (ret < 0){
|
||||
if (ret < 0) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
|
||||
return NULL;
|
||||
}
|
||||
if (ret < readsize) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("unexpected end of file."));
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
|
||||
("unexpected end of file."));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -606,7 +627,7 @@ gst_filesrc_get_read (GstFileSrc *src)
|
|||
}
|
||||
|
||||
static GstData *
|
||||
gst_filesrc_get (GstPad *pad)
|
||||
gst_filesrc_get (GstPad * pad)
|
||||
{
|
||||
GstFileSrc *src;
|
||||
|
||||
|
@ -626,7 +647,9 @@ gst_filesrc_get (GstPad *pad)
|
|||
|
||||
src->seek_happened = FALSE;
|
||||
GST_DEBUG_OBJECT (src, "sending discont");
|
||||
event = gst_event_new_discontinuous (FALSE, GST_FORMAT_BYTES, src->curoffset, NULL);
|
||||
event =
|
||||
gst_event_new_discontinuous (FALSE, GST_FORMAT_BYTES, src->curoffset,
|
||||
NULL);
|
||||
return GST_DATA (event);
|
||||
}
|
||||
|
||||
|
@ -634,77 +657,76 @@ gst_filesrc_get (GstPad *pad)
|
|||
g_assert (src->curoffset <= src->filelen);
|
||||
if (src->curoffset == src->filelen) {
|
||||
if (!gst_filesrc_check_filesize (src) || src->curoffset >= src->filelen) {
|
||||
GST_DEBUG_OBJECT (src, "eos %" G_GINT64_FORMAT" %" G_GINT64_FORMAT,
|
||||
src->curoffset, src->filelen);
|
||||
GST_DEBUG_OBJECT (src, "eos %" G_GINT64_FORMAT " %" G_GINT64_FORMAT,
|
||||
src->curoffset, src->filelen);
|
||||
gst_element_set_eos (GST_ELEMENT (src));
|
||||
return GST_DATA (gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
}
|
||||
|
||||
if (src->using_mmap){
|
||||
if (src->using_mmap) {
|
||||
return GST_DATA (gst_filesrc_get_mmap (src));
|
||||
}else{
|
||||
} else {
|
||||
return GST_DATA (gst_filesrc_get_read (src));
|
||||
}
|
||||
}
|
||||
|
||||
/* TRUE if the filesize of the file was updated */
|
||||
static gboolean
|
||||
gst_filesrc_check_filesize (GstFileSrc *src)
|
||||
gst_filesrc_check_filesize (GstFileSrc * src)
|
||||
{
|
||||
struct stat stat_results;
|
||||
|
||||
g_return_val_if_fail (GST_FLAG_IS_SET (src ,GST_FILESRC_OPEN), FALSE);
|
||||
|
||||
fstat(src->fd, &stat_results);
|
||||
GST_DEBUG_OBJECT (src, "checked filesize on %s (was %"G_GUINT64_FORMAT", is %"G_GUINT64_FORMAT")",
|
||||
src->filename, src->filelen, (guint64) stat_results.st_size);
|
||||
g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN), FALSE);
|
||||
|
||||
fstat (src->fd, &stat_results);
|
||||
GST_DEBUG_OBJECT (src,
|
||||
"checked filesize on %s (was %" G_GUINT64_FORMAT ", is %" G_GUINT64_FORMAT
|
||||
")", src->filename, src->filelen, (guint64) stat_results.st_size);
|
||||
if (src->filelen == (guint64) stat_results.st_size)
|
||||
return FALSE;
|
||||
src->filelen = stat_results.st_size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* open the file and mmap it, necessary to go to READY state */
|
||||
static gboolean
|
||||
gst_filesrc_open_file (GstFileSrc *src)
|
||||
gst_filesrc_open_file (GstFileSrc * src)
|
||||
{
|
||||
g_return_val_if_fail (!GST_FLAG_IS_SET (src ,GST_FILESRC_OPEN), FALSE);
|
||||
g_return_val_if_fail (!GST_FLAG_IS_SET (src, GST_FILESRC_OPEN), FALSE);
|
||||
|
||||
if (src->filename == NULL || src->filename[0] == '\0')
|
||||
{
|
||||
if (src->filename == NULL || src->filename[0] == '\0') {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
|
||||
(_("No file name specified for reading.")), (NULL));
|
||||
(_("No file name specified for reading.")), (NULL));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
GST_INFO_OBJECT (src, "opening file %s",src->filename);
|
||||
GST_INFO_OBJECT (src, "opening file %s", src->filename);
|
||||
|
||||
/* open the file */
|
||||
src->fd = open (src->filename, O_RDONLY);
|
||||
if (src->fd < 0)
|
||||
{
|
||||
if (src->fd < 0) {
|
||||
if (errno == ENOENT)
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL), (NULL));
|
||||
else
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
||||
(_("Could not open file \"%s\" for reading."), src->filename),
|
||||
GST_ERROR_SYSTEM);
|
||||
(_("Could not open file \"%s\" for reading."), src->filename),
|
||||
GST_ERROR_SYSTEM);
|
||||
return FALSE;
|
||||
} else {
|
||||
/* check if it is a regular file, otherwise bail out */
|
||||
struct stat stat_results;
|
||||
|
||||
fstat(src->fd, &stat_results);
|
||||
fstat (src->fd, &stat_results);
|
||||
|
||||
if (!S_ISREG(stat_results.st_mode)) {
|
||||
if (!S_ISREG (stat_results.st_mode)) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
||||
(_("File \"%s\" isn't a regular file."), src->filename),
|
||||
(NULL));
|
||||
close(src->fd);
|
||||
(_("File \"%s\" isn't a regular file."), src->filename), (NULL));
|
||||
close (src->fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* find the file length */
|
||||
src->filelen = stat_results.st_size;
|
||||
|
||||
|
@ -712,7 +734,7 @@ gst_filesrc_open_file (GstFileSrc *src)
|
|||
src->mapbuf = gst_filesrc_map_region (src, 0, src->mapsize);
|
||||
if (src->mapbuf == NULL) {
|
||||
src->using_mmap = FALSE;
|
||||
}else{
|
||||
} else {
|
||||
src->using_mmap = TRUE;
|
||||
}
|
||||
|
||||
|
@ -725,7 +747,7 @@ gst_filesrc_open_file (GstFileSrc *src)
|
|||
|
||||
/* unmap and close the file */
|
||||
static void
|
||||
gst_filesrc_close_file (GstFileSrc *src)
|
||||
gst_filesrc_close_file (GstFileSrc * src)
|
||||
{
|
||||
g_return_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN));
|
||||
|
||||
|
@ -747,9 +769,9 @@ gst_filesrc_close_file (GstFileSrc *src)
|
|||
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_filesrc_change_state (GstElement *element)
|
||||
gst_filesrc_change_state (GstElement * element)
|
||||
{
|
||||
GstFileSrc *src = GST_FILESRC(element);
|
||||
GstFileSrc *src = GST_FILESRC (element);
|
||||
|
||||
switch (GST_STATE_TRANSITION (element)) {
|
||||
case GST_STATE_NULL_TO_READY:
|
||||
|
@ -758,13 +780,13 @@ gst_filesrc_change_state (GstElement *element)
|
|||
break;
|
||||
case GST_STATE_READY_TO_PAUSED:
|
||||
if (!GST_FLAG_IS_SET (element, GST_FILESRC_OPEN)) {
|
||||
if (!gst_filesrc_open_file (GST_FILESRC (element)))
|
||||
return GST_STATE_FAILURE;
|
||||
if (!gst_filesrc_open_file (GST_FILESRC (element)))
|
||||
return GST_STATE_FAILURE;
|
||||
}
|
||||
break;
|
||||
case GST_STATE_PAUSED_TO_READY:
|
||||
if (GST_FLAG_IS_SET (element, GST_FILESRC_OPEN))
|
||||
gst_filesrc_close_file (GST_FILESRC (element));
|
||||
gst_filesrc_close_file (GST_FILESRC (element));
|
||||
src->seek_happened = TRUE;
|
||||
break;
|
||||
default:
|
||||
|
@ -778,8 +800,8 @@ gst_filesrc_change_state (GstElement *element)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_filesrc_srcpad_query (GstPad *pad, GstQueryType type,
|
||||
GstFormat *format, gint64 *value)
|
||||
gst_filesrc_srcpad_query (GstPad * pad, GstQueryType type,
|
||||
GstFormat * format, gint64 * value)
|
||||
{
|
||||
GstFileSrc *src = GST_FILESRC (GST_PAD_PARENT (pad));
|
||||
|
||||
|
@ -794,14 +816,14 @@ gst_filesrc_srcpad_query (GstPad *pad, GstQueryType type,
|
|||
case GST_QUERY_POSITION:
|
||||
switch (*format) {
|
||||
case GST_FORMAT_BYTES:
|
||||
*value = src->curoffset;
|
||||
break;
|
||||
*value = src->curoffset;
|
||||
break;
|
||||
case GST_FORMAT_PERCENT:
|
||||
if (src->filelen == 0)
|
||||
return FALSE;
|
||||
*value = src->curoffset * GST_FORMAT_PERCENT_MAX / src->filelen;
|
||||
break;
|
||||
default:
|
||||
*value = src->curoffset * GST_FORMAT_PERCENT_MAX / src->filelen;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
@ -813,7 +835,7 @@ gst_filesrc_srcpad_query (GstPad *pad, GstQueryType type,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
|
||||
gst_filesrc_srcpad_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstFileSrc *src = GST_FILESRC (GST_PAD_PARENT (pad));
|
||||
|
||||
|
@ -831,35 +853,41 @@ gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
|
|||
offset = GST_EVENT_SEEK_OFFSET (event);
|
||||
|
||||
switch (GST_EVENT_SEEK_METHOD (event)) {
|
||||
case GST_SEEK_METHOD_SET:
|
||||
if (offset > src->filelen && (!gst_filesrc_check_filesize (src) || offset > src->filelen)) {
|
||||
goto error;
|
||||
case GST_SEEK_METHOD_SET:
|
||||
if (offset > src->filelen && (!gst_filesrc_check_filesize (src)
|
||||
|| offset > src->filelen)) {
|
||||
goto error;
|
||||
}
|
||||
src->curoffset = offset;
|
||||
GST_DEBUG_OBJECT (src, "seek set pending to %" G_GINT64_FORMAT, src->curoffset);
|
||||
src->curoffset = offset;
|
||||
GST_DEBUG_OBJECT (src, "seek set pending to %" G_GINT64_FORMAT,
|
||||
src->curoffset);
|
||||
break;
|
||||
case GST_SEEK_METHOD_CUR:
|
||||
if (offset + src->curoffset > src->filelen)
|
||||
if (!gst_filesrc_check_filesize (src) || offset + src->curoffset > src->filelen)
|
||||
case GST_SEEK_METHOD_CUR:
|
||||
if (offset + src->curoffset > src->filelen)
|
||||
if (!gst_filesrc_check_filesize (src)
|
||||
|| offset + src->curoffset > src->filelen)
|
||||
goto error;
|
||||
src->curoffset += offset;
|
||||
GST_DEBUG_OBJECT (src, "seek cur pending to %" G_GINT64_FORMAT, src->curoffset);
|
||||
src->curoffset += offset;
|
||||
GST_DEBUG_OBJECT (src, "seek cur pending to %" G_GINT64_FORMAT,
|
||||
src->curoffset);
|
||||
break;
|
||||
case GST_SEEK_METHOD_END:
|
||||
if (ABS (offset) > src->filelen) {
|
||||
if (!gst_filesrc_check_filesize (src) || ABS (offset) > src->filelen)
|
||||
case GST_SEEK_METHOD_END:
|
||||
if (ABS (offset) > src->filelen) {
|
||||
if (!gst_filesrc_check_filesize (src)
|
||||
|| ABS (offset) > src->filelen)
|
||||
goto error;
|
||||
goto error;
|
||||
}
|
||||
src->curoffset = src->filelen - ABS (offset);
|
||||
GST_DEBUG_OBJECT (src, "seek end pending to %" G_GINT64_FORMAT, src->curoffset);
|
||||
src->curoffset = src->filelen - ABS (offset);
|
||||
GST_DEBUG_OBJECT (src, "seek end pending to %" G_GINT64_FORMAT,
|
||||
src->curoffset);
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
src->seek_happened = TRUE;
|
||||
src->need_flush = GST_EVENT_SEEK_FLAGS(event) & GST_SEEK_FLAG_FLUSH;
|
||||
src->need_flush = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH;
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_SIZE:
|
||||
|
@ -867,7 +895,7 @@ gst_filesrc_srcpad_event (GstPad *pad, GstEvent *event)
|
|||
goto error;
|
||||
}
|
||||
src->block_size = GST_EVENT_SIZE_VALUE (event);
|
||||
g_object_notify (G_OBJECT (src), "blocksize");
|
||||
g_object_notify (G_OBJECT (src), "blocksize");
|
||||
break;
|
||||
case GST_EVENT_FLUSH:
|
||||
src->need_flush = TRUE;
|
||||
|
@ -892,20 +920,21 @@ gst_filesrc_uri_get_type (void)
|
|||
return GST_URI_SRC;
|
||||
}
|
||||
static gchar **
|
||||
gst_filesrc_uri_get_protocols(void)
|
||||
gst_filesrc_uri_get_protocols (void)
|
||||
{
|
||||
static gchar *protocols[] = {"file", NULL};
|
||||
static gchar *protocols[] = { "file", NULL };
|
||||
return protocols;
|
||||
}
|
||||
static const gchar *
|
||||
gst_filesrc_uri_get_uri (GstURIHandler *handler)
|
||||
gst_filesrc_uri_get_uri (GstURIHandler * handler)
|
||||
{
|
||||
GstFileSrc *src = GST_FILESRC (handler);
|
||||
|
||||
|
||||
return src->uri;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_filesrc_uri_set_uri (GstURIHandler *handler, const gchar *uri)
|
||||
gst_filesrc_uri_set_uri (GstURIHandler * handler, const gchar * uri)
|
||||
{
|
||||
gchar *protocol, *location;
|
||||
gboolean ret;
|
||||
|
|
|
@ -29,21 +29,19 @@
|
|||
#include <sys/types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GST_TYPE_FILESRC \
|
||||
(gst_filesrc_get_type())
|
||||
#define GST_FILESRC(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FILESRC,GstFileSrc))
|
||||
#define GST_FILESRC_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FILESRC,GstFileSrcClass))
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FILESRC,GstFileSrcClass))
|
||||
#define GST_IS_FILESRC(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FILESRC))
|
||||
#define GST_IS_FILESRC_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FILESRC))
|
||||
|
||||
typedef enum {
|
||||
GST_FILESRC_OPEN = GST_ELEMENT_FLAG_LAST,
|
||||
typedef enum
|
||||
{
|
||||
GST_FILESRC_OPEN = GST_ELEMENT_FLAG_LAST,
|
||||
|
||||
GST_FILESRC_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2
|
||||
} GstFileSrcFlags;
|
||||
|
@ -51,20 +49,21 @@ typedef enum {
|
|||
typedef struct _GstFileSrc GstFileSrc;
|
||||
typedef struct _GstFileSrcClass GstFileSrcClass;
|
||||
|
||||
struct _GstFileSrc {
|
||||
struct _GstFileSrc
|
||||
{
|
||||
GstElement element;
|
||||
GstPad *srcpad;
|
||||
|
||||
guint pagesize; /* system page size*/
|
||||
|
||||
gchar *filename; /* filename */
|
||||
gchar *uri; /* caching the URI */
|
||||
gint fd; /* open file descriptor*/
|
||||
off_t filelen; /* what's the file length?*/
|
||||
guint pagesize; /* system page size */
|
||||
|
||||
off_t curoffset; /* current offset in file*/
|
||||
off_t block_size; /* bytes per read */
|
||||
gboolean touch; /* whether to touch every page */
|
||||
gchar *filename; /* filename */
|
||||
gchar *uri; /* caching the URI */
|
||||
gint fd; /* open file descriptor */
|
||||
off_t filelen; /* what's the file length? */
|
||||
|
||||
off_t curoffset; /* current offset in file */
|
||||
off_t block_size; /* bytes per read */
|
||||
gboolean touch; /* whether to touch every page */
|
||||
gboolean using_mmap;
|
||||
|
||||
GstBuffer *mapbuf;
|
||||
|
@ -74,12 +73,12 @@ struct _GstFileSrc {
|
|||
gboolean need_flush;
|
||||
};
|
||||
|
||||
struct _GstFileSrcClass {
|
||||
struct _GstFileSrcClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_filesrc_get_type(void);
|
||||
GType gst_filesrc_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_FILESRC_H__ */
|
||||
|
|
|
@ -34,22 +34,22 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_identity_debug);
|
||||
#define GST_CAT_DEFAULT gst_identity_debug
|
||||
|
||||
GstElementDetails gst_identity_details = GST_ELEMENT_DETAILS (
|
||||
"Identity",
|
||||
"Generic",
|
||||
"Pass data without modification",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>"
|
||||
);
|
||||
GstElementDetails gst_identity_details = GST_ELEMENT_DETAILS ("Identity",
|
||||
"Generic",
|
||||
"Pass data without modification",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>");
|
||||
|
||||
|
||||
/* Identity signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
SIGNAL_HANDOFF,
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_LOOP_BASED,
|
||||
ARG_SLEEP_TIME,
|
||||
|
@ -65,12 +65,15 @@ enum {
|
|||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_identity_debug, "identity", 0, "identity element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstIdentity, gst_identity, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
GST_BOILERPLATE_FULL (GstIdentity, gst_identity, GstElement, GST_TYPE_ELEMENT,
|
||||
_do_init);
|
||||
|
||||
static void gst_identity_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
static void gst_identity_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||
static void gst_identity_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_identity_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static void gst_identity_chain (GstPad *pad, GstData *_data);
|
||||
static void gst_identity_chain (GstPad * pad, GstData * _data);
|
||||
|
||||
static guint gst_identity_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
@ -78,11 +81,11 @@ static void
|
|||
gst_identity_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &gst_identity_details);
|
||||
}
|
||||
static void
|
||||
gst_identity_class_init (GstIdentityClass *klass)
|
||||
static void
|
||||
gst_identity_class_init (GstIdentityClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
|
||||
|
@ -90,50 +93,52 @@ gst_identity_class_init (GstIdentityClass *klass)
|
|||
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOOP_BASED,
|
||||
g_param_spec_boolean ("loop-based", "Loop-based",
|
||||
"Set to TRUE to use loop-based rather than chain-based scheduling",
|
||||
TRUE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("loop-based", "Loop-based",
|
||||
"Set to TRUE to use loop-based rather than chain-based scheduling",
|
||||
TRUE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SLEEP_TIME,
|
||||
g_param_spec_uint ("sleep-time", "Sleep time", "Microseconds to sleep between processing",
|
||||
0, G_MAXUINT, 0, G_PARAM_READWRITE));
|
||||
g_param_spec_uint ("sleep-time", "Sleep time",
|
||||
"Microseconds to sleep between processing", 0, G_MAXUINT, 0,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUPLICATE,
|
||||
g_param_spec_uint ("duplicate", "Duplicate Buffers", "Push the buffers N times",
|
||||
0, G_MAXUINT, 1, G_PARAM_READWRITE));
|
||||
g_param_spec_uint ("duplicate", "Duplicate Buffers",
|
||||
"Push the buffers N times", 0, G_MAXUINT, 1, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ERROR_AFTER,
|
||||
g_param_spec_int ("error_after", "Error After", "Error after N buffers",
|
||||
G_MININT, G_MAXINT, -1, G_PARAM_READWRITE));
|
||||
g_param_spec_int ("error_after", "Error After", "Error after N buffers",
|
||||
G_MININT, G_MAXINT, -1, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DROP_PROBABILITY,
|
||||
g_param_spec_float ("drop_probability", "Drop Probability", "The Probability a buffer is dropped",
|
||||
0.0, 1.0, 0.0, G_PARAM_READWRITE));
|
||||
g_param_spec_float ("drop_probability", "Drop Probability",
|
||||
"The Probability a buffer is dropped", 0.0, 1.0, 0.0,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
|
||||
g_param_spec_boolean ("silent", "silent", "silent",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("silent", "silent", "silent", FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
|
||||
g_param_spec_string ("last-message", "last-message", "last-message",
|
||||
NULL, G_PARAM_READABLE));
|
||||
g_param_spec_string ("last-message", "last-message", "last-message", NULL,
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
|
||||
g_param_spec_boolean("dump", "Dump", "Dump buffer contents",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("dump", "Dump", "Dump buffer contents", FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
gst_identity_signals[SIGNAL_HANDOFF] =
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstIdentityClass, handoff), NULL, NULL,
|
||||
gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
|
||||
GST_TYPE_BUFFER);
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstIdentityClass, handoff), NULL, NULL,
|
||||
gst_marshal_VOID__POINTER, G_TYPE_NONE, 1, GST_TYPE_BUFFER);
|
||||
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_identity_set_property);
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_identity_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_identity_get_property);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_identity_init (GstIdentity *identity)
|
||||
static void
|
||||
gst_identity_init (GstIdentity * identity)
|
||||
{
|
||||
identity->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (identity), identity->sinkpad);
|
||||
gst_pad_set_chain_function (identity->sinkpad, GST_DEBUG_FUNCPTR (gst_identity_chain));
|
||||
gst_pad_set_chain_function (identity->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_identity_chain));
|
||||
gst_pad_set_link_function (identity->sinkpad, gst_pad_proxy_pad_link);
|
||||
gst_pad_set_getcaps_function (identity->sinkpad, gst_pad_proxy_getcaps);
|
||||
|
||||
|
||||
identity->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_element_add_pad (GST_ELEMENT (identity), identity->srcpad);
|
||||
gst_pad_set_link_function (identity->srcpad, gst_pad_proxy_pad_link);
|
||||
|
@ -150,8 +155,8 @@ gst_identity_init (GstIdentity *identity)
|
|||
identity->srccaps = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_identity_chain (GstPad *pad, GstData *_data)
|
||||
static void
|
||||
gst_identity_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
GstBuffer *buf = GST_BUFFER (_data);
|
||||
GstIdentity *identity;
|
||||
|
@ -168,20 +173,20 @@ gst_identity_chain (GstPad *pad, GstData *_data)
|
|||
if (identity->error_after == 0) {
|
||||
gst_buffer_unref (buf);
|
||||
GST_ELEMENT_ERROR (identity, CORE, FAILED,
|
||||
(_("Failed after iterations as requested.")),
|
||||
(NULL));
|
||||
(_("Failed after iterations as requested.")), (NULL));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (identity->drop_probability > 0.0) {
|
||||
if ((gfloat)(1.0*rand()/(RAND_MAX)) < identity->drop_probability) {
|
||||
if ((gfloat) (1.0 * rand () / (RAND_MAX)) < identity->drop_probability) {
|
||||
if (identity->last_message != NULL) {
|
||||
g_free (identity->last_message);
|
||||
}
|
||||
identity->last_message = g_strdup_printf ("dropping ******* (%s:%s)i (%d bytes, %"
|
||||
G_GINT64_FORMAT ")",
|
||||
GST_DEBUG_PAD_NAME (identity->sinkpad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
identity->last_message =
|
||||
g_strdup_printf ("dropping ******* (%s:%s)i (%d bytes, %"
|
||||
G_GINT64_FORMAT ")", GST_DEBUG_PAD_NAME (identity->sinkpad),
|
||||
GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
g_object_notify (G_OBJECT (identity), "last-message");
|
||||
gst_buffer_unref (buf);
|
||||
return;
|
||||
|
@ -194,16 +199,17 @@ gst_identity_chain (GstPad *pad, GstData *_data)
|
|||
for (i = identity->duplicate; i; i--) {
|
||||
if (!identity->silent) {
|
||||
g_free (identity->last_message);
|
||||
identity->last_message = g_strdup_printf ("chain ******* (%s:%s)i (%d bytes, %"
|
||||
G_GINT64_FORMAT ")",
|
||||
GST_DEBUG_PAD_NAME (identity->sinkpad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
identity->last_message =
|
||||
g_strdup_printf ("chain ******* (%s:%s)i (%d bytes, %"
|
||||
G_GINT64_FORMAT ")", GST_DEBUG_PAD_NAME (identity->sinkpad),
|
||||
GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
g_object_notify (G_OBJECT (identity), "last-message");
|
||||
}
|
||||
|
||||
g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
|
||||
buf);
|
||||
buf);
|
||||
|
||||
if (i>1)
|
||||
if (i > 1)
|
||||
gst_buffer_ref (buf);
|
||||
|
||||
gst_pad_push (identity->srcpad, GST_DATA (buf));
|
||||
|
@ -213,8 +219,8 @@ gst_identity_chain (GstPad *pad, GstData *_data)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_identity_loop (GstElement *element)
|
||||
static void
|
||||
gst_identity_loop (GstElement * element)
|
||||
{
|
||||
GstIdentity *identity;
|
||||
GstBuffer *buf;
|
||||
|
@ -223,43 +229,42 @@ gst_identity_loop (GstElement *element)
|
|||
g_return_if_fail (GST_IS_IDENTITY (element));
|
||||
|
||||
identity = GST_IDENTITY (element);
|
||||
|
||||
|
||||
buf = GST_BUFFER (gst_pad_pull (identity->sinkpad));
|
||||
if (GST_IS_EVENT (buf)) {
|
||||
GstEvent *event = GST_EVENT (buf);
|
||||
|
||||
if (GST_EVENT_IS_INTERRUPT (event)) {
|
||||
gst_event_unref (event);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
gst_pad_event_default (identity->sinkpad, event);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
gst_identity_chain (identity->sinkpad, GST_DATA (buf));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_identity_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_identity_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstIdentity *identity;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_IDENTITY (object));
|
||||
|
||||
|
||||
identity = GST_IDENTITY (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_LOOP_BASED:
|
||||
identity->loop_based = g_value_get_boolean (value);
|
||||
if (identity->loop_based) {
|
||||
gst_element_set_loop_function (GST_ELEMENT (identity), gst_identity_loop);
|
||||
gst_pad_set_chain_function (identity->sinkpad, NULL);
|
||||
}
|
||||
else {
|
||||
gst_pad_set_chain_function (identity->sinkpad, gst_identity_chain);
|
||||
gst_element_set_loop_function (GST_ELEMENT (identity), NULL);
|
||||
gst_element_set_loop_function (GST_ELEMENT (identity),
|
||||
gst_identity_loop);
|
||||
gst_pad_set_chain_function (identity->sinkpad, NULL);
|
||||
} else {
|
||||
gst_pad_set_chain_function (identity->sinkpad, gst_identity_chain);
|
||||
gst_element_set_loop_function (GST_ELEMENT (identity), NULL);
|
||||
}
|
||||
break;
|
||||
case ARG_SLEEP_TIME:
|
||||
|
@ -285,12 +290,15 @@ gst_identity_set_property (GObject *object, guint prop_id, const GValue *value,
|
|||
}
|
||||
}
|
||||
|
||||
static void gst_identity_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
|
||||
static void
|
||||
gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstIdentity *identity;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_IDENTITY (object));
|
||||
|
||||
|
||||
identity = GST_IDENTITY (object);
|
||||
|
||||
switch (prop_id) {
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GST_TYPE_IDENTITY \
|
||||
(gst_identity_get_type())
|
||||
#define GST_IDENTITY(obj) \
|
||||
|
@ -40,36 +38,36 @@ G_BEGIN_DECLS
|
|||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IDENTITY))
|
||||
#define GST_IS_IDENTITY_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IDENTITY))
|
||||
|
||||
typedef struct _GstIdentity GstIdentity;
|
||||
typedef struct _GstIdentityClass GstIdentityClass;
|
||||
|
||||
struct _GstIdentity {
|
||||
GstElement element;
|
||||
struct _GstIdentity
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
GstPad *sinkpad;
|
||||
GstPad *srcpad;
|
||||
GstPad *sinkpad;
|
||||
GstPad *srcpad;
|
||||
|
||||
gboolean loop_based;
|
||||
guint duplicate;
|
||||
gint error_after;
|
||||
gfloat drop_probability;
|
||||
guint sleep_time;
|
||||
gboolean silent;
|
||||
gboolean dump;
|
||||
gchar *last_message;
|
||||
GstCaps *srccaps;
|
||||
gboolean loop_based;
|
||||
guint duplicate;
|
||||
gint error_after;
|
||||
gfloat drop_probability;
|
||||
guint sleep_time;
|
||||
gboolean silent;
|
||||
gboolean dump;
|
||||
gchar *last_message;
|
||||
GstCaps *srccaps;
|
||||
};
|
||||
|
||||
struct _GstIdentityClass {
|
||||
struct _GstIdentityClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*handoff) (GstElement *element, GstBuffer *buf);
|
||||
void (*handoff) (GstElement * element, GstBuffer * buf);
|
||||
};
|
||||
|
||||
GType gst_identity_get_type(void);
|
||||
GType gst_identity_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_IDENTITY_H__ */
|
||||
|
|
|
@ -35,63 +35,64 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_md5sink_debug);
|
||||
#define GST_CAT_DEFAULT gst_md5sink_debug
|
||||
|
||||
GstElementDetails gst_md5sink_details = GST_ELEMENT_DETAILS (
|
||||
"MD5 Sink",
|
||||
"Sink",
|
||||
"compute MD5 for incoming data",
|
||||
"Benjamin Otte <in7y118@public.uni-hamburg.de>"
|
||||
);
|
||||
GstElementDetails gst_md5sink_details = GST_ELEMENT_DETAILS ("MD5 Sink",
|
||||
"Sink",
|
||||
"compute MD5 for incoming data",
|
||||
"Benjamin Otte <in7y118@public.uni-hamburg.de>");
|
||||
|
||||
/* MD5Sink signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_MD5,
|
||||
/* FILL ME */
|
||||
};
|
||||
|
||||
GstStaticPadTemplate md5_sink_template = GST_STATIC_PAD_TEMPLATE (
|
||||
"sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
GstStaticPadTemplate md5_sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_md5sink_debug, "md5sink", 0, "md5sink element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstMD5Sink, gst_md5sink, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
GST_BOILERPLATE_FULL (GstMD5Sink, gst_md5sink, GstElement, GST_TYPE_ELEMENT,
|
||||
_do_init);
|
||||
|
||||
/* GObject stuff */
|
||||
/*static void gst_md5sink_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);*/
|
||||
static void gst_md5sink_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
static void gst_md5sink_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static void gst_md5sink_chain (GstPad *pad, GstData *_data);
|
||||
static GstElementStateReturn gst_md5sink_change_state (GstElement *element);
|
||||
static void gst_md5sink_chain (GstPad * pad, GstData * _data);
|
||||
static GstElementStateReturn gst_md5sink_change_state (GstElement * element);
|
||||
|
||||
|
||||
/* MD5 stuff */
|
||||
static void md5_init_ctx (GstMD5Sink *ctx);
|
||||
static gpointer md5_read_ctx (GstMD5Sink *ctx, gpointer resbuf);
|
||||
static gpointer md5_finish_ctx (GstMD5Sink *ctx, gpointer resbuf);
|
||||
static void md5_process_bytes (const void *buffer, size_t len, GstMD5Sink *ctx);
|
||||
static void md5_process_block (const void *buffer, size_t len, GstMD5Sink *ctx);
|
||||
static void md5_init_ctx (GstMD5Sink * ctx);
|
||||
static gpointer md5_read_ctx (GstMD5Sink * ctx, gpointer resbuf);
|
||||
static gpointer md5_finish_ctx (GstMD5Sink * ctx, gpointer resbuf);
|
||||
static void md5_process_bytes (const void *buffer, size_t len,
|
||||
GstMD5Sink * ctx);
|
||||
static void md5_process_block (const void *buffer, size_t len,
|
||||
GstMD5Sink * ctx);
|
||||
|
||||
/* This array contains the bytes used to pad the buffer to the next
|
||||
64-byte boundary. (RFC 1321, 3.1: Step 1) */
|
||||
static const guchar fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
|
||||
static const guchar fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
|
||||
|
||||
/* MD5 functions */
|
||||
/* Initialize structure containing state of computation.
|
||||
(RFC 1321, 3.3: Step 3) */
|
||||
static void
|
||||
md5_init_ctx (GstMD5Sink *ctx)
|
||||
md5_init_ctx (GstMD5Sink * ctx)
|
||||
{
|
||||
ctx->A = 0x67452301;
|
||||
ctx->B = 0xefcdab89;
|
||||
|
@ -101,13 +102,14 @@ md5_init_ctx (GstMD5Sink *ctx)
|
|||
ctx->total[0] = ctx->total[1] = 0;
|
||||
ctx->buflen = 0;
|
||||
}
|
||||
|
||||
/* Process the remaining bytes in the internal buffer and the usual
|
||||
prolog according to the standard and write the result to RESBUF.
|
||||
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
static gpointer
|
||||
md5_finish_ctx (GstMD5Sink *ctx, gpointer resbuf)
|
||||
md5_finish_ctx (GstMD5Sink * ctx, gpointer resbuf)
|
||||
{
|
||||
/* Take yet unprocessed bytes into account. */
|
||||
guint32 bytes = ctx->buflen;
|
||||
|
@ -122,22 +124,23 @@ md5_finish_ctx (GstMD5Sink *ctx, gpointer resbuf)
|
|||
memcpy (&ctx->buffer[bytes], fillbuf, pad);
|
||||
|
||||
/* Put the 64-bit file length in *bits* at the end of the buffer. */
|
||||
*(guint32 *) &ctx->buffer[bytes + pad] = GUINT32_TO_LE (ctx->total[0] << 3);
|
||||
*(guint32 *) &ctx->buffer[bytes + pad + 4] = GUINT32_TO_LE ((ctx->total[1] << 3) |
|
||||
(ctx->total[0] >> 29));
|
||||
*(guint32 *) & ctx->buffer[bytes + pad] = GUINT32_TO_LE (ctx->total[0] << 3);
|
||||
*(guint32 *) & ctx->buffer[bytes + pad + 4] =
|
||||
GUINT32_TO_LE ((ctx->total[1] << 3) | (ctx->total[0] >> 29));
|
||||
|
||||
/* Process last bytes. */
|
||||
md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
|
||||
|
||||
return md5_read_ctx (ctx, resbuf);
|
||||
}
|
||||
|
||||
/* Put result from CTX in first 16 bytes following RESBUF. The result
|
||||
must be in little endian byte order.
|
||||
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
static gpointer
|
||||
md5_read_ctx (GstMD5Sink *ctx, gpointer resbuf)
|
||||
md5_read_ctx (GstMD5Sink * ctx, gpointer resbuf)
|
||||
{
|
||||
((guint32 *) resbuf)[0] = GUINT32_TO_LE (ctx->A);
|
||||
((guint32 *) resbuf)[1] = GUINT32_TO_LE (ctx->B);
|
||||
|
@ -148,66 +151,60 @@ md5_read_ctx (GstMD5Sink *ctx, gpointer resbuf)
|
|||
}
|
||||
|
||||
static void
|
||||
md5_process_bytes (const void *buffer, size_t len, GstMD5Sink *ctx)
|
||||
md5_process_bytes (const void *buffer, size_t len, GstMD5Sink * ctx)
|
||||
{
|
||||
/*const void aligned_buffer = buffer; */
|
||||
|
||||
/* When we already have some bits in our internal buffer concatenate
|
||||
both inputs first. */
|
||||
if (ctx->buflen != 0)
|
||||
{
|
||||
size_t left_over = ctx->buflen;
|
||||
size_t add = 128 - left_over > len ? len : 128 - left_over;
|
||||
if (ctx->buflen != 0) {
|
||||
size_t left_over = ctx->buflen;
|
||||
size_t add = 128 - left_over > len ? len : 128 - left_over;
|
||||
|
||||
/* Only put full words in the buffer. */
|
||||
/* Forcing alignment here appears to be only an optimization.
|
||||
* The glibc source uses __alignof__, which seems to be a
|
||||
* gratuitous usage of a GCC extension, when sizeof() will
|
||||
* work fine. (And don't question the sanity of using
|
||||
* sizeof(guint32) instead of 4. */
|
||||
/* add -= add % __alignof__ (guint32); */
|
||||
add -= add % sizeof(guint32);
|
||||
/* Only put full words in the buffer. */
|
||||
/* Forcing alignment here appears to be only an optimization.
|
||||
* The glibc source uses __alignof__, which seems to be a
|
||||
* gratuitous usage of a GCC extension, when sizeof() will
|
||||
* work fine. (And don't question the sanity of using
|
||||
* sizeof(guint32) instead of 4. */
|
||||
/* add -= add % __alignof__ (guint32); */
|
||||
add -= add % sizeof (guint32);
|
||||
|
||||
memcpy (&ctx->buffer[left_over], buffer, add);
|
||||
ctx->buflen += add;
|
||||
memcpy (&ctx->buffer[left_over], buffer, add);
|
||||
ctx->buflen += add;
|
||||
|
||||
if (ctx->buflen > 64)
|
||||
{
|
||||
md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
|
||||
if (ctx->buflen > 64) {
|
||||
md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
|
||||
|
||||
ctx->buflen &= 63;
|
||||
/* The regions in the following copy operation cannot overlap. */
|
||||
memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
|
||||
ctx->buflen);
|
||||
}
|
||||
|
||||
buffer = (const char *) buffer + add;
|
||||
len -= add;
|
||||
ctx->buflen &= 63;
|
||||
/* The regions in the following copy operation cannot overlap. */
|
||||
memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], ctx->buflen);
|
||||
}
|
||||
|
||||
buffer = (const char *) buffer + add;
|
||||
len -= add;
|
||||
}
|
||||
|
||||
/* Process available complete blocks. */
|
||||
if (len > 64)
|
||||
{
|
||||
md5_process_block (buffer, len & ~63, ctx);
|
||||
buffer = (const char *) buffer + (len & ~63);
|
||||
len &= 63;
|
||||
}
|
||||
if (len > 64) {
|
||||
md5_process_block (buffer, len & ~63, ctx);
|
||||
buffer = (const char *) buffer + (len & ~63);
|
||||
len &= 63;
|
||||
}
|
||||
|
||||
/* Move remaining bytes in internal buffer. */
|
||||
if (len > 0)
|
||||
{
|
||||
size_t left_over = ctx->buflen;
|
||||
if (len > 0) {
|
||||
size_t left_over = ctx->buflen;
|
||||
|
||||
memcpy (&ctx->buffer[left_over], buffer, len);
|
||||
left_over += len;
|
||||
if (left_over >= 64)
|
||||
{
|
||||
md5_process_block (ctx->buffer, 64, ctx);
|
||||
left_over -= 64;
|
||||
memcpy (ctx->buffer, &ctx->buffer[64], left_over);
|
||||
}
|
||||
ctx->buflen = left_over;
|
||||
memcpy (&ctx->buffer[left_over], buffer, len);
|
||||
left_over += len;
|
||||
if (left_over >= 64) {
|
||||
md5_process_block (ctx->buffer, 64, ctx);
|
||||
left_over -= 64;
|
||||
memcpy (ctx->buffer, &ctx->buffer[64], left_over);
|
||||
}
|
||||
ctx->buflen = left_over;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -223,7 +220,7 @@ md5_process_bytes (const void *buffer, size_t len, GstMD5Sink *ctx)
|
|||
/* Process LEN bytes of BUFFER, accumulating context into CTX.
|
||||
It is assumed that LEN % 64 == 0. */
|
||||
static void
|
||||
md5_process_block (const void *buffer, size_t len, GstMD5Sink *ctx)
|
||||
md5_process_block (const void *buffer, size_t len, GstMD5Sink * ctx)
|
||||
{
|
||||
guint32 correct_words[16];
|
||||
const guint32 *words = buffer;
|
||||
|
@ -243,20 +240,19 @@ md5_process_block (const void *buffer, size_t len, GstMD5Sink *ctx)
|
|||
|
||||
/* Process all bytes in the buffer with 64 bytes in each round of
|
||||
the loop. */
|
||||
while (words < endp)
|
||||
{
|
||||
guint32 *cwp = correct_words;
|
||||
guint32 A_save = A;
|
||||
guint32 B_save = B;
|
||||
guint32 C_save = C;
|
||||
guint32 D_save = D;
|
||||
while (words < endp) {
|
||||
guint32 *cwp = correct_words;
|
||||
guint32 A_save = A;
|
||||
guint32 B_save = B;
|
||||
guint32 C_save = C;
|
||||
guint32 D_save = D;
|
||||
|
||||
/* First round: using the given function, the context and a constant
|
||||
the next context is computed. Because the algorithms processing
|
||||
unit is a 32-bit word and it is determined to work on words in
|
||||
little endian byte order we perhaps have to change the byte order
|
||||
before the computation. To reduce the work for the next steps
|
||||
we store the swapped words in the array CORRECT_WORDS. */
|
||||
/* First round: using the given function, the context and a constant
|
||||
the next context is computed. Because the algorithms processing
|
||||
unit is a 32-bit word and it is determined to work on words in
|
||||
little endian byte order we perhaps have to change the byte order
|
||||
before the computation. To reduce the work for the next steps
|
||||
we store the swapped words in the array CORRECT_WORDS. */
|
||||
|
||||
#define OP(a, b, c, d, s, T) \
|
||||
do \
|
||||
|
@ -268,37 +264,37 @@ md5_process_block (const void *buffer, size_t len, GstMD5Sink *ctx)
|
|||
} \
|
||||
while (0)
|
||||
|
||||
/* It is unfortunate that C does not provide an operator for
|
||||
cyclic rotation. Hope the C compiler is smart enough. */
|
||||
/* It is unfortunate that C does not provide an operator for
|
||||
cyclic rotation. Hope the C compiler is smart enough. */
|
||||
#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
|
||||
|
||||
/* Before we start, one word to the strange constants.
|
||||
They are defined in RFC 1321 as
|
||||
/* Before we start, one word to the strange constants.
|
||||
They are defined in RFC 1321 as
|
||||
|
||||
T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
|
||||
*/
|
||||
T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
|
||||
*/
|
||||
|
||||
/* Round 1. */
|
||||
OP (A, B, C, D, 7, 0xd76aa478);
|
||||
OP (D, A, B, C, 12, 0xe8c7b756);
|
||||
OP (C, D, A, B, 17, 0x242070db);
|
||||
OP (B, C, D, A, 22, 0xc1bdceee);
|
||||
OP (A, B, C, D, 7, 0xf57c0faf);
|
||||
OP (D, A, B, C, 12, 0x4787c62a);
|
||||
OP (C, D, A, B, 17, 0xa8304613);
|
||||
OP (B, C, D, A, 22, 0xfd469501);
|
||||
OP (A, B, C, D, 7, 0x698098d8);
|
||||
OP (D, A, B, C, 12, 0x8b44f7af);
|
||||
OP (C, D, A, B, 17, 0xffff5bb1);
|
||||
OP (B, C, D, A, 22, 0x895cd7be);
|
||||
OP (A, B, C, D, 7, 0x6b901122);
|
||||
OP (D, A, B, C, 12, 0xfd987193);
|
||||
OP (C, D, A, B, 17, 0xa679438e);
|
||||
OP (B, C, D, A, 22, 0x49b40821);
|
||||
/* Round 1. */
|
||||
OP (A, B, C, D, 7, 0xd76aa478);
|
||||
OP (D, A, B, C, 12, 0xe8c7b756);
|
||||
OP (C, D, A, B, 17, 0x242070db);
|
||||
OP (B, C, D, A, 22, 0xc1bdceee);
|
||||
OP (A, B, C, D, 7, 0xf57c0faf);
|
||||
OP (D, A, B, C, 12, 0x4787c62a);
|
||||
OP (C, D, A, B, 17, 0xa8304613);
|
||||
OP (B, C, D, A, 22, 0xfd469501);
|
||||
OP (A, B, C, D, 7, 0x698098d8);
|
||||
OP (D, A, B, C, 12, 0x8b44f7af);
|
||||
OP (C, D, A, B, 17, 0xffff5bb1);
|
||||
OP (B, C, D, A, 22, 0x895cd7be);
|
||||
OP (A, B, C, D, 7, 0x6b901122);
|
||||
OP (D, A, B, C, 12, 0xfd987193);
|
||||
OP (C, D, A, B, 17, 0xa679438e);
|
||||
OP (B, C, D, A, 22, 0x49b40821);
|
||||
|
||||
/* For the second to fourth round we have the possibly swapped words
|
||||
in CORRECT_WORDS. Redefine the macro to take an additional first
|
||||
argument specifying the function to use. */
|
||||
/* For the second to fourth round we have the possibly swapped words
|
||||
in CORRECT_WORDS. Redefine the macro to take an additional first
|
||||
argument specifying the function to use. */
|
||||
#undef OP
|
||||
#define OP(f, a, b, c, d, k, s, T) \
|
||||
do \
|
||||
|
@ -309,66 +305,66 @@ md5_process_block (const void *buffer, size_t len, GstMD5Sink *ctx)
|
|||
} \
|
||||
while (0)
|
||||
|
||||
/* Round 2. */
|
||||
OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
|
||||
OP (FG, D, A, B, C, 6, 9, 0xc040b340);
|
||||
OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
|
||||
OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
|
||||
OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
|
||||
OP (FG, D, A, B, C, 10, 9, 0x02441453);
|
||||
OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
|
||||
OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
|
||||
OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
|
||||
OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
|
||||
OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
|
||||
OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
|
||||
OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
|
||||
OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
|
||||
OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
|
||||
OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
|
||||
/* Round 2. */
|
||||
OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
|
||||
OP (FG, D, A, B, C, 6, 9, 0xc040b340);
|
||||
OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
|
||||
OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
|
||||
OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
|
||||
OP (FG, D, A, B, C, 10, 9, 0x02441453);
|
||||
OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
|
||||
OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
|
||||
OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
|
||||
OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
|
||||
OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
|
||||
OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
|
||||
OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
|
||||
OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
|
||||
OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
|
||||
OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
|
||||
|
||||
/* Round 3. */
|
||||
OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
|
||||
OP (FH, D, A, B, C, 8, 11, 0x8771f681);
|
||||
OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
|
||||
OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
|
||||
OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
|
||||
OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
|
||||
OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
|
||||
OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
|
||||
OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
|
||||
OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
|
||||
OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
|
||||
OP (FH, B, C, D, A, 6, 23, 0x04881d05);
|
||||
OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
|
||||
OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
|
||||
OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
|
||||
OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
|
||||
/* Round 3. */
|
||||
OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
|
||||
OP (FH, D, A, B, C, 8, 11, 0x8771f681);
|
||||
OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
|
||||
OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
|
||||
OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
|
||||
OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
|
||||
OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
|
||||
OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
|
||||
OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
|
||||
OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
|
||||
OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
|
||||
OP (FH, B, C, D, A, 6, 23, 0x04881d05);
|
||||
OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
|
||||
OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
|
||||
OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
|
||||
OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
|
||||
|
||||
/* Round 4. */
|
||||
OP (FI, A, B, C, D, 0, 6, 0xf4292244);
|
||||
OP (FI, D, A, B, C, 7, 10, 0x432aff97);
|
||||
OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
|
||||
OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
|
||||
OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
|
||||
OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
|
||||
OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
|
||||
OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
|
||||
OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
|
||||
OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
|
||||
OP (FI, C, D, A, B, 6, 15, 0xa3014314);
|
||||
OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
|
||||
OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
|
||||
OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
|
||||
OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
|
||||
OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
|
||||
/* Round 4. */
|
||||
OP (FI, A, B, C, D, 0, 6, 0xf4292244);
|
||||
OP (FI, D, A, B, C, 7, 10, 0x432aff97);
|
||||
OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
|
||||
OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
|
||||
OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
|
||||
OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
|
||||
OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
|
||||
OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
|
||||
OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
|
||||
OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
|
||||
OP (FI, C, D, A, B, 6, 15, 0xa3014314);
|
||||
OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
|
||||
OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
|
||||
OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
|
||||
OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
|
||||
OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
|
||||
|
||||
/* Add the starting values of the context. */
|
||||
A += A_save;
|
||||
B += B_save;
|
||||
C += C_save;
|
||||
D += D_save;
|
||||
}
|
||||
/* Add the starting values of the context. */
|
||||
A += A_save;
|
||||
B += B_save;
|
||||
C += C_save;
|
||||
D += D_save;
|
||||
}
|
||||
|
||||
/* Put checksum in context given as argument. */
|
||||
ctx->A = A;
|
||||
|
@ -381,14 +377,14 @@ static void
|
|||
gst_md5sink_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &gst_md5sink_details);
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&md5_sink_template));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_md5sink_class_init (GstMD5SinkClass *klass)
|
||||
gst_md5sink_class_init (GstMD5SinkClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
@ -400,18 +396,20 @@ gst_md5sink_class_init (GstMD5SinkClass *klass)
|
|||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_md5sink_get_property);
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MD5,
|
||||
g_param_spec_string ("md5", "md5", "current value of the md5 sum",
|
||||
"", G_PARAM_READABLE));
|
||||
g_param_spec_string ("md5", "md5", "current value of the md5 sum",
|
||||
"", G_PARAM_READABLE));
|
||||
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_md5sink_change_state);
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_md5sink_change_state);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_md5sink_init (GstMD5Sink *md5sink)
|
||||
static void
|
||||
gst_md5sink_init (GstMD5Sink * md5sink)
|
||||
{
|
||||
GstPad *pad;
|
||||
pad = gst_pad_new_from_template (gst_static_pad_template_get (
|
||||
&md5_sink_template), "sink");
|
||||
|
||||
pad =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&md5_sink_template), "sink");
|
||||
gst_element_add_pad (GST_ELEMENT (md5sink), pad);
|
||||
gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_md5sink_chain));
|
||||
|
||||
|
@ -419,15 +417,15 @@ gst_md5sink_init (GstMD5Sink *md5sink)
|
|||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_md5sink_change_state (GstElement *element)
|
||||
gst_md5sink_change_state (GstElement * element)
|
||||
{
|
||||
GstMD5Sink *sink;
|
||||
|
||||
|
||||
/* element check */
|
||||
sink = GST_MD5SINK (element);
|
||||
|
||||
g_return_val_if_fail (GST_IS_MD5SINK (sink), GST_STATE_FAILURE);
|
||||
|
||||
|
||||
switch (GST_STATE_TRANSITION (element)) {
|
||||
case GST_STATE_READY_TO_PAUSED:
|
||||
md5_init_ctx (sink);
|
||||
|
@ -440,38 +438,39 @@ gst_md5sink_change_state (GstElement *element)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if ((GST_ELEMENT_CLASS (parent_class)->change_state))
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
|
||||
|
||||
return GST_STATE_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_md5sink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_md5sink_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstMD5Sink *sink;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_MD5SINK (object));
|
||||
|
||||
|
||||
sink = GST_MD5SINK (object);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_MD5:
|
||||
{
|
||||
/* you could actually get a value for the current md5.
|
||||
* This is currently disabled.
|
||||
* md5_read_ctx (sink, sink->md5); */
|
||||
/* md5 is a guchar[16] */
|
||||
int i;
|
||||
guchar *md5string = g_malloc0 (33);
|
||||
{
|
||||
/* you could actually get a value for the current md5.
|
||||
* This is currently disabled.
|
||||
* md5_read_ctx (sink, sink->md5); */
|
||||
/* md5 is a guchar[16] */
|
||||
int i;
|
||||
guchar *md5string = g_malloc0 (33);
|
||||
|
||||
for (i = 0; i < 16; ++i)
|
||||
sprintf (md5string + i * 2, "%02x", sink->md5[i]);
|
||||
g_value_set_string (value, md5string);
|
||||
g_free (md5string);
|
||||
}
|
||||
for (i = 0; i < 16; ++i)
|
||||
sprintf (md5string + i * 2, "%02x", sink->md5[i]);
|
||||
g_value_set_string (value, md5string);
|
||||
g_free (md5string);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
@ -479,8 +478,8 @@ gst_md5sink_get_property (GObject *object, guint prop_id, GValue *value, GParamS
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_md5sink_chain (GstPad *pad, GstData *_data)
|
||||
static void
|
||||
gst_md5sink_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
GstBuffer *buf = GST_BUFFER (_data);
|
||||
GstMD5Sink *md5sink;
|
||||
|
@ -491,11 +490,9 @@ gst_md5sink_chain (GstPad *pad, GstData *_data)
|
|||
|
||||
md5sink = GST_MD5SINK (gst_pad_get_parent (pad));
|
||||
|
||||
if (GST_IS_BUFFER (buf))
|
||||
{
|
||||
if (GST_IS_BUFFER (buf)) {
|
||||
md5_process_bytes (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), md5sink);
|
||||
}
|
||||
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GST_TYPE_MD5SINK \
|
||||
(gst_md5sink_get_type())
|
||||
#define GST_MD5SINK(obj) \
|
||||
|
@ -40,11 +38,11 @@ G_BEGIN_DECLS
|
|||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MD5SINK))
|
||||
#define GST_IS_MD5SINK_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MD5SINK))
|
||||
|
||||
typedef struct _GstMD5Sink GstMD5Sink;
|
||||
typedef struct _GstMD5SinkClass GstMD5SinkClass;
|
||||
|
||||
struct _GstMD5Sink {
|
||||
struct _GstMD5Sink
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
/* md5 information */
|
||||
|
@ -56,21 +54,21 @@ struct _GstMD5Sink {
|
|||
guint32 total[2];
|
||||
guint32 buflen;
|
||||
gchar buffer[128];
|
||||
|
||||
|
||||
/* latest md5 */
|
||||
guchar md5[16];
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct _GstMD5SinkClass {
|
||||
struct _GstMD5SinkClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
|
||||
};
|
||||
|
||||
GType gst_md5sink_get_type (void);
|
||||
GType gst_md5sink_get_type (void);
|
||||
|
||||
gboolean gst_md5sink_factory_init (GstElementFactory *factory);
|
||||
gboolean gst_md5sink_factory_init (GstElementFactory * factory);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_MD5SINK_H__ */
|
||||
|
|
|
@ -40,20 +40,21 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_multifilesrc_debug);
|
||||
#define GST_CAT_DEFAULT gst_multifilesrc_debug
|
||||
|
||||
GstElementDetails gst_multifilesrc_details = GST_ELEMENT_DETAILS (
|
||||
"Multi File Source",
|
||||
"Source/File",
|
||||
"Read from multiple files in order",
|
||||
"Dominic Ludlam <dom@openfx.org>"
|
||||
);
|
||||
GstElementDetails gst_multifilesrc_details =
|
||||
GST_ELEMENT_DETAILS ("Multi File Source",
|
||||
"Source/File",
|
||||
"Read from multiple files in order",
|
||||
"Dominic Ludlam <dom@openfx.org>");
|
||||
|
||||
/* FileSrc signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
NEW_FILE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_LOCATIONS
|
||||
};
|
||||
|
@ -61,18 +62,24 @@ enum {
|
|||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_multifilesrc_debug, "multifilesrc", 0, "multifilesrc element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstMultiFileSrc, gst_multifilesrc, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
GST_BOILERPLATE_FULL (GstMultiFileSrc, gst_multifilesrc, GstElement,
|
||||
GST_TYPE_ELEMENT, _do_init);
|
||||
|
||||
static void gst_multifilesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
static void gst_multifilesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||
static void gst_multifilesrc_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_multifilesrc_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstData *gst_multifilesrc_get (GstPad * pad);
|
||||
|
||||
static GstData * gst_multifilesrc_get (GstPad *pad);
|
||||
/*static GstBuffer * gst_multifilesrc_get_region (GstPad *pad,GstRegionType type,guint64 offset,guint64 len);*/
|
||||
|
||||
static GstElementStateReturn gst_multifilesrc_change_state (GstElement *element);
|
||||
static GstElementStateReturn gst_multifilesrc_change_state (GstElement *
|
||||
element);
|
||||
|
||||
static gboolean gst_multifilesrc_open_file (GstMultiFileSrc *src, GstPad *srcpad);
|
||||
static void gst_multifilesrc_close_file (GstMultiFileSrc *src);
|
||||
static gboolean gst_multifilesrc_open_file (GstMultiFileSrc * src,
|
||||
GstPad * srcpad);
|
||||
static void gst_multifilesrc_close_file (GstMultiFileSrc * src);
|
||||
|
||||
static guint gst_multifilesrc_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
@ -80,28 +87,25 @@ static void
|
|||
gst_multifilesrc_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &gst_multifilesrc_details);
|
||||
}
|
||||
static void
|
||||
gst_multifilesrc_class_init (GstMultiFileSrcClass *klass)
|
||||
gst_multifilesrc_class_init (GstMultiFileSrcClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
||||
gobject_class = (GObjectClass*)klass;
|
||||
gstelement_class = (GstElementClass*)klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
|
||||
gst_multifilesrc_signals[NEW_FILE] =
|
||||
g_signal_new ("new-file", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstMultiFileSrcClass, new_file), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1,
|
||||
G_TYPE_STRING);
|
||||
g_signal_new ("new-file", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstMultiFileSrcClass, new_file), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
|
||||
|
||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_LOCATIONS,
|
||||
g_param_spec_pointer("locations","locations","locations",
|
||||
G_PARAM_READWRITE)); /* CHECKME */
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATIONS, g_param_spec_pointer ("locations", "locations", "locations", G_PARAM_READWRITE)); /* CHECKME */
|
||||
|
||||
gobject_class->set_property = gst_multifilesrc_set_property;
|
||||
gobject_class->get_property = gst_multifilesrc_get_property;
|
||||
|
@ -110,12 +114,12 @@ gst_multifilesrc_class_init (GstMultiFileSrcClass *klass)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_multifilesrc_init (GstMultiFileSrc *multifilesrc)
|
||||
gst_multifilesrc_init (GstMultiFileSrc * multifilesrc)
|
||||
{
|
||||
/* GST_FLAG_SET (filesrc, GST_SRC_); */
|
||||
|
||||
multifilesrc->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_pad_set_get_function (multifilesrc->srcpad,gst_multifilesrc_get);
|
||||
gst_pad_set_get_function (multifilesrc->srcpad, gst_multifilesrc_get);
|
||||
/* gst_pad_set_getregion_function (multifilesrc->srcpad,gst_multifilesrc_get_region); */
|
||||
gst_element_add_pad (GST_ELEMENT (multifilesrc), multifilesrc->srcpad);
|
||||
|
||||
|
@ -128,7 +132,8 @@ gst_multifilesrc_init (GstMultiFileSrc *multifilesrc)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_multifilesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
gst_multifilesrc_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstMultiFileSrc *src;
|
||||
|
||||
|
@ -144,11 +149,11 @@ gst_multifilesrc_set_property (GObject *object, guint prop_id, const GValue *val
|
|||
|
||||
/* clear the filename if we get a NULL */
|
||||
if (g_value_get_pointer (value) == NULL) {
|
||||
gst_element_set_state (GST_ELEMENT (object), GST_STATE_NULL);
|
||||
src->listptr = NULL;
|
||||
/* otherwise set the new filenames */
|
||||
gst_element_set_state (GST_ELEMENT (object), GST_STATE_NULL);
|
||||
src->listptr = NULL;
|
||||
/* otherwise set the new filenames */
|
||||
} else {
|
||||
src->listptr = g_value_get_pointer (value);
|
||||
src->listptr = g_value_get_pointer (value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -157,7 +162,8 @@ gst_multifilesrc_set_property (GObject *object, guint prop_id, const GValue *val
|
|||
}
|
||||
|
||||
static void
|
||||
gst_multifilesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
gst_multifilesrc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstMultiFileSrc *src;
|
||||
|
||||
|
@ -183,7 +189,7 @@ gst_multifilesrc_get_property (GObject *object, guint prop_id, GValue *value, GP
|
|||
* Push a new buffer from the filesrc at the current offset.
|
||||
*/
|
||||
static GstData *
|
||||
gst_multifilesrc_get (GstPad *pad)
|
||||
gst_multifilesrc_get (GstPad * pad)
|
||||
{
|
||||
GstMultiFileSrc *src;
|
||||
GstBuffer *buf;
|
||||
|
@ -193,7 +199,7 @@ gst_multifilesrc_get (GstPad *pad)
|
|||
src = GST_MULTIFILESRC (gst_pad_get_parent (pad));
|
||||
|
||||
if (GST_FLAG_IS_SET (src, GST_MULTIFILESRC_OPEN))
|
||||
gst_multifilesrc_close_file(src);
|
||||
gst_multifilesrc_close_file (src);
|
||||
|
||||
if (!src->listptr) {
|
||||
return GST_DATA (gst_event_new (GST_EVENT_EOS));
|
||||
|
@ -203,11 +209,11 @@ gst_multifilesrc_get (GstPad *pad)
|
|||
src->currentfilename = (gchar *) list->data;
|
||||
src->listptr = src->listptr->next;
|
||||
|
||||
if (!gst_multifilesrc_open_file(src, pad))
|
||||
return NULL;
|
||||
if (!gst_multifilesrc_open_file (src, pad))
|
||||
return NULL;
|
||||
|
||||
/* emitted after the open, as the user may free the list and string from here*/
|
||||
g_signal_emit(G_OBJECT(src), gst_multifilesrc_signals[NEW_FILE], 0, list);
|
||||
/* emitted after the open, as the user may free the list and string from here */
|
||||
g_signal_emit (G_OBJECT (src), gst_multifilesrc_signals[NEW_FILE], 0, list);
|
||||
|
||||
/* create the buffer */
|
||||
/* FIXME: should eventually use a bufferpool for this */
|
||||
|
@ -231,24 +237,23 @@ gst_multifilesrc_get (GstPad *pad)
|
|||
}
|
||||
|
||||
/* open the file and mmap it, necessary to go to READY state */
|
||||
static
|
||||
gboolean gst_multifilesrc_open_file (GstMultiFileSrc *src, GstPad *srcpad)
|
||||
static gboolean
|
||||
gst_multifilesrc_open_file (GstMultiFileSrc * src, GstPad * srcpad)
|
||||
{
|
||||
g_return_val_if_fail (!GST_FLAG_IS_SET (src, GST_MULTIFILESRC_OPEN), FALSE);
|
||||
|
||||
if (src->currentfilename == NULL || src->currentfilename[0] == '\0')
|
||||
{
|
||||
if (src->currentfilename == NULL || src->currentfilename[0] == '\0') {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
|
||||
(_("No file name specified for reading.")), (NULL));
|
||||
(_("No file name specified for reading.")), (NULL));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* open the file */
|
||||
src->fd = open ((const char *) src->currentfilename, O_RDONLY);
|
||||
if (src->fd < 0) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
||||
(_("Could not open file \"%s\" for reading."), src->currentfilename),
|
||||
GST_ERROR_SYSTEM);
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
||||
(_("Could not open file \"%s\" for reading."), src->currentfilename),
|
||||
GST_ERROR_SYSTEM);
|
||||
return FALSE;
|
||||
|
||||
} else {
|
||||
|
@ -257,12 +262,12 @@ gboolean gst_multifilesrc_open_file (GstMultiFileSrc *src, GstPad *srcpad)
|
|||
lseek (src->fd, 0, SEEK_SET);
|
||||
/* map the file into memory */
|
||||
src->map = mmap (NULL, src->size, PROT_READ, MAP_SHARED, src->fd, 0);
|
||||
madvise (src->map,src->size, 2);
|
||||
madvise (src->map, src->size, 2);
|
||||
/* collapse state if that failed */
|
||||
if (src->map == NULL) {
|
||||
close (src->fd);
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, TOO_LAZY, (NULL),
|
||||
("mmap call failed."));
|
||||
("mmap call failed."));
|
||||
return FALSE;
|
||||
}
|
||||
GST_FLAG_SET (src, GST_MULTIFILESRC_OPEN);
|
||||
|
@ -273,7 +278,7 @@ gboolean gst_multifilesrc_open_file (GstMultiFileSrc *src, GstPad *srcpad)
|
|||
|
||||
/* unmap and close the file */
|
||||
static void
|
||||
gst_multifilesrc_close_file (GstMultiFileSrc *src)
|
||||
gst_multifilesrc_close_file (GstMultiFileSrc * src)
|
||||
{
|
||||
g_return_if_fail (GST_FLAG_IS_SET (src, GST_MULTIFILESRC_OPEN));
|
||||
|
||||
|
@ -291,7 +296,7 @@ gst_multifilesrc_close_file (GstMultiFileSrc *src)
|
|||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_multifilesrc_change_state (GstElement *element)
|
||||
gst_multifilesrc_change_state (GstElement * element)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_MULTIFILESRC (element), GST_STATE_FAILURE);
|
||||
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GST_TYPE_MULTIFILESRC \
|
||||
(gst_multifilesrc_get_type())
|
||||
#define GST_MULTIFILESRC(obj) \
|
||||
|
@ -39,41 +37,42 @@ G_BEGIN_DECLS
|
|||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MULTIFILESRC))
|
||||
#define GST_IS_MULTIFILESRC_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MULTIFILESRC))
|
||||
typedef enum
|
||||
{
|
||||
GST_MULTIFILESRC_OPEN = GST_ELEMENT_FLAG_LAST,
|
||||
|
||||
typedef enum {
|
||||
GST_MULTIFILESRC_OPEN = GST_ELEMENT_FLAG_LAST,
|
||||
|
||||
GST_MULTIFILESRC_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2
|
||||
GST_MULTIFILESRC_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2
|
||||
} GstMultiFileSrcFlags;
|
||||
|
||||
typedef struct _GstMultiFileSrc GstMultiFileSrc;
|
||||
typedef struct _GstMultiFileSrcClass GstMultiFileSrcClass;
|
||||
|
||||
struct _GstMultiFileSrc {
|
||||
struct _GstMultiFileSrc
|
||||
{
|
||||
GstElement element;
|
||||
/* pads */
|
||||
GstPad *srcpad;
|
||||
|
||||
/* current file details */
|
||||
gchar *currentfilename;
|
||||
gchar *currentfilename;
|
||||
GSList *listptr;
|
||||
|
||||
/* mapping parameters */
|
||||
gint fd;
|
||||
gulong size; /* how long is the file? */
|
||||
guchar *map; /* where the file is mapped to */
|
||||
gulong size; /* how long is the file? */
|
||||
guchar *map; /* where the file is mapped to */
|
||||
|
||||
gboolean new_seek;
|
||||
};
|
||||
|
||||
struct _GstMultiFileSrcClass {
|
||||
struct _GstMultiFileSrcClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
|
||||
void (*new_file) (GstMultiFileSrc *multifilesrc, gchar *newfilename);
|
||||
void (*new_file) (GstMultiFileSrc * multifilesrc, gchar * newfilename);
|
||||
};
|
||||
|
||||
GType gst_multifilesrc_get_type(void);
|
||||
GType gst_multifilesrc_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_MULTIFILESRC_H__ */
|
||||
|
|
|
@ -40,22 +40,22 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_pipefilter_debug);
|
||||
#define GST_CAT_DEFAULT gst_pipefilter_debug
|
||||
|
||||
GstElementDetails gst_pipefilter_details = GST_ELEMENT_DETAILS (
|
||||
"Pipefilter",
|
||||
"Filter",
|
||||
"Interoperate with an external program using stdin and stdout",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>, "
|
||||
"Wim Taymans <wim.taymans@chello.be>"
|
||||
);
|
||||
GstElementDetails gst_pipefilter_details = GST_ELEMENT_DETAILS ("Pipefilter",
|
||||
"Filter",
|
||||
"Interoperate with an external program using stdin and stdout",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>, "
|
||||
"Wim Taymans <wim.taymans@chello.be>");
|
||||
|
||||
|
||||
/* Pipefilter signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_COMMAND
|
||||
};
|
||||
|
@ -64,46 +64,47 @@ enum {
|
|||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_pipefilter_debug, "pipefilter", 0, "pipefilter element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstPipefilter, gst_pipefilter, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
GST_BOILERPLATE_FULL (GstPipefilter, gst_pipefilter, GstElement,
|
||||
GST_TYPE_ELEMENT, _do_init);
|
||||
|
||||
static void gst_pipefilter_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
static void gst_pipefilter_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||
static void gst_pipefilter_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_pipefilter_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstData* gst_pipefilter_get (GstPad *pad);
|
||||
static void gst_pipefilter_chain (GstPad *pad, GstData *_data);
|
||||
static gboolean gst_pipefilter_handle_event (GstPad *pad, GstEvent *event);
|
||||
static GstData *gst_pipefilter_get (GstPad * pad);
|
||||
static void gst_pipefilter_chain (GstPad * pad, GstData * _data);
|
||||
static gboolean gst_pipefilter_handle_event (GstPad * pad, GstEvent * event);
|
||||
|
||||
static GstElementStateReturn gst_pipefilter_change_state (GstElement *element);
|
||||
static GstElementStateReturn gst_pipefilter_change_state (GstElement * element);
|
||||
|
||||
static void
|
||||
gst_pipefilter_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &gst_pipefilter_details);
|
||||
}
|
||||
static void
|
||||
gst_pipefilter_class_init (GstPipefilterClass *klass)
|
||||
static void
|
||||
gst_pipefilter_class_init (GstPipefilterClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
||||
gobject_class = (GObjectClass*)klass;
|
||||
gstelement_class = (GstElementClass*)klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
|
||||
gobject_class->set_property = gst_pipefilter_set_property;
|
||||
gobject_class->set_property = gst_pipefilter_set_property;
|
||||
gobject_class->get_property = gst_pipefilter_get_property;
|
||||
|
||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_COMMAND,
|
||||
g_param_spec_string("command","command","command",
|
||||
NULL, G_PARAM_READWRITE)); /* CHECKME */
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COMMAND, g_param_spec_string ("command", "command", "command", NULL, G_PARAM_READWRITE)); /* CHECKME */
|
||||
|
||||
gstelement_class->change_state = gst_pipefilter_change_state;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_pipefilter_init (GstPipefilter *pipefilter)
|
||||
gst_pipefilter_init (GstPipefilter * pipefilter)
|
||||
{
|
||||
GST_FLAG_SET (pipefilter, GST_ELEMENT_DECOUPLED);
|
||||
|
||||
|
@ -122,7 +123,7 @@ gst_pipefilter_init (GstPipefilter *pipefilter)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_pipefilter_handle_event (GstPad *pad, GstEvent *event)
|
||||
gst_pipefilter_handle_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstPipefilter *pipefilter;
|
||||
|
||||
|
@ -133,9 +134,9 @@ gst_pipefilter_handle_event (GstPad *pad, GstEvent *event)
|
|||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_EOS:
|
||||
if (close (pipefilter->fdin[1]) < 0)
|
||||
perror("close");
|
||||
perror ("close");
|
||||
if (close (pipefilter->fdout[0]) < 0)
|
||||
perror("close");
|
||||
perror ("close");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -146,8 +147,8 @@ gst_pipefilter_handle_event (GstPad *pad, GstEvent *event)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static GstData*
|
||||
gst_pipefilter_get (GstPad *pad)
|
||||
static GstData *
|
||||
gst_pipefilter_get (GstPad * pad)
|
||||
{
|
||||
GstPipefilter *pipefilter;
|
||||
GstBuffer *newbuf;
|
||||
|
@ -157,16 +158,18 @@ gst_pipefilter_get (GstPad *pad)
|
|||
|
||||
/* create the buffer */
|
||||
/* FIXME: should eventually use a bufferpool for this */
|
||||
newbuf = gst_buffer_new();
|
||||
g_return_val_if_fail(newbuf, NULL);
|
||||
newbuf = gst_buffer_new ();
|
||||
g_return_val_if_fail (newbuf, NULL);
|
||||
|
||||
/* allocate the space for the buffer data */
|
||||
GST_BUFFER_DATA(newbuf) = g_malloc(pipefilter->bytes_per_read);
|
||||
g_return_val_if_fail(GST_BUFFER_DATA(newbuf) != NULL, NULL);
|
||||
GST_BUFFER_DATA (newbuf) = g_malloc (pipefilter->bytes_per_read);
|
||||
g_return_val_if_fail (GST_BUFFER_DATA (newbuf) != NULL, NULL);
|
||||
|
||||
/* read it in from the file */
|
||||
GST_DEBUG ("attemting to read %ld bytes", pipefilter->bytes_per_read);
|
||||
readbytes = read(pipefilter->fdout[0], GST_BUFFER_DATA(newbuf), pipefilter->bytes_per_read);
|
||||
readbytes =
|
||||
read (pipefilter->fdout[0], GST_BUFFER_DATA (newbuf),
|
||||
pipefilter->bytes_per_read);
|
||||
GST_DEBUG ("read %ld bytes", readbytes);
|
||||
if (readbytes < 0) {
|
||||
GST_ELEMENT_ERROR (pipefilter, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
|
||||
|
@ -178,15 +181,15 @@ gst_pipefilter_get (GstPad *pad)
|
|||
|
||||
}
|
||||
|
||||
GST_BUFFER_OFFSET(newbuf) = pipefilter->curoffset;
|
||||
GST_BUFFER_SIZE(newbuf) = readbytes;
|
||||
GST_BUFFER_OFFSET (newbuf) = pipefilter->curoffset;
|
||||
GST_BUFFER_SIZE (newbuf) = readbytes;
|
||||
pipefilter->curoffset += readbytes;
|
||||
|
||||
return GST_DATA (newbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_pipefilter_chain (GstPad *pad,GstData *_data)
|
||||
gst_pipefilter_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
GstPipefilter *pipefilter;
|
||||
|
@ -194,8 +197,8 @@ gst_pipefilter_chain (GstPad *pad,GstData *_data)
|
|||
guchar *data;
|
||||
gulong size;
|
||||
|
||||
g_return_if_fail(pad != NULL);
|
||||
g_return_if_fail(GST_IS_PAD(pad));
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_PAD (pad));
|
||||
|
||||
if (GST_IS_EVENT (_data)) {
|
||||
gst_pipefilter_handle_event (pad, GST_EVENT (_data));
|
||||
|
@ -205,32 +208,33 @@ gst_pipefilter_chain (GstPad *pad,GstData *_data)
|
|||
pipefilter = GST_PIPEFILTER (gst_pad_get_parent (pad));
|
||||
|
||||
buf = GST_BUFFER (_data);
|
||||
data = GST_BUFFER_DATA(buf);
|
||||
size = GST_BUFFER_SIZE(buf);
|
||||
data = GST_BUFFER_DATA (buf);
|
||||
size = GST_BUFFER_SIZE (buf);
|
||||
|
||||
GST_DEBUG ("attemting to write %ld bytes", size);
|
||||
writebytes = write(pipefilter->fdin[1],data,size);
|
||||
writebytes = write (pipefilter->fdin[1], data, size);
|
||||
GST_DEBUG ("written %ld bytes", writebytes);
|
||||
if (writebytes < 0) {
|
||||
GST_ELEMENT_ERROR (pipefilter, RESOURCE, WRITE, (NULL), GST_ERROR_SYSTEM);
|
||||
return;
|
||||
}
|
||||
gst_buffer_unref(buf);
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_pipefilter_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
gst_pipefilter_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstPipefilter *pipefilter;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail(GST_IS_PIPEFILTER(object));
|
||||
pipefilter = GST_PIPEFILTER(object);
|
||||
g_return_if_fail (GST_IS_PIPEFILTER (object));
|
||||
pipefilter = GST_PIPEFILTER (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_COMMAND:
|
||||
pipefilter->orig_command = g_strdup(g_value_get_string (value));
|
||||
pipefilter->command = g_strsplit(g_value_get_string (value), " ", 0);
|
||||
pipefilter->orig_command = g_strdup (g_value_get_string (value));
|
||||
pipefilter->command = g_strsplit (g_value_get_string (value), " ", 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -238,13 +242,14 @@ gst_pipefilter_set_property (GObject *object, guint prop_id, const GValue *value
|
|||
}
|
||||
|
||||
static void
|
||||
gst_pipefilter_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
gst_pipefilter_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstPipefilter *pipefilter;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail(GST_IS_PIPEFILTER(object));
|
||||
pipefilter = GST_PIPEFILTER(object);
|
||||
g_return_if_fail (GST_IS_PIPEFILTER (object));
|
||||
pipefilter = GST_PIPEFILTER (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_COMMAND:
|
||||
|
@ -258,78 +263,75 @@ gst_pipefilter_get_property (GObject *object, guint prop_id, GValue *value, GPar
|
|||
|
||||
/* open the file, necessary to go to RUNNING state */
|
||||
static gboolean
|
||||
gst_pipefilter_open_file (GstPipefilter *src)
|
||||
gst_pipefilter_open_file (GstPipefilter * src)
|
||||
{
|
||||
g_return_val_if_fail(!GST_FLAG_IS_SET(src,GST_PIPEFILTER_OPEN), FALSE);
|
||||
g_return_val_if_fail (!GST_FLAG_IS_SET (src, GST_PIPEFILTER_OPEN), FALSE);
|
||||
|
||||
pipe(src->fdin);
|
||||
pipe(src->fdout);
|
||||
pipe (src->fdin);
|
||||
pipe (src->fdout);
|
||||
|
||||
if((src->childpid = fork()) == -1)
|
||||
{
|
||||
if ((src->childpid = fork ()) == -1) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, TOO_LAZY, (NULL), GST_ERROR_SYSTEM);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(src->childpid == 0)
|
||||
{
|
||||
close(src->fdin[1]);
|
||||
close(src->fdout[0]);
|
||||
if (src->childpid == 0) {
|
||||
close (src->fdin[1]);
|
||||
close (src->fdout[0]);
|
||||
/* child */
|
||||
dup2(src->fdin[0], STDIN_FILENO); /* set the childs input stream */
|
||||
dup2(src->fdout[1], STDOUT_FILENO); /* set the childs output stream */
|
||||
execvp(src->command[0], &src->command[0]);
|
||||
dup2 (src->fdin[0], STDIN_FILENO); /* set the childs input stream */
|
||||
dup2 (src->fdout[1], STDOUT_FILENO); /* set the childs output stream */
|
||||
execvp (src->command[0], &src->command[0]);
|
||||
/* will only be reached if execvp has an error */
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, TOO_LAZY, (NULL), GST_ERROR_SYSTEM);
|
||||
return FALSE;
|
||||
|
||||
|
||||
} else {
|
||||
close (src->fdin[0]);
|
||||
close (src->fdout[1]);
|
||||
}
|
||||
else {
|
||||
close(src->fdin[0]);
|
||||
close(src->fdout[1]);
|
||||
}
|
||||
|
||||
GST_FLAG_SET(src,GST_PIPEFILTER_OPEN);
|
||||
|
||||
GST_FLAG_SET (src, GST_PIPEFILTER_OPEN);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* close the file */
|
||||
static void
|
||||
gst_pipefilter_close_file (GstPipefilter *src)
|
||||
gst_pipefilter_close_file (GstPipefilter * src)
|
||||
{
|
||||
g_return_if_fail(GST_FLAG_IS_SET(src,GST_PIPEFILTER_OPEN));
|
||||
g_return_if_fail (GST_FLAG_IS_SET (src, GST_PIPEFILTER_OPEN));
|
||||
|
||||
/* close the file */
|
||||
close(src->fdout[0]);
|
||||
close(src->fdout[1]);
|
||||
close(src->fdin[0]);
|
||||
close(src->fdin[1]);
|
||||
close (src->fdout[0]);
|
||||
close (src->fdout[1]);
|
||||
close (src->fdin[0]);
|
||||
close (src->fdin[1]);
|
||||
|
||||
/* zero out a lot of our state */
|
||||
src->curoffset = 0;
|
||||
src->seq = 0;
|
||||
|
||||
GST_FLAG_UNSET(src,GST_PIPEFILTER_OPEN);
|
||||
GST_FLAG_UNSET (src, GST_PIPEFILTER_OPEN);
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_pipefilter_change_state (GstElement *element)
|
||||
gst_pipefilter_change_state (GstElement * element)
|
||||
{
|
||||
g_return_val_if_fail(GST_IS_PIPEFILTER(element), FALSE);
|
||||
g_return_val_if_fail (GST_IS_PIPEFILTER (element), FALSE);
|
||||
|
||||
/* if going down into NULL state, close the file if it's open */
|
||||
if (GST_STATE_PENDING(element) == GST_STATE_NULL) {
|
||||
if (GST_FLAG_IS_SET(element,GST_PIPEFILTER_OPEN))
|
||||
gst_pipefilter_close_file(GST_PIPEFILTER(element));
|
||||
/* otherwise (READY or higher) we need to open the file */
|
||||
/* if going down into NULL state, close the file if it's open */
|
||||
if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
|
||||
if (GST_FLAG_IS_SET (element, GST_PIPEFILTER_OPEN))
|
||||
gst_pipefilter_close_file (GST_PIPEFILTER (element));
|
||||
/* otherwise (READY or higher) we need to open the file */
|
||||
} else {
|
||||
if (!GST_FLAG_IS_SET(element,GST_PIPEFILTER_OPEN)) {
|
||||
if (!gst_pipefilter_open_file(GST_PIPEFILTER(element)))
|
||||
return GST_STATE_FAILURE;
|
||||
if (!GST_FLAG_IS_SET (element, GST_PIPEFILTER_OPEN)) {
|
||||
if (!gst_pipefilter_open_file (GST_PIPEFILTER (element)))
|
||||
return GST_STATE_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (GST_ELEMENT_CLASS(parent_class)->change_state)
|
||||
return GST_ELEMENT_CLASS(parent_class)->change_state(element);
|
||||
|
||||
if (GST_ELEMENT_CLASS (parent_class)->change_state)
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
return GST_STATE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GST_TYPE_PIPEFILTER \
|
||||
(gst_pipefilter_get_type())
|
||||
#define GST_PIPEFILTER(obj) \
|
||||
|
@ -40,17 +38,18 @@ G_BEGIN_DECLS
|
|||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PIPEFILTER))
|
||||
#define GST_IS_PIPEFILTER_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PIPEFILTER))
|
||||
typedef enum
|
||||
{
|
||||
GST_PIPEFILTER_OPEN = GST_ELEMENT_FLAG_LAST,
|
||||
|
||||
typedef enum {
|
||||
GST_PIPEFILTER_OPEN = GST_ELEMENT_FLAG_LAST,
|
||||
|
||||
GST_PIPEFILTER_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2
|
||||
GST_PIPEFILTER_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2
|
||||
} GstPipeFilterFlags;
|
||||
|
||||
typedef struct _GstPipefilter GstPipefilter;
|
||||
typedef struct _GstPipefilterClass GstPipefilterClass;
|
||||
|
||||
struct _GstPipefilter {
|
||||
struct _GstPipefilter
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
GstPad *sinkpad;
|
||||
|
@ -62,20 +61,20 @@ struct _GstPipefilter {
|
|||
/* fd */
|
||||
gint fdout[2];
|
||||
gint fdin[2];
|
||||
pid_t childpid;
|
||||
pid_t childpid;
|
||||
|
||||
gulong curoffset; /* current offset in file */
|
||||
gulong bytes_per_read; /* bytes per read */
|
||||
gulong curoffset; /* current offset in file */
|
||||
gulong bytes_per_read; /* bytes per read */
|
||||
|
||||
gulong seq; /* buffer sequence number */
|
||||
gulong seq; /* buffer sequence number */
|
||||
};
|
||||
|
||||
struct _GstPipefilterClass {
|
||||
struct _GstPipefilterClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_pipefilter_get_type(void);
|
||||
GType gst_pipefilter_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_PIPEFILTER_H__ */
|
||||
|
|
|
@ -32,21 +32,21 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_shaper_debug);
|
||||
#define GST_CAT_DEFAULT gst_shaper_debug
|
||||
|
||||
GstElementDetails gst_shaper_details = GST_ELEMENT_DETAILS (
|
||||
"Shaper",
|
||||
"Generic",
|
||||
"Synchronizes streams on different pads",
|
||||
"Wim Taymans <wim.taymans@chello.be>"
|
||||
);
|
||||
GstElementDetails gst_shaper_details = GST_ELEMENT_DETAILS ("Shaper",
|
||||
"Generic",
|
||||
"Synchronizes streams on different pads",
|
||||
"Wim Taymans <wim.taymans@chello.be>");
|
||||
|
||||
|
||||
/* Shaper signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_POLICY,
|
||||
ARG_SILENT,
|
||||
|
@ -55,24 +55,20 @@ enum {
|
|||
|
||||
typedef struct
|
||||
{
|
||||
GstPad *sinkpad;
|
||||
GstPad *srcpad;
|
||||
GstBuffer *buffer;
|
||||
GstPad *sinkpad;
|
||||
GstPad *srcpad;
|
||||
GstBuffer *buffer;
|
||||
} GstShaperConnection;
|
||||
|
||||
GstStaticPadTemplate shaper_src_template = GST_STATIC_PAD_TEMPLATE (
|
||||
"src%d",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_SOMETIMES,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
GstStaticPadTemplate shaper_src_template = GST_STATIC_PAD_TEMPLATE ("src%d",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_SOMETIMES,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
GstStaticPadTemplate shaper_sink_template = GST_STATIC_PAD_TEMPLATE (
|
||||
"sink%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
GstStaticPadTemplate shaper_sink_template = GST_STATIC_PAD_TEMPLATE ("sink%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
#define GST_TYPE_SHAPER_POLICY (gst_shaper_policy_get_type())
|
||||
static GType
|
||||
|
@ -80,12 +76,13 @@ gst_shaper_policy_get_type (void)
|
|||
{
|
||||
static GType shaper_policy_type = 0;
|
||||
static GEnumValue shaper_policy[] = {
|
||||
{ SHAPER_POLICY_TIMESTAMPS, "1", "sync on timestamps"},
|
||||
{ SHAPER_POLICY_BUFFERSIZE, "2", "sync on buffer size"},
|
||||
{SHAPER_POLICY_TIMESTAMPS, "1", "sync on timestamps"},
|
||||
{SHAPER_POLICY_BUFFERSIZE, "2", "sync on buffer size"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
if (!shaper_policy_type) {
|
||||
shaper_policy_type = g_enum_register_static ("GstShaperPolicy", shaper_policy);
|
||||
shaper_policy_type =
|
||||
g_enum_register_static ("GstShaperPolicy", shaper_policy);
|
||||
}
|
||||
return shaper_policy_type;
|
||||
}
|
||||
|
@ -93,24 +90,25 @@ gst_shaper_policy_get_type (void)
|
|||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_shaper_debug, "shaper", 0, "shaper element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstShaper, gst_shaper, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
GST_BOILERPLATE_FULL (GstShaper, gst_shaper, GstElement, GST_TYPE_ELEMENT,
|
||||
_do_init);
|
||||
|
||||
static void gst_shaper_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_shaper_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
static void gst_shaper_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_shaper_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstPad* gst_shaper_request_new_pad (GstElement *element, GstPadTemplate *templ,
|
||||
const gchar *unused);
|
||||
static GstPad *gst_shaper_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * unused);
|
||||
|
||||
static void gst_shaper_loop (GstElement *element);
|
||||
static void gst_shaper_loop (GstElement * element);
|
||||
|
||||
|
||||
static void
|
||||
gst_shaper_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &gst_shaper_details);
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&shaper_src_template));
|
||||
|
@ -118,41 +116,43 @@ gst_shaper_base_init (gpointer g_class)
|
|||
gst_static_pad_template_get (&shaper_sink_template));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_shaper_class_init (GstShaperClass *klass)
|
||||
static void
|
||||
gst_shaper_class_init (GstShaperClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
||||
gobject_class = (GObjectClass*) klass;
|
||||
gstelement_class = (GstElementClass*) klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_POLICY,
|
||||
g_param_spec_enum ("policy", "Policy", "Shaper policy",
|
||||
GST_TYPE_SHAPER_POLICY, SHAPER_POLICY_TIMESTAMPS, G_PARAM_READWRITE));
|
||||
g_param_spec_enum ("policy", "Policy", "Shaper policy",
|
||||
GST_TYPE_SHAPER_POLICY, SHAPER_POLICY_TIMESTAMPS, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
|
||||
g_param_spec_boolean ("silent", "silent", "silent",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("silent", "silent", "silent",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
|
||||
g_param_spec_string ("last-message", "last-message", "last-message",
|
||||
NULL, G_PARAM_READABLE));
|
||||
g_param_spec_string ("last-message", "last-message", "last-message",
|
||||
NULL, G_PARAM_READABLE));
|
||||
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_shaper_set_property);
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_shaper_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_shaper_get_property);
|
||||
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_shaper_request_new_pad);
|
||||
gstelement_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_shaper_request_new_pad);
|
||||
}
|
||||
|
||||
static GstCaps*
|
||||
gst_shaper_getcaps (GstPad *pad)
|
||||
static GstCaps *
|
||||
gst_shaper_getcaps (GstPad * pad)
|
||||
{
|
||||
GstPad *otherpad;
|
||||
GstShaperConnection *connection;
|
||||
|
||||
connection = gst_pad_get_element_private (pad);
|
||||
|
||||
otherpad = (pad == connection->srcpad ? connection->sinkpad : connection->srcpad);
|
||||
otherpad =
|
||||
(pad == connection->srcpad ? connection->sinkpad : connection->srcpad);
|
||||
|
||||
if (GST_PAD_PEER (otherpad)) {
|
||||
return gst_pad_get_caps (GST_PAD_PEER (otherpad));
|
||||
|
@ -161,8 +161,8 @@ gst_shaper_getcaps (GstPad *pad)
|
|||
}
|
||||
}
|
||||
|
||||
static GList*
|
||||
gst_shaper_get_internal_link (GstPad *pad)
|
||||
static GList *
|
||||
gst_shaper_get_internal_link (GstPad * pad)
|
||||
{
|
||||
GList *res = NULL;
|
||||
GstShaperConnection *connection;
|
||||
|
@ -170,7 +170,8 @@ gst_shaper_get_internal_link (GstPad *pad)
|
|||
|
||||
connection = gst_pad_get_element_private (pad);
|
||||
|
||||
otherpad = (pad == connection->srcpad ? connection->sinkpad : connection->srcpad);
|
||||
otherpad =
|
||||
(pad == connection->srcpad ? connection->sinkpad : connection->srcpad);
|
||||
|
||||
res = g_list_prepend (res, otherpad);
|
||||
|
||||
|
@ -178,20 +179,21 @@ gst_shaper_get_internal_link (GstPad *pad)
|
|||
}
|
||||
|
||||
static GstPadLinkReturn
|
||||
gst_shaper_link (GstPad *pad, const GstCaps *caps)
|
||||
gst_shaper_link (GstPad * pad, const GstCaps * caps)
|
||||
{
|
||||
GstPad *otherpad;
|
||||
GstShaperConnection *connection;
|
||||
|
||||
connection = gst_pad_get_element_private (pad);
|
||||
|
||||
otherpad = (pad == connection->srcpad ? connection->sinkpad : connection->srcpad);
|
||||
otherpad =
|
||||
(pad == connection->srcpad ? connection->sinkpad : connection->srcpad);
|
||||
|
||||
return gst_pad_try_set_caps (otherpad, caps);
|
||||
}
|
||||
|
||||
static GstShaperConnection*
|
||||
gst_shaper_create_connection (GstShaper *shaper)
|
||||
static GstShaperConnection *
|
||||
gst_shaper_create_connection (GstShaper * shaper)
|
||||
{
|
||||
GstShaperConnection *connection;
|
||||
gchar *padname;
|
||||
|
@ -201,21 +203,25 @@ gst_shaper_create_connection (GstShaper *shaper)
|
|||
connection = g_new0 (GstShaperConnection, 1);
|
||||
|
||||
padname = g_strdup_printf ("sink%d", shaper->nconnections);
|
||||
connection->sinkpad = gst_pad_new_from_template (
|
||||
gst_static_pad_template_get (&shaper_sink_template), padname);
|
||||
connection->sinkpad =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&shaper_sink_template), padname);
|
||||
g_free (padname);
|
||||
gst_pad_set_getcaps_function (connection->sinkpad, gst_shaper_getcaps);
|
||||
gst_pad_set_internal_link_function (connection->sinkpad, gst_shaper_get_internal_link);
|
||||
gst_pad_set_internal_link_function (connection->sinkpad,
|
||||
gst_shaper_get_internal_link);
|
||||
gst_pad_set_link_function (connection->sinkpad, gst_shaper_link);
|
||||
gst_pad_set_element_private (connection->sinkpad, connection);
|
||||
gst_element_add_pad (GST_ELEMENT (shaper), connection->sinkpad);
|
||||
|
||||
padname = g_strdup_printf ("src%d", shaper->nconnections);
|
||||
connection->srcpad = gst_pad_new_from_template (
|
||||
gst_static_pad_template_get (&shaper_src_template), padname);
|
||||
connection->srcpad =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&shaper_src_template), padname);
|
||||
g_free (padname);
|
||||
gst_pad_set_getcaps_function (connection->srcpad, gst_shaper_getcaps);
|
||||
gst_pad_set_internal_link_function (connection->srcpad, gst_shaper_get_internal_link);
|
||||
gst_pad_set_internal_link_function (connection->srcpad,
|
||||
gst_shaper_get_internal_link);
|
||||
gst_pad_set_link_function (connection->srcpad, gst_shaper_link);
|
||||
gst_pad_set_element_private (connection->srcpad, connection);
|
||||
gst_element_add_pad (GST_ELEMENT (shaper), connection->srcpad);
|
||||
|
@ -225,8 +231,9 @@ gst_shaper_create_connection (GstShaper *shaper)
|
|||
return connection;
|
||||
}
|
||||
|
||||
static GstPad*
|
||||
gst_shaper_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
|
||||
static GstPad *
|
||||
gst_shaper_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
||||
const gchar * unused)
|
||||
{
|
||||
GstShaper *shaper = GST_SHAPER (element);
|
||||
GstShaperConnection *connection;
|
||||
|
@ -236,8 +243,8 @@ gst_shaper_request_new_pad (GstElement *element, GstPadTemplate *templ, const gc
|
|||
return connection->sinkpad;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_shaper_init (GstShaper *shaper)
|
||||
static void
|
||||
gst_shaper_init (GstShaper * shaper)
|
||||
{
|
||||
gst_element_set_loop_function (GST_ELEMENT (shaper), gst_shaper_loop);
|
||||
|
||||
|
@ -248,8 +255,8 @@ gst_shaper_init (GstShaper *shaper)
|
|||
shaper->last_message = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_shaper_loop (GstElement *element)
|
||||
static void
|
||||
gst_shaper_loop (GstElement * element)
|
||||
{
|
||||
GstShaper *shaper;
|
||||
GSList *connections;
|
||||
|
@ -278,16 +285,15 @@ gst_shaper_loop (GstElement *element)
|
|||
gst_pad_push (connection->srcpad, GST_DATA (buffer));
|
||||
|
||||
switch (type) {
|
||||
/* on EOS we disable the pad so that we don't pull on
|
||||
* it again and never get more data */
|
||||
case GST_EVENT_EOS:
|
||||
/* on EOS we disable the pad so that we don't pull on
|
||||
* it again and never get more data */
|
||||
case GST_EVENT_EOS:
|
||||
gst_pad_set_active (connection->sinkpad, FALSE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* we store the buffer */
|
||||
connection->buffer = buffer;
|
||||
}
|
||||
|
@ -295,9 +301,8 @@ gst_shaper_loop (GstElement *element)
|
|||
/* FIXME policy stuff goes here */
|
||||
/* find connection with lowest timestamp */
|
||||
if (min == NULL || (connection->buffer != NULL &&
|
||||
(GST_BUFFER_TIMESTAMP (connection->buffer) <
|
||||
GST_BUFFER_TIMESTAMP (min->buffer))))
|
||||
{
|
||||
(GST_BUFFER_TIMESTAMP (connection->buffer) <
|
||||
GST_BUFFER_TIMESTAMP (min->buffer)))) {
|
||||
min = connection;
|
||||
}
|
||||
connections = g_slist_next (connections);
|
||||
|
@ -309,20 +314,21 @@ gst_shaper_loop (GstElement *element)
|
|||
/* since we pushed a buffer, it's not EOS */
|
||||
eos = FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (eos) {
|
||||
gst_element_set_eos (element);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_shaper_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_shaper_set_property (GObject * object, guint prop_id, const GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstShaper *shaper;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_SHAPER (object));
|
||||
|
||||
|
||||
shaper = GST_SHAPER (object);
|
||||
|
||||
switch (prop_id) {
|
||||
|
@ -338,12 +344,15 @@ gst_shaper_set_property (GObject *object, guint prop_id, const GValue *value, GP
|
|||
}
|
||||
}
|
||||
|
||||
static void gst_shaper_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
|
||||
static void
|
||||
gst_shaper_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstShaper *shaper;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_SHAPER (object));
|
||||
|
||||
|
||||
shaper = GST_SHAPER (object);
|
||||
|
||||
switch (prop_id) {
|
||||
|
@ -361,4 +370,3 @@ static void gst_shaper_get_property(GObject *object, guint prop_id, GValue *valu
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GST_TYPE_SHAPER \
|
||||
(gst_shaper_get_type())
|
||||
#define GST_SHAPER(obj) \
|
||||
|
@ -40,8 +38,8 @@ G_BEGIN_DECLS
|
|||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SHAPER))
|
||||
#define GST_IS_SHAPER_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SHAPER))
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
SHAPER_POLICY_TIMESTAMPS = 1,
|
||||
SHAPER_POLICY_BUFFERSIZE
|
||||
} GstShaperPolicyType;
|
||||
|
@ -49,26 +47,27 @@ typedef enum {
|
|||
typedef struct _GstShaper GstShaper;
|
||||
typedef struct _GstShaperClass GstShaperClass;
|
||||
|
||||
struct _GstShaper {
|
||||
GstElement element;
|
||||
struct _GstShaper
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
GSList *connections;
|
||||
gint nconnections;
|
||||
GSList *connections;
|
||||
gint nconnections;
|
||||
|
||||
GstShaperPolicyType policy;
|
||||
GstShaperPolicyType policy;
|
||||
|
||||
gboolean silent;
|
||||
gchar *last_message;
|
||||
gboolean silent;
|
||||
gchar *last_message;
|
||||
};
|
||||
|
||||
struct _GstShaperClass {
|
||||
struct _GstShaperClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_shaper_get_type (void);
|
||||
gboolean gst_shaper_factory_init (GstElementFactory *factory);
|
||||
GType gst_shaper_get_type (void);
|
||||
gboolean gst_shaper_factory_init (GstElementFactory * factory);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_SHAPER_H__ */
|
||||
|
|
|
@ -30,21 +30,21 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_statistics_debug);
|
||||
#define GST_CAT_DEFAULT gst_statistics_debug
|
||||
|
||||
GstElementDetails gst_statistics_details = GST_ELEMENT_DETAILS (
|
||||
"Statistics",
|
||||
"Generic",
|
||||
"Statistics on buffers/bytes/events",
|
||||
"David I. Lehn <dlehn@users.sourceforge.net>"
|
||||
);
|
||||
GstElementDetails gst_statistics_details = GST_ELEMENT_DETAILS ("Statistics",
|
||||
"Generic",
|
||||
"Statistics on buffers/bytes/events",
|
||||
"David I. Lehn <dlehn@users.sourceforge.net>");
|
||||
|
||||
|
||||
/* Statistics signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
SIGNAL_UPDATE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_BUFFERS,
|
||||
ARG_BYTES,
|
||||
|
@ -61,14 +61,17 @@ enum {
|
|||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_statistics_debug, "statistics", 0, "statistics element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstStatistics, gst_statistics, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
GST_BOILERPLATE_FULL (GstStatistics, gst_statistics, GstElement,
|
||||
GST_TYPE_ELEMENT, _do_init);
|
||||
|
||||
static void gst_statistics_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
static void gst_statistics_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||
static void gst_statistics_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_statistics_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static void gst_statistics_chain (GstPad *pad, GstData *_data);
|
||||
static void gst_statistics_reset (GstStatistics *statistics);
|
||||
static void gst_statistics_print (GstStatistics *statistics);
|
||||
static void gst_statistics_chain (GstPad * pad, GstData * _data);
|
||||
static void gst_statistics_reset (GstStatistics * statistics);
|
||||
static void gst_statistics_print (GstStatistics * statistics);
|
||||
|
||||
static guint gst_statistics_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
|
@ -79,71 +82,75 @@ static void
|
|||
gst_statistics_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &gst_statistics_details);
|
||||
}
|
||||
static void
|
||||
gst_statistics_class_init (GstStatisticsClass *klass)
|
||||
static void
|
||||
gst_statistics_class_init (GstStatisticsClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BUFFERS,
|
||||
g_param_spec_int64 ("buffers", "buffers", "total buffers count",
|
||||
0, G_MAXINT64, 0, G_PARAM_READABLE));
|
||||
g_param_spec_int64 ("buffers", "buffers", "total buffers count",
|
||||
0, G_MAXINT64, 0, G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BYTES,
|
||||
g_param_spec_int64 ("bytes", "bytes", "total bytes count",
|
||||
0, G_MAXINT64, 0, G_PARAM_READABLE));
|
||||
g_param_spec_int64 ("bytes", "bytes", "total bytes count",
|
||||
0, G_MAXINT64, 0, G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EVENTS,
|
||||
g_param_spec_int64 ("events", "events", "total event count",
|
||||
0, G_MAXINT64, 0, G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BUFFER_UPDATE_FREQ,
|
||||
g_param_spec_int64 ("buffer_update_freq", "buffer update freq", "buffer update frequency",
|
||||
0, G_MAXINT64, 0, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BYTES_UPDATE_FREQ,
|
||||
g_param_spec_int64 ("bytes_update_freq", "bytes update freq", "bytes update frequency",
|
||||
0, G_MAXINT64, 0, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EVENT_UPDATE_FREQ,
|
||||
g_param_spec_int64 ("event_update_freq", "event update freq", "event update frequency",
|
||||
0, G_MAXINT64, 0, G_PARAM_READWRITE));
|
||||
g_param_spec_int64 ("events", "events", "total event count",
|
||||
0, G_MAXINT64, 0, G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
ARG_BUFFER_UPDATE_FREQ, g_param_spec_int64 ("buffer_update_freq",
|
||||
"buffer update freq", "buffer update frequency", 0, G_MAXINT64, 0,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
ARG_BYTES_UPDATE_FREQ, g_param_spec_int64 ("bytes_update_freq",
|
||||
"bytes update freq", "bytes update frequency", 0, G_MAXINT64, 0,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
ARG_EVENT_UPDATE_FREQ, g_param_spec_int64 ("event_update_freq",
|
||||
"event update freq", "event update frequency", 0, G_MAXINT64, 0,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_UPDATE_ON_EOS,
|
||||
g_param_spec_boolean ("update_on_eos", "update on EOS", "update on EOS event",
|
||||
TRUE,G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("update_on_eos", "update on EOS",
|
||||
"update on EOS event", TRUE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_UPDATE,
|
||||
g_param_spec_boolean ("update", "update", "update",
|
||||
TRUE,G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("update", "update", "update", TRUE,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
|
||||
g_param_spec_boolean ("silent", "silent", "silent",
|
||||
TRUE,G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("silent", "silent", "silent", TRUE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
gst_statistics_signals[SIGNAL_UPDATE] =
|
||||
g_signal_new ("update", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstStatisticsClass, update), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
g_signal_new ("update", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstStatisticsClass, update), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_statistics_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_statistics_get_property);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_statistics_init (GstStatistics *statistics)
|
||||
static void
|
||||
gst_statistics_init (GstStatistics * statistics)
|
||||
{
|
||||
statistics->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (statistics), statistics->sinkpad);
|
||||
gst_pad_set_chain_function (statistics->sinkpad, GST_DEBUG_FUNCPTR (gst_statistics_chain));
|
||||
|
||||
gst_pad_set_chain_function (statistics->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_statistics_chain));
|
||||
|
||||
statistics->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_element_add_pad (GST_ELEMENT (statistics), statistics->srcpad);
|
||||
|
||||
statistics->timer = NULL;
|
||||
statistics->last_timer = NULL;
|
||||
gst_statistics_reset(statistics);
|
||||
gst_statistics_reset (statistics);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_statistics_reset (GstStatistics *statistics)
|
||||
gst_statistics_reset (GstStatistics * statistics)
|
||||
{
|
||||
g_return_if_fail (statistics != NULL);
|
||||
g_return_if_fail (GST_IS_STATISTICS (statistics));
|
||||
|
@ -169,15 +176,16 @@ gst_statistics_reset (GstStatistics *statistics)
|
|||
statistics->silent = FALSE;
|
||||
|
||||
if (!statistics->timer) {
|
||||
statistics->timer = g_timer_new();
|
||||
statistics->timer = g_timer_new ();
|
||||
}
|
||||
if (!statistics->last_timer) {
|
||||
statistics->last_timer = g_timer_new();
|
||||
statistics->last_timer = g_timer_new ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_stats(gboolean first, const gchar *name, const gchar *type, stats *base, stats *final, double time)
|
||||
print_stats (gboolean first, const gchar * name, const gchar * type,
|
||||
stats * base, stats * final, double time)
|
||||
{
|
||||
const gchar *header0 = "statistics";
|
||||
const gchar *headerN = " ";
|
||||
|
@ -187,25 +195,21 @@ print_stats(gboolean first, const gchar *name, const gchar *type, stats *base, s
|
|||
delta.bytes = final->bytes - base->bytes;
|
||||
delta.events = final->events - base->events;
|
||||
|
||||
g_print("%s: (%s) %s: s:%g buffers:%" G_GINT64_FORMAT
|
||||
" bytes:%" G_GINT64_FORMAT
|
||||
" events:%" G_GINT64_FORMAT "\n",
|
||||
first ? header0 : headerN,
|
||||
name, type, time,
|
||||
final->buffers,
|
||||
final->bytes,
|
||||
final->events);
|
||||
g_print("%s: (%s) %s: buf/s:%g B/s:%g e/s:%g B/buf:%g\n",
|
||||
headerN,
|
||||
name, type,
|
||||
delta.buffers/time,
|
||||
delta.bytes/time,
|
||||
delta.events/time,
|
||||
((double)delta.bytes/(double)delta.buffers));
|
||||
g_print ("%s: (%s) %s: s:%g buffers:%" G_GINT64_FORMAT
|
||||
" bytes:%" G_GINT64_FORMAT
|
||||
" events:%" G_GINT64_FORMAT "\n",
|
||||
first ? header0 : headerN,
|
||||
name, type, time, final->buffers, final->bytes, final->events);
|
||||
g_print ("%s: (%s) %s: buf/s:%g B/s:%g e/s:%g B/buf:%g\n",
|
||||
headerN,
|
||||
name, type,
|
||||
delta.buffers / time,
|
||||
delta.bytes / time,
|
||||
delta.events / time, ((double) delta.bytes / (double) delta.buffers));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_statistics_print (GstStatistics *statistics)
|
||||
gst_statistics_print (GstStatistics * statistics)
|
||||
{
|
||||
const gchar *name;
|
||||
double elapsed;
|
||||
|
@ -214,22 +218,23 @@ gst_statistics_print (GstStatistics *statistics)
|
|||
g_return_if_fail (statistics != NULL);
|
||||
g_return_if_fail (GST_IS_STATISTICS (statistics));
|
||||
|
||||
name = gst_object_get_name(GST_OBJECT(statistics));
|
||||
name = gst_object_get_name (GST_OBJECT (statistics));
|
||||
if (!name) {
|
||||
name = "";
|
||||
}
|
||||
|
||||
elapsed = g_timer_elapsed(statistics->timer, NULL);
|
||||
last_elapsed = g_timer_elapsed(statistics->last_timer, NULL);
|
||||
elapsed = g_timer_elapsed (statistics->timer, NULL);
|
||||
last_elapsed = g_timer_elapsed (statistics->last_timer, NULL);
|
||||
|
||||
print_stats(1, name, "total", &zero_stats, &statistics->stats, elapsed);
|
||||
print_stats(0, name, "last", &statistics->last_stats, &statistics->stats, last_elapsed);
|
||||
print_stats (1, name, "total", &zero_stats, &statistics->stats, elapsed);
|
||||
print_stats (0, name, "last", &statistics->last_stats, &statistics->stats,
|
||||
last_elapsed);
|
||||
statistics->last_stats = statistics->stats;
|
||||
g_timer_reset(statistics->last_timer);
|
||||
g_timer_reset (statistics->last_timer);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_statistics_chain (GstPad *pad, GstData *_data)
|
||||
static void
|
||||
gst_statistics_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
GstBuffer *buf = GST_BUFFER (_data);
|
||||
GstStatistics *statistics;
|
||||
|
@ -241,20 +246,21 @@ gst_statistics_chain (GstPad *pad, GstData *_data)
|
|||
|
||||
statistics = GST_STATISTICS (gst_pad_get_parent (pad));
|
||||
|
||||
if (GST_IS_EVENT(buf)) {
|
||||
if (GST_IS_EVENT (buf)) {
|
||||
GstEvent *event = GST_EVENT (buf);
|
||||
|
||||
statistics->stats.events += 1;
|
||||
if (GST_EVENT_TYPE(event) == GST_EVENT_EOS) {
|
||||
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
|
||||
gst_element_set_eos (GST_ELEMENT (statistics));
|
||||
if (statistics->update_on_eos) {
|
||||
update = TRUE;
|
||||
update = TRUE;
|
||||
}
|
||||
}
|
||||
if (statistics->update_freq.events) {
|
||||
statistics->update_count.events += 1;
|
||||
if (statistics->update_count.events == statistics->update_freq.events) {
|
||||
statistics->update_count.events = 0;
|
||||
update = TRUE;
|
||||
statistics->update_count.events = 0;
|
||||
update = TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -262,17 +268,17 @@ gst_statistics_chain (GstPad *pad, GstData *_data)
|
|||
if (statistics->update_freq.buffers) {
|
||||
statistics->update_count.buffers += 1;
|
||||
if (statistics->update_count.buffers == statistics->update_freq.buffers) {
|
||||
statistics->update_count.buffers = 0;
|
||||
update = TRUE;
|
||||
statistics->update_count.buffers = 0;
|
||||
update = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
statistics->stats.bytes += GST_BUFFER_SIZE(buf);
|
||||
statistics->stats.bytes += GST_BUFFER_SIZE (buf);
|
||||
if (statistics->update_freq.bytes) {
|
||||
statistics->update_count.bytes += GST_BUFFER_SIZE(buf);
|
||||
statistics->update_count.bytes += GST_BUFFER_SIZE (buf);
|
||||
if (statistics->update_count.bytes >= statistics->update_freq.bytes) {
|
||||
statistics->update_count.bytes = 0;
|
||||
update = TRUE;
|
||||
statistics->update_count.bytes = 0;
|
||||
update = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -280,24 +286,26 @@ gst_statistics_chain (GstPad *pad, GstData *_data)
|
|||
if (update) {
|
||||
if (statistics->update) {
|
||||
GST_DEBUG ("[%s]: pre update emit", GST_ELEMENT_NAME (statistics));
|
||||
g_signal_emit (G_OBJECT (statistics), gst_statistics_signals[SIGNAL_UPDATE], 0);
|
||||
g_signal_emit (G_OBJECT (statistics),
|
||||
gst_statistics_signals[SIGNAL_UPDATE], 0);
|
||||
GST_DEBUG ("[%s]: post update emit", GST_ELEMENT_NAME (statistics));
|
||||
}
|
||||
if (!statistics->silent) {
|
||||
gst_statistics_print(statistics);
|
||||
gst_statistics_print (statistics);
|
||||
}
|
||||
}
|
||||
gst_pad_push (statistics->srcpad, GST_DATA (buf));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_statistics_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_statistics_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstStatistics *statistics;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_STATISTICS (object));
|
||||
|
||||
|
||||
statistics = GST_STATISTICS (object);
|
||||
|
||||
switch (prop_id) {
|
||||
|
@ -325,12 +333,15 @@ gst_statistics_set_property (GObject *object, guint prop_id, const GValue *value
|
|||
}
|
||||
}
|
||||
|
||||
static void gst_statistics_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
|
||||
static void
|
||||
gst_statistics_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstStatistics *statistics;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail (GST_IS_STATISTICS (object));
|
||||
|
||||
|
||||
statistics = GST_STATISTICS (object);
|
||||
|
||||
switch (prop_id) {
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GST_TYPE_STATISTICS \
|
||||
(gst_statistics_get_type())
|
||||
#define GST_STATISTICS(obj) \
|
||||
|
@ -39,19 +37,20 @@ G_BEGIN_DECLS
|
|||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_STATISTICS))
|
||||
#define GST_IS_STATISTICS_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_STATISTICS))
|
||||
|
||||
typedef struct _GstStatistics GstStatistics;
|
||||
typedef struct _GstStatisticsClass GstStatisticsClass;
|
||||
|
||||
typedef struct _stats stats;
|
||||
|
||||
struct _stats {
|
||||
struct _stats
|
||||
{
|
||||
gint64 buffers;
|
||||
gint64 bytes;
|
||||
gint64 events;
|
||||
};
|
||||
|
||||
struct _GstStatistics {
|
||||
struct _GstStatistics
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
GstPad *sinkpad;
|
||||
|
@ -65,20 +64,20 @@ struct _GstStatistics {
|
|||
stats update_count;
|
||||
stats update_freq;
|
||||
|
||||
gboolean update_on_eos;
|
||||
gboolean update_on_eos;
|
||||
gboolean update;
|
||||
gboolean silent;
|
||||
};
|
||||
|
||||
struct _GstStatisticsClass {
|
||||
struct _GstStatisticsClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*update) (GstElement *element);
|
||||
void (*update) (GstElement * element);
|
||||
};
|
||||
|
||||
GType gst_statistics_get_type(void);
|
||||
GType gst_statistics_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_STATISTICS_H__ */
|
||||
|
|
|
@ -31,21 +31,21 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_tee_debug);
|
||||
#define GST_CAT_DEFAULT gst_tee_debug
|
||||
|
||||
GstElementDetails gst_tee_details = GST_ELEMENT_DETAILS (
|
||||
"Tee pipe fitting",
|
||||
"Generic",
|
||||
"1-to-N pipe fitting",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>, "
|
||||
"Wim Taymans <wim.taymans@chello.be>"
|
||||
);
|
||||
GstElementDetails gst_tee_details = GST_ELEMENT_DETAILS ("Tee pipe fitting",
|
||||
"Generic",
|
||||
"1-to-N pipe fitting",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>, "
|
||||
"Wim Taymans <wim.taymans@chello.be>");
|
||||
|
||||
/* Tee signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_SILENT,
|
||||
ARG_NUM_PADS,
|
||||
|
@ -53,89 +53,93 @@ enum {
|
|||
/* FILL ME */
|
||||
};
|
||||
|
||||
GstStaticPadTemplate tee_src_template = GST_STATIC_PAD_TEMPLATE (
|
||||
"src%d",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
GstStaticPadTemplate tee_src_template = GST_STATIC_PAD_TEMPLATE ("src%d",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
#define _do_init(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_tee_debug, "tee", 0, "tee element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstTee, gst_tee, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
|
||||
static GstPad* gst_tee_request_new_pad (GstElement *element, GstPadTemplate *temp, const gchar *unused);
|
||||
static GstPad *gst_tee_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * temp, const gchar * unused);
|
||||
|
||||
static void gst_tee_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_tee_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
static void gst_tee_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_tee_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static void gst_tee_chain (GstPad *pad, GstData *_data);
|
||||
static void gst_tee_chain (GstPad * pad, GstData * _data);
|
||||
|
||||
|
||||
static void
|
||||
gst_tee_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &gst_tee_details);
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&tee_src_template));
|
||||
}
|
||||
static void
|
||||
gst_tee_class_init (GstTeeClass *klass)
|
||||
gst_tee_class_init (GstTeeClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
||||
gobject_class = (GObjectClass*)klass;
|
||||
gstelement_class = (GstElementClass*)klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_PADS,
|
||||
g_param_spec_int ("num_pads", "num_pads", "num_pads",
|
||||
0, G_MAXINT, 0, G_PARAM_READABLE));
|
||||
g_param_spec_int ("num_pads", "num_pads", "num_pads",
|
||||
0, G_MAXINT, 0, G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
|
||||
g_param_spec_boolean ("silent", "silent", "silent",
|
||||
TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("silent", "silent", "silent",
|
||||
TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
|
||||
g_param_spec_string ("last_message", "last_message", "last_message",
|
||||
NULL, G_PARAM_READABLE));
|
||||
|
||||
g_param_spec_string ("last_message", "last_message", "last_message",
|
||||
NULL, G_PARAM_READABLE));
|
||||
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_tee_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_tee_get_property);
|
||||
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_tee_request_new_pad);
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_tee_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_tee_get_property);
|
||||
|
||||
gstelement_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_tee_request_new_pad);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tee_init (GstTee *tee)
|
||||
static void
|
||||
gst_tee_init (GstTee * tee)
|
||||
{
|
||||
tee->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad);
|
||||
gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain));
|
||||
gst_pad_set_link_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_pad_proxy_pad_link));
|
||||
gst_pad_set_getcaps_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
|
||||
gst_pad_set_link_function (tee->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_pad_proxy_pad_link));
|
||||
gst_pad_set_getcaps_function (tee->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
|
||||
|
||||
tee->last_message = NULL;
|
||||
}
|
||||
|
||||
/* helper compare function */
|
||||
gint name_pad_compare (gconstpointer a, gconstpointer b)
|
||||
gint
|
||||
name_pad_compare (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
GstPad* pad = (GstPad*) a;
|
||||
GstPad *pad = (GstPad *) a;
|
||||
gchar *name = (gchar *) b;
|
||||
|
||||
|
||||
g_assert (GST_IS_PAD (pad));
|
||||
|
||||
return strcmp (name, gst_pad_get_name (pad)); /* returns 0 if match */
|
||||
return strcmp (name, gst_pad_get_name (pad)); /* returns 0 if match */
|
||||
}
|
||||
|
||||
static GstPad*
|
||||
gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
|
||||
static GstPad *
|
||||
gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
||||
const gchar * unused)
|
||||
{
|
||||
gchar *name;
|
||||
GstPad *srcpad;
|
||||
|
@ -144,7 +148,7 @@ gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar
|
|||
const GList *pads;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TEE (element), NULL);
|
||||
|
||||
|
||||
if (templ->direction != GST_PAD_SRC) {
|
||||
g_warning ("gsttee: request new pad that is not a SRC pad\n");
|
||||
return NULL;
|
||||
|
@ -154,13 +158,12 @@ gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar
|
|||
|
||||
/* try names in order and find one that's not in use atm */
|
||||
pads = gst_element_get_pad_list (element);
|
||||
|
||||
|
||||
name = NULL;
|
||||
while (!name)
|
||||
{
|
||||
while (!name) {
|
||||
name = g_strdup_printf ("src%d", i);
|
||||
if (g_list_find_custom ((GList *)pads, (gconstpointer) name, name_pad_compare) != NULL)
|
||||
{
|
||||
if (g_list_find_custom ((GList *) pads, (gconstpointer) name,
|
||||
name_pad_compare) != NULL) {
|
||||
/* this name is taken, use the next one */
|
||||
++i;
|
||||
g_free (name);
|
||||
|
@ -172,11 +175,13 @@ gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar
|
|||
tee->last_message = g_strdup_printf ("new pad %s", name);
|
||||
g_object_notify (G_OBJECT (tee), "last_message");
|
||||
}
|
||||
|
||||
|
||||
srcpad = gst_pad_new_from_template (templ, name);
|
||||
g_free (name);
|
||||
gst_pad_set_link_function (srcpad, GST_DEBUG_FUNCPTR (gst_pad_proxy_pad_link));
|
||||
gst_pad_set_getcaps_function (srcpad, GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
|
||||
gst_pad_set_link_function (srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_pad_proxy_pad_link));
|
||||
gst_pad_set_getcaps_function (srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
|
||||
gst_element_add_pad (GST_ELEMENT (tee), srcpad);
|
||||
GST_PAD_ELEMENT_PRIVATE (srcpad) = NULL;
|
||||
|
||||
|
@ -188,7 +193,8 @@ gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar
|
|||
}
|
||||
|
||||
static void
|
||||
gst_tee_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
gst_tee_set_property (GObject * object, guint prop_id, const GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstTee *tee;
|
||||
|
||||
|
@ -209,7 +215,8 @@ gst_tee_set_property (GObject *object, guint prop_id, const GValue *value, GPara
|
|||
}
|
||||
|
||||
static void
|
||||
gst_tee_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
gst_tee_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstTee *tee;
|
||||
|
||||
|
@ -241,8 +248,8 @@ gst_tee_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec
|
|||
*
|
||||
* Chain a buffer on a pad.
|
||||
*/
|
||||
static void
|
||||
gst_tee_chain (GstPad *pad, GstData *_data)
|
||||
static void
|
||||
gst_tee_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
GstBuffer *buf = GST_BUFFER (_data);
|
||||
GstTee *tee;
|
||||
|
@ -255,11 +262,12 @@ gst_tee_chain (GstPad *pad, GstData *_data)
|
|||
tee = GST_TEE (gst_pad_get_parent (pad));
|
||||
|
||||
gst_buffer_ref_by_count (buf, GST_ELEMENT (tee)->numsrcpads - 1);
|
||||
|
||||
|
||||
pads = gst_element_get_pad_list (GST_ELEMENT (tee));
|
||||
|
||||
while (pads) {
|
||||
GstPad *outpad = GST_PAD (pads->data);
|
||||
|
||||
pads = g_list_next (pads);
|
||||
|
||||
if (GST_PAD_DIRECTION (outpad) != GST_PAD_SRC)
|
||||
|
@ -267,9 +275,10 @@ gst_tee_chain (GstPad *pad, GstData *_data)
|
|||
|
||||
if (!tee->silent) {
|
||||
g_free (tee->last_message);
|
||||
tee->last_message = g_strdup_printf ("chain ******* (%s:%s)t (%d bytes, %"
|
||||
G_GUINT64_FORMAT ") %p",
|
||||
GST_DEBUG_PAD_NAME (outpad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
|
||||
tee->last_message =
|
||||
g_strdup_printf ("chain ******* (%s:%s)t (%d bytes, %"
|
||||
G_GUINT64_FORMAT ") %p", GST_DEBUG_PAD_NAME (outpad),
|
||||
GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
|
||||
g_object_notify (G_OBJECT (tee), "last_message");
|
||||
}
|
||||
|
||||
|
@ -279,4 +288,3 @@ gst_tee_chain (GstPad *pad, GstData *_data)
|
|||
gst_buffer_unref (buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GST_TYPE_TEE \
|
||||
(gst_tee_get_type())
|
||||
#define GST_TEE(obj) \
|
||||
|
@ -39,27 +37,27 @@ G_BEGIN_DECLS
|
|||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TEE))
|
||||
#define GST_IS_TEE_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TEE))
|
||||
typedef struct _GstTee GstTee;
|
||||
typedef struct _GstTeeClass GstTeeClass;
|
||||
|
||||
typedef struct _GstTee GstTee;
|
||||
typedef struct _GstTeeClass GstTeeClass;
|
||||
|
||||
struct _GstTee {
|
||||
struct _GstTee
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
GstPad *sinkpad;
|
||||
|
||||
gboolean silent;
|
||||
gchar *last_message;
|
||||
gchar *last_message;
|
||||
};
|
||||
|
||||
struct _GstTeeClass {
|
||||
struct _GstTeeClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_tee_get_type (void);
|
||||
GType gst_tee_get_type (void);
|
||||
|
||||
gboolean gst_tee_factory_init (GstElementFactory *factory);
|
||||
gboolean gst_tee_factory_init (GstElementFactory * factory);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_TEE_H__ */
|
||||
|
|
|
@ -49,42 +49,42 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_type_find_element_debug);
|
||||
#define GST_CAT_DEFAULT gst_type_find_element_debug
|
||||
|
||||
GstElementDetails gst_type_find_element_details = GST_ELEMENT_DETAILS (
|
||||
"TypeFind",
|
||||
"Generic",
|
||||
"Finds the media type of a stream",
|
||||
"Benjamin Otte <in7y118@public.uni-hamburg.de>"
|
||||
);
|
||||
GstElementDetails gst_type_find_element_details =
|
||||
GST_ELEMENT_DETAILS ("TypeFind",
|
||||
"Generic",
|
||||
"Finds the media type of a stream",
|
||||
"Benjamin Otte <in7y118@public.uni-hamburg.de>");
|
||||
|
||||
/* generic templates */
|
||||
GstStaticPadTemplate type_find_element_sink_template = GST_STATIC_PAD_TEMPLATE (
|
||||
"sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
GstStaticPadTemplate type_find_element_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
GstStaticPadTemplate type_find_element_src_template = GST_STATIC_PAD_TEMPLATE (
|
||||
"src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
GstStaticPadTemplate type_find_element_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
/* TypeFind signals and args */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
HAVE_TYPE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_CAPS,
|
||||
ARG_MINIMUM,
|
||||
ARG_MAXIMUM
|
||||
};
|
||||
enum {
|
||||
MODE_NORMAL, /* act as identity */
|
||||
MODE_TYPEFIND, /* do typefinding */
|
||||
enum
|
||||
{
|
||||
MODE_NORMAL, /* act as identity */
|
||||
MODE_TYPEFIND, /* do typefinding */
|
||||
};
|
||||
|
||||
|
||||
|
@ -92,32 +92,28 @@ enum {
|
|||
GST_DEBUG_CATEGORY_INIT (gst_type_find_element_debug, "typefind", \
|
||||
GST_DEBUG_BG_YELLOW | GST_DEBUG_FG_GREEN, "type finding element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstTypeFindElement, gst_type_find_element, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||
GST_BOILERPLATE_FULL (GstTypeFindElement, gst_type_find_element, GstElement,
|
||||
GST_TYPE_ELEMENT, _do_init);
|
||||
|
||||
static void gst_type_find_element_dispose (GObject * object);
|
||||
static void gst_type_find_element_set_property (GObject * object,
|
||||
guint prop_id,
|
||||
const GValue * value,
|
||||
GParamSpec * pspec);
|
||||
static void gst_type_find_element_get_property (GObject * object,
|
||||
guint prop_id,
|
||||
GValue * value,
|
||||
GParamSpec * pspec);
|
||||
static void gst_type_find_element_dispose (GObject * object);
|
||||
static void gst_type_find_element_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||
static void gst_type_find_element_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec);
|
||||
|
||||
static const GstEventMask *
|
||||
gst_type_find_element_src_event_mask (GstPad * pad);
|
||||
static gboolean gst_type_find_element_src_event (GstPad * pad,
|
||||
GstEvent * event);
|
||||
static const GstEventMask *gst_type_find_element_src_event_mask (GstPad * pad);
|
||||
static gboolean gst_type_find_element_src_event (GstPad * pad,
|
||||
GstEvent * event);
|
||||
|
||||
static void gst_type_find_element_chain (GstPad * sinkpad,
|
||||
GstData * data);
|
||||
static void gst_type_find_element_chain (GstPad * sinkpad, GstData * data);
|
||||
static GstElementStateReturn
|
||||
gst_type_find_element_change_state (GstElement * element);
|
||||
gst_type_find_element_change_state (GstElement * element);
|
||||
|
||||
static guint gst_type_find_element_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void
|
||||
gst_type_find_element_have_type (GstTypeFindElement *typefind, guint probability, const GstCaps *caps)
|
||||
gst_type_find_element_have_type (GstTypeFindElement * typefind,
|
||||
guint probability, const GstCaps * caps)
|
||||
{
|
||||
g_assert (typefind->caps == NULL);
|
||||
g_assert (caps != NULL);
|
||||
|
@ -130,53 +126,62 @@ static void
|
|||
gst_type_find_element_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &gst_type_find_element_details);
|
||||
|
||||
gst_element_class_set_details (gstelement_class,
|
||||
&gst_type_find_element_details);
|
||||
}
|
||||
static void
|
||||
gst_type_find_element_class_init (GstTypeFindElementClass *typefind_class)
|
||||
gst_type_find_element_class_init (GstTypeFindElementClass * typefind_class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (typefind_class);
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (typefind_class);
|
||||
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_type_find_element_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_type_find_element_get_property);
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_type_find_element_dispose);
|
||||
gobject_class->set_property =
|
||||
GST_DEBUG_FUNCPTR (gst_type_find_element_set_property);
|
||||
gobject_class->get_property =
|
||||
GST_DEBUG_FUNCPTR (gst_type_find_element_get_property);
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_type_find_element_dispose);
|
||||
|
||||
typefind_class->have_type = gst_type_find_element_have_type;
|
||||
|
||||
g_object_class_install_property (gobject_class, ARG_CAPS,
|
||||
g_param_spec_boxed ("caps", _("caps"), _("detected capabilities in stream"),
|
||||
gst_caps_get_type(), G_PARAM_READABLE));
|
||||
g_param_spec_boxed ("caps", _("caps"),
|
||||
_("detected capabilities in stream"), gst_caps_get_type (),
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class, ARG_MINIMUM,
|
||||
g_param_spec_uint ("minimum", _("minimum"), "minimum probability required to accept caps",
|
||||
GST_TYPE_FIND_MINIMUM, GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MINIMUM, G_PARAM_READWRITE));
|
||||
g_param_spec_uint ("minimum", _("minimum"),
|
||||
"minimum probability required to accept caps", GST_TYPE_FIND_MINIMUM,
|
||||
GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MINIMUM, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, ARG_MINIMUM,
|
||||
g_param_spec_uint ("maximum", _("maximum"), "probability to stop typefinding",
|
||||
GST_TYPE_FIND_MINIMUM, GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MAXIMUM, G_PARAM_READWRITE));
|
||||
g_param_spec_uint ("maximum", _("maximum"),
|
||||
"probability to stop typefinding", GST_TYPE_FIND_MINIMUM,
|
||||
GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MAXIMUM, G_PARAM_READWRITE));
|
||||
|
||||
gst_type_find_element_signals[HAVE_TYPE] = g_signal_new ("have_type",
|
||||
G_TYPE_FROM_CLASS (typefind_class), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstTypeFindElementClass, have_type), NULL, NULL,
|
||||
gst_marshal_VOID__UINT_BOXED, G_TYPE_NONE, 2,
|
||||
G_TYPE_UINT, GST_TYPE_CAPS | G_SIGNAL_TYPE_STATIC_SCOPE);
|
||||
gst_type_find_element_signals[HAVE_TYPE] = g_signal_new ("have_type",
|
||||
G_TYPE_FROM_CLASS (typefind_class), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstTypeFindElementClass, have_type), NULL, NULL,
|
||||
gst_marshal_VOID__UINT_BOXED, G_TYPE_NONE, 2,
|
||||
G_TYPE_UINT, GST_TYPE_CAPS | G_SIGNAL_TYPE_STATIC_SCOPE);
|
||||
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_type_find_element_change_state);
|
||||
gstelement_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_type_find_element_change_state);
|
||||
}
|
||||
static void
|
||||
gst_type_find_element_init (GstTypeFindElement *typefind)
|
||||
gst_type_find_element_init (GstTypeFindElement * typefind)
|
||||
{
|
||||
/* sinkpad */
|
||||
typefind->sink = gst_pad_new_from_template (
|
||||
gst_static_pad_template_get (&type_find_element_sink_template), "sink");
|
||||
gst_pad_set_chain_function (typefind->sink,
|
||||
gst_type_find_element_chain);
|
||||
typefind->sink =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&type_find_element_sink_template), "sink");
|
||||
gst_pad_set_chain_function (typefind->sink, gst_type_find_element_chain);
|
||||
gst_element_add_pad (GST_ELEMENT (typefind), typefind->sink);
|
||||
/* srcpad */
|
||||
typefind->src = gst_pad_new_from_template (
|
||||
gst_static_pad_template_get (&type_find_element_src_template), "src");
|
||||
typefind->src =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&type_find_element_src_template), "src");
|
||||
gst_pad_set_event_function (typefind->src, gst_type_find_element_src_event);
|
||||
gst_pad_set_event_mask_function (typefind->src, gst_type_find_element_src_event_mask);
|
||||
gst_pad_set_event_mask_function (typefind->src,
|
||||
gst_type_find_element_src_event_mask);
|
||||
gst_pad_use_explicit_caps (typefind->src);
|
||||
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
||||
|
||||
|
@ -189,7 +194,7 @@ gst_type_find_element_init (GstTypeFindElement *typefind)
|
|||
GST_FLAG_SET (typefind, GST_ELEMENT_EVENT_AWARE);
|
||||
}
|
||||
static void
|
||||
gst_type_find_element_dispose (GObject *object)
|
||||
gst_type_find_element_dispose (GObject * object)
|
||||
{
|
||||
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (object);
|
||||
|
||||
|
@ -201,8 +206,8 @@ gst_type_find_element_dispose (GObject *object)
|
|||
}
|
||||
}
|
||||
static void
|
||||
gst_type_find_element_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
gst_type_find_element_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTypeFindElement *typefind;
|
||||
|
||||
|
@ -225,8 +230,8 @@ gst_type_find_element_set_property (GObject *object, guint prop_id,
|
|||
}
|
||||
}
|
||||
static void
|
||||
gst_type_find_element_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
gst_type_find_element_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTypeFindElement *typefind;
|
||||
|
||||
|
@ -250,18 +255,21 @@ gst_type_find_element_get_property (GObject *object, guint prop_id,
|
|||
}
|
||||
}
|
||||
static const GstEventMask *
|
||||
gst_type_find_element_src_event_mask (GstPad *pad)
|
||||
gst_type_find_element_src_event_mask (GstPad * pad)
|
||||
{
|
||||
static const GstEventMask mask[] = {
|
||||
{ GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_METHOD_CUR | GST_SEEK_METHOD_END | GST_SEEK_FLAG_FLUSH},
|
||||
{GST_EVENT_SEEK,
|
||||
GST_SEEK_METHOD_SET | GST_SEEK_METHOD_CUR | GST_SEEK_METHOD_END |
|
||||
GST_SEEK_FLAG_FLUSH},
|
||||
/* add more if you want, event masks suck and need to die anyway */
|
||||
{ 0, }
|
||||
{0,}
|
||||
};
|
||||
|
||||
|
||||
return mask;
|
||||
}
|
||||
static gboolean
|
||||
gst_type_find_element_src_event (GstPad *pad, GstEvent *event)
|
||||
|
||||
static gboolean
|
||||
gst_type_find_element_src_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
|
||||
|
||||
|
@ -272,15 +280,16 @@ gst_type_find_element_src_event (GstPad *pad, GstEvent *event)
|
|||
}
|
||||
return gst_pad_event_default (pad, event);
|
||||
}
|
||||
typedef struct {
|
||||
GstTypeFindFactory * factory;
|
||||
gint probability;
|
||||
GstCaps * caps;
|
||||
gint64 requested_offset;
|
||||
guint requested_size;
|
||||
typedef struct
|
||||
{
|
||||
GstTypeFindFactory *factory;
|
||||
gint probability;
|
||||
GstCaps *caps;
|
||||
gint64 requested_offset;
|
||||
guint requested_size;
|
||||
|
||||
GList * buffers;
|
||||
GstTypeFindElement * self;
|
||||
GList *buffers;
|
||||
GstTypeFindElement *self;
|
||||
} TypeFindEntry;
|
||||
|
||||
static inline TypeFindEntry *
|
||||
|
@ -289,42 +298,45 @@ new_entry (void)
|
|||
return g_new0 (TypeFindEntry, 1);
|
||||
}
|
||||
static void
|
||||
free_entry_buffers (TypeFindEntry *entry)
|
||||
free_entry_buffers (TypeFindEntry * entry)
|
||||
{
|
||||
g_list_foreach (entry->buffers, (GFunc) gst_data_unref, NULL);
|
||||
g_list_free (entry->buffers);
|
||||
entry->buffers = NULL;
|
||||
}
|
||||
static void
|
||||
free_entry (TypeFindEntry *entry)
|
||||
free_entry (TypeFindEntry * entry)
|
||||
{
|
||||
free_entry_buffers (entry);
|
||||
|
||||
|
||||
if (entry->caps)
|
||||
gst_caps_free (entry->caps);
|
||||
g_free (entry);
|
||||
}
|
||||
static void
|
||||
start_typefinding (GstTypeFindElement *typefind)
|
||||
start_typefinding (GstTypeFindElement * typefind)
|
||||
{
|
||||
g_assert (typefind->caps == NULL);
|
||||
g_assert (typefind->possibilities == NULL);
|
||||
|
||||
|
||||
GST_DEBUG_OBJECT (typefind, "starting typefinding");
|
||||
typefind->mode = MODE_TYPEFIND;
|
||||
typefind->stream_length_available = TRUE;
|
||||
typefind->stream_length = 0;
|
||||
typefind->mode = MODE_TYPEFIND;
|
||||
typefind->stream_length_available = TRUE;
|
||||
typefind->stream_length = 0;
|
||||
}
|
||||
static void
|
||||
stop_typefinding (GstTypeFindElement *typefind)
|
||||
stop_typefinding (GstTypeFindElement * typefind)
|
||||
{
|
||||
/* stop all typefinding and set mode back to normal */
|
||||
gboolean push_cached_buffers = gst_element_get_state (GST_ELEMENT (typefind)) == GST_STATE_PLAYING;
|
||||
|
||||
GST_DEBUG_OBJECT (typefind, "stopping typefinding%s", push_cached_buffers ? " and pushing cached buffers" : "");
|
||||
gboolean push_cached_buffers =
|
||||
gst_element_get_state (GST_ELEMENT (typefind)) == GST_STATE_PLAYING;
|
||||
|
||||
GST_DEBUG_OBJECT (typefind, "stopping typefinding%s",
|
||||
push_cached_buffers ? " and pushing cached buffers" : "");
|
||||
if (typefind->possibilities != NULL) {
|
||||
/* this should only happen on PAUSED => READY or EOS */
|
||||
GST_LOG_OBJECT (typefind, "freeing remaining %u typefind functions", g_list_length (typefind->possibilities));
|
||||
GST_LOG_OBJECT (typefind, "freeing remaining %u typefind functions",
|
||||
g_list_length (typefind->possibilities));
|
||||
g_list_foreach (typefind->possibilities, (GFunc) free_entry, NULL);
|
||||
g_list_free (typefind->possibilities);
|
||||
typefind->possibilities = NULL;
|
||||
|
@ -336,51 +348,59 @@ stop_typefinding (GstTypeFindElement *typefind)
|
|||
GstBuffer *buffer;
|
||||
guint size = gst_buffer_store_get_size (typefind->store, 0);
|
||||
|
||||
if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
||||
if (size
|
||||
&& (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
||||
GST_LOG_OBJECT (typefind, "pushing cached data (%u bytes)", size);
|
||||
gst_pad_push (typefind->src, GST_DATA (buffer));
|
||||
} else {
|
||||
size = 0;
|
||||
}
|
||||
GST_LOG_OBJECT (typefind, "seeking back to current position %u", size);
|
||||
if (!gst_pad_send_event (GST_PAD_PEER (typefind->sink),
|
||||
gst_event_new_seek (GST_SEEK_METHOD_SET | GST_FORMAT_BYTES, size))) {
|
||||
GST_WARNING_OBJECT (typefind, "could not seek to required position %u, hope for the best", size);
|
||||
if (!gst_pad_send_event (GST_PAD_PEER (typefind->sink),
|
||||
gst_event_new_seek (GST_SEEK_METHOD_SET | GST_FORMAT_BYTES,
|
||||
size))) {
|
||||
GST_WARNING_OBJECT (typefind,
|
||||
"could not seek to required position %u, hope for the best", size);
|
||||
}
|
||||
}
|
||||
gst_buffer_store_clear (typefind->store);
|
||||
}
|
||||
|
||||
static guint64
|
||||
find_element_get_length (gpointer data)
|
||||
{
|
||||
TypeFindEntry *entry = (TypeFindEntry *) data;
|
||||
GstTypeFindElement *typefind = entry->self;
|
||||
GstFormat format = GST_FORMAT_BYTES;
|
||||
|
||||
|
||||
if (!typefind->stream_length_available) {
|
||||
GST_LOG_OBJECT (entry->self, "'%s' called get_length () but we know it's not available",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory));
|
||||
GST_LOG_OBJECT (entry->self,
|
||||
"'%s' called get_length () but we know it's not available",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory));
|
||||
return 0;
|
||||
}
|
||||
if (entry->self->stream_length == 0) {
|
||||
typefind->stream_length_available = gst_pad_query (GST_PAD_PEER (entry->self->sink), GST_QUERY_TOTAL,
|
||||
&format, &entry->self->stream_length);
|
||||
typefind->stream_length_available =
|
||||
gst_pad_query (GST_PAD_PEER (entry->self->sink), GST_QUERY_TOTAL,
|
||||
&format, &entry->self->stream_length);
|
||||
if (format != GST_FORMAT_BYTES)
|
||||
typefind->stream_length_available = FALSE;
|
||||
if (!typefind->stream_length_available) {
|
||||
GST_DEBUG_OBJECT (entry->self, "'%s' called get_length () but it's not available",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory));
|
||||
GST_DEBUG_OBJECT (entry->self,
|
||||
"'%s' called get_length () but it's not available",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory));
|
||||
return 0;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (entry->self, "'%s' called get_length () and it's %"G_GUINT64_FORMAT" bytes",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->self->stream_length);
|
||||
GST_DEBUG_OBJECT (entry->self,
|
||||
"'%s' called get_length () and it's %" G_GUINT64_FORMAT " bytes",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->self->stream_length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return entry->self->stream_length;
|
||||
}
|
||||
static void
|
||||
gst_type_find_element_handle_event (GstPad *pad, GstEvent *event)
|
||||
gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
TypeFindEntry *entry;
|
||||
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
|
||||
|
@ -388,20 +408,24 @@ gst_type_find_element_handle_event (GstPad *pad, GstEvent *event)
|
|||
if (typefind->mode == MODE_TYPEFIND) {
|
||||
/* need to do more? */
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_EOS:
|
||||
/* this should only happen when we got all available data */
|
||||
entry = (TypeFindEntry *) typefind->possibilities ? typefind->possibilities->data : NULL;
|
||||
if (entry && entry->probability >= typefind->min_probability) {
|
||||
GST_INFO_OBJECT (typefind, "'%s' is the best typefind left after we got all data, using it now (probability %u)",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
|
||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0, entry->probability, entry->caps);
|
||||
}
|
||||
stop_typefinding (typefind);
|
||||
gst_pad_event_default (pad, event);
|
||||
break;
|
||||
default:
|
||||
gst_data_unref (GST_DATA (event));
|
||||
break;
|
||||
case GST_EVENT_EOS:
|
||||
/* this should only happen when we got all available data */
|
||||
entry =
|
||||
(TypeFindEntry *) typefind->possibilities ? typefind->
|
||||
possibilities->data : NULL;
|
||||
if (entry && entry->probability >= typefind->min_probability) {
|
||||
GST_INFO_OBJECT (typefind,
|
||||
"'%s' is the best typefind left after we got all data, using it now (probability %u)",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
|
||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
|
||||
entry->probability, entry->caps);
|
||||
}
|
||||
stop_typefinding (typefind);
|
||||
gst_pad_event_default (pad, event);
|
||||
break;
|
||||
default:
|
||||
gst_data_unref (GST_DATA (event));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
gst_pad_event_default (pad, event);
|
||||
|
@ -412,9 +436,9 @@ find_peek (gpointer data, gint64 offset, guint size)
|
|||
{
|
||||
GstBuffer *buf;
|
||||
TypeFindEntry *entry = (TypeFindEntry *) data;
|
||||
|
||||
GST_LOG_OBJECT (entry->self, "'%s' called peek (%"G_GINT64_FORMAT", %u)",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), offset, size);
|
||||
|
||||
GST_LOG_OBJECT (entry->self, "'%s' called peek (%" G_GINT64_FORMAT ", %u)",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), offset, size);
|
||||
if (offset >= 0) {
|
||||
buf = gst_buffer_store_get_buffer (entry->self->store, offset, size);
|
||||
} else {
|
||||
|
@ -424,7 +448,9 @@ find_peek (gpointer data, gint64 offset, guint size)
|
|||
if (length == 0) {
|
||||
buf = NULL;
|
||||
} else {
|
||||
buf = gst_buffer_store_get_buffer (entry->self->store, length + offset, size);
|
||||
buf =
|
||||
gst_buffer_store_get_buffer (entry->self->store, length + offset,
|
||||
size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -433,8 +459,9 @@ find_peek (gpointer data, gint64 offset, guint size)
|
|||
return GST_BUFFER_DATA (buf);
|
||||
} else {
|
||||
if (entry->requested_size == 0) {
|
||||
GST_LOG_OBJECT (entry->self, "setting requested peek (%"G_GINT64_FORMAT", %u) on '%s'",
|
||||
offset, size, GST_PLUGIN_FEATURE_NAME (entry->factory));
|
||||
GST_LOG_OBJECT (entry->self,
|
||||
"setting requested peek (%" G_GINT64_FORMAT ", %u) on '%s'", offset,
|
||||
size, GST_PLUGIN_FEATURE_NAME (entry->factory));
|
||||
entry->requested_offset = offset;
|
||||
entry->requested_size = size;
|
||||
}
|
||||
|
@ -442,12 +469,12 @@ find_peek (gpointer data, gint64 offset, guint size)
|
|||
}
|
||||
}
|
||||
static void
|
||||
find_suggest (gpointer data, guint probability, const GstCaps *caps)
|
||||
find_suggest (gpointer data, guint probability, const GstCaps * caps)
|
||||
{
|
||||
TypeFindEntry *entry = (TypeFindEntry *) data;
|
||||
|
||||
GST_LOG_OBJECT (entry->self, "'%s' called suggest (%u, %" GST_PTR_FORMAT ")",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), probability, caps);
|
||||
|
||||
GST_LOG_OBJECT (entry->self, "'%s' called suggest (%u, %" GST_PTR_FORMAT ")",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), probability, caps);
|
||||
if (((gint) probability) > entry->probability) {
|
||||
entry->probability = probability;
|
||||
gst_caps_replace (&entry->caps, gst_caps_copy (caps));
|
||||
|
@ -472,13 +499,13 @@ compare_type_find_factory (gconstpointer fac1, gconstpointer fac2)
|
|||
return GST_PLUGIN_FEATURE (fac1)->rank - GST_PLUGIN_FEATURE (fac2)->rank;
|
||||
}
|
||||
static void
|
||||
gst_type_find_element_chain (GstPad *pad, GstData *data)
|
||||
gst_type_find_element_chain (GstPad * pad, GstData * data)
|
||||
{
|
||||
GstTypeFindElement *typefind;
|
||||
GList *entries;
|
||||
TypeFindEntry *entry;
|
||||
GList *walk;
|
||||
GstTypeFind find = {find_peek, find_suggest, NULL, find_element_get_length };
|
||||
GstTypeFind find = { find_peek, find_suggest, NULL, find_element_get_length };
|
||||
|
||||
typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
|
||||
if (GST_IS_EVENT (data)) {
|
||||
|
@ -489,36 +516,39 @@ gst_type_find_element_chain (GstPad *pad, GstData *data)
|
|||
case MODE_NORMAL:
|
||||
gst_pad_push (typefind->src, data);
|
||||
return;
|
||||
case MODE_TYPEFIND: {
|
||||
case MODE_TYPEFIND:{
|
||||
guint64 current_offset;
|
||||
|
||||
|
||||
gst_buffer_store_add_buffer (typefind->store, GST_BUFFER (data));
|
||||
current_offset = GST_BUFFER_OFFSET_IS_VALID (data) ?
|
||||
GST_BUFFER_OFFSET (data) + GST_BUFFER_SIZE (data) :
|
||||
current_offset = GST_BUFFER_OFFSET_IS_VALID (data) ?
|
||||
GST_BUFFER_OFFSET (data) + GST_BUFFER_SIZE (data) :
|
||||
gst_buffer_store_get_size (typefind->store, 0);
|
||||
gst_data_unref (data);
|
||||
if (typefind->possibilities == NULL) {
|
||||
/* not yet started, get all typefinding functions into our "queue" */
|
||||
GList *all_factories = gst_type_find_factory_get_list ();
|
||||
GST_INFO_OBJECT (typefind, "starting with %u typefinding functions",
|
||||
g_list_length ((GList *) all_factories));
|
||||
|
||||
|
||||
GST_INFO_OBJECT (typefind, "starting with %u typefinding functions",
|
||||
g_list_length ((GList *) all_factories));
|
||||
|
||||
all_factories = g_list_sort (all_factories, compare_type_find_factory);
|
||||
walk = all_factories;
|
||||
while (all_factories) {
|
||||
entry = new_entry ();
|
||||
|
||||
|
||||
entry->factory = GST_TYPE_FIND_FACTORY (all_factories->data);
|
||||
entry->self = typefind;
|
||||
entry->probability = 0;
|
||||
typefind->possibilities = g_list_prepend (typefind->possibilities, entry);
|
||||
typefind->possibilities =
|
||||
g_list_prepend (typefind->possibilities, entry);
|
||||
all_factories = g_list_next (all_factories);
|
||||
}
|
||||
g_list_free (all_factories);
|
||||
}
|
||||
/* call every typefind function once */
|
||||
walk = entries = typefind->possibilities;
|
||||
GST_INFO_OBJECT (typefind, "iterating %u typefinding functions", g_list_length (entries));
|
||||
GST_INFO_OBJECT (typefind, "iterating %u typefinding functions",
|
||||
g_list_length (entries));
|
||||
typefind->possibilities = NULL;
|
||||
while (walk) {
|
||||
find.data = entry = (TypeFindEntry *) walk->data;
|
||||
|
@ -529,16 +559,19 @@ gst_type_find_element_chain (GstPad *pad, GstData *data)
|
|||
gst_type_find_factory_call_function (entry->factory, &find);
|
||||
free_entry_buffers (entry);
|
||||
if (entry->probability == 0 && entry->requested_size == 0) {
|
||||
GST_DEBUG_OBJECT (typefind, "'%s' was removed - no chance of being the right plugin",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory));
|
||||
GST_DEBUG_OBJECT (typefind,
|
||||
"'%s' was removed - no chance of being the right plugin",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory));
|
||||
free_entry (entry);
|
||||
} else if (entry->probability >= typefind->max_probability) {
|
||||
/* wooha, got caps */
|
||||
GstCaps *found_caps = entry->caps;
|
||||
guint probability = entry->probability;
|
||||
|
||||
GST_INFO_OBJECT (typefind, "'%s' returned %u/%u probability, using it NOW",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), probability, typefind->max_probability);
|
||||
|
||||
GST_INFO_OBJECT (typefind,
|
||||
"'%s' returned %u/%u probability, using it NOW",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), probability,
|
||||
typefind->max_probability);
|
||||
while (walk) {
|
||||
free_entry ((TypeFindEntry *) walk->data);
|
||||
walk = g_list_next (walk);
|
||||
|
@ -549,11 +582,13 @@ gst_type_find_element_chain (GstPad *pad, GstData *data)
|
|||
walk = g_list_next (walk);
|
||||
}
|
||||
typefind->possibilities = NULL;
|
||||
g_list_free (typefind->possibilities);
|
||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0, probability, found_caps);
|
||||
g_list_free (typefind->possibilities);
|
||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
|
||||
probability, found_caps);
|
||||
free_entry (entry);
|
||||
} else {
|
||||
typefind->possibilities = g_list_prepend (typefind->possibilities, entry);
|
||||
typefind->possibilities =
|
||||
g_list_prepend (typefind->possibilities, entry);
|
||||
}
|
||||
}
|
||||
g_list_free (entries);
|
||||
|
@ -564,8 +599,9 @@ gst_type_find_element_chain (GstPad *pad, GstData *data)
|
|||
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
|
||||
} else {
|
||||
/* set up typefind element for next iteration */
|
||||
typefind->possibilities = g_list_sort (typefind->possibilities, compare_type_find_entry);
|
||||
|
||||
typefind->possibilities =
|
||||
g_list_sort (typefind->possibilities, compare_type_find_entry);
|
||||
|
||||
/* look for typefind functions that require data without seeking */
|
||||
for (walk = typefind->possibilities; walk; walk = g_list_next (walk)) {
|
||||
entry = (TypeFindEntry *) walk->data;
|
||||
|
@ -582,19 +618,27 @@ gst_type_find_element_chain (GstPad *pad, GstData *data)
|
|||
gint64 seek_offset;
|
||||
GstEvent *event;
|
||||
|
||||
seek_offset = entry->requested_offset > 0 ? entry->requested_offset :
|
||||
find_element_get_length (entry) + entry->requested_offset;
|
||||
seek_offset += gst_buffer_store_get_size (typefind->store, seek_offset);
|
||||
event = gst_event_new_seek (GST_FORMAT_BYTES | GST_SEEK_METHOD_SET, seek_offset);
|
||||
seek_offset =
|
||||
entry->requested_offset >
|
||||
0 ? entry->
|
||||
requested_offset : find_element_get_length (entry) +
|
||||
entry->requested_offset;
|
||||
seek_offset +=
|
||||
gst_buffer_store_get_size (typefind->store, seek_offset);
|
||||
event =
|
||||
gst_event_new_seek (GST_FORMAT_BYTES | GST_SEEK_METHOD_SET,
|
||||
seek_offset);
|
||||
if (gst_pad_send_event (GST_PAD_PEER (typefind->sink), event)) {
|
||||
/* done seeking */
|
||||
GST_DEBUG_OBJECT (typefind, "'%s' was reset - seeked to %"G_GINT64_FORMAT,
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), seek_offset);
|
||||
GST_DEBUG_OBJECT (typefind,
|
||||
"'%s' was reset - seeked to %" G_GINT64_FORMAT,
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), seek_offset);
|
||||
break;
|
||||
} else if (entry->requested_offset < 0) {
|
||||
/* impossible to seek */
|
||||
GST_DEBUG_OBJECT (typefind, "'%s' was reset - couldn't seek to %"G_GINT64_FORMAT,
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), seek_offset);
|
||||
GST_DEBUG_OBJECT (typefind,
|
||||
"'%s' was reset - couldn't seek to %" G_GINT64_FORMAT,
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), seek_offset);
|
||||
entry->requested_size = 0;
|
||||
entry->requested_offset = 0;
|
||||
}
|
||||
|
@ -605,21 +649,26 @@ gst_type_find_element_chain (GstPad *pad, GstData *data)
|
|||
walk = g_list_next (typefind->possibilities);
|
||||
while (walk) {
|
||||
GList *cur = walk;
|
||||
|
||||
entry = (TypeFindEntry *) walk->data;
|
||||
walk = g_list_next (walk);
|
||||
if (entry->requested_size == 0) {
|
||||
GST_DEBUG_OBJECT (typefind, "'%s' was removed - higher possibilities available",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory));
|
||||
GST_DEBUG_OBJECT (typefind,
|
||||
"'%s' was removed - higher possibilities available",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory));
|
||||
free_entry (entry);
|
||||
typefind->possibilities = g_list_delete_link (typefind->possibilities, cur);
|
||||
typefind->possibilities =
|
||||
g_list_delete_link (typefind->possibilities, cur);
|
||||
}
|
||||
}
|
||||
if (g_list_next (typefind->possibilities) == NULL) {
|
||||
entry = (TypeFindEntry *) typefind->possibilities->data;
|
||||
if (entry->probability > typefind->min_probability) {
|
||||
GST_INFO_OBJECT (typefind, "'%s' is the only typefind left, using it now (probability %u)",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
|
||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0, entry->probability, entry->caps);
|
||||
GST_INFO_OBJECT (typefind,
|
||||
"'%s' is the only typefind left, using it now (probability %u)",
|
||||
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
|
||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
||||
0, entry->probability, entry->caps);
|
||||
free_entry (entry);
|
||||
g_list_free (typefind->possibilities);
|
||||
typefind->possibilities = NULL;
|
||||
|
@ -635,7 +684,7 @@ gst_type_find_element_chain (GstPad *pad, GstData *data)
|
|||
}
|
||||
}
|
||||
static GstElementStateReturn
|
||||
gst_type_find_element_change_state (GstElement *element)
|
||||
gst_type_find_element_change_state (GstElement * element)
|
||||
{
|
||||
GstTypeFindElement *typefind;
|
||||
|
||||
|
@ -652,6 +701,6 @@ gst_type_find_element_change_state (GstElement *element)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
}
|
||||
|
|
|
@ -29,48 +29,44 @@
|
|||
#include "gstbufferstore.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
|
||||
#define GST_TYPE_TYPE_FIND_ELEMENT (gst_type_find_element_get_type ())
|
||||
#define GST_TYPE_FIND_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TYPE_FIND_ELEMENT, GstTypeFindElement))
|
||||
#define GST_IS_TYPE_FIND_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TYPE_FIND_ELEMENT))
|
||||
#define GST_TYPE_FIND_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TYPE_FIND_ELEMENT, GstTypeFindElementClass))
|
||||
#define GST_IS_TYPE_FIND_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TYPE_FIND_ELEMENT))
|
||||
#define GST_TYPE_FIND_ELEMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TYPE_FIND_ELEMENT, GstTypeFindElementClass))
|
||||
typedef struct _GstTypeFindElement GstTypeFindElement;
|
||||
typedef struct _GstTypeFindElementClass GstTypeFindElementClass;
|
||||
|
||||
typedef struct _GstTypeFindElement GstTypeFindElement;
|
||||
typedef struct _GstTypeFindElementClass GstTypeFindElementClass;
|
||||
struct _GstTypeFindElement
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
struct _GstTypeFindElement {
|
||||
GstElement element;
|
||||
GstPad *sink;
|
||||
GstPad *src;
|
||||
|
||||
GstPad * sink;
|
||||
GstPad * src;
|
||||
guint min_probability;
|
||||
guint max_probability;
|
||||
GstCaps *caps;
|
||||
|
||||
guint min_probability;
|
||||
guint max_probability;
|
||||
GstCaps * caps;
|
||||
guint mode;
|
||||
GstBufferStore *store;
|
||||
guint64 stream_length;
|
||||
gboolean stream_length_available;
|
||||
|
||||
guint mode;
|
||||
GstBufferStore * store;
|
||||
guint64 stream_length;
|
||||
gboolean stream_length_available;
|
||||
|
||||
GList * possibilities;
|
||||
GList *possibilities;
|
||||
};
|
||||
|
||||
struct _GstTypeFindElementClass {
|
||||
GstElementClass parent_class;
|
||||
struct _GstTypeFindElementClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*have_type) (GstTypeFindElement *element,
|
||||
guint probability,
|
||||
const GstCaps * caps);
|
||||
void (*have_type) (GstTypeFindElement * element,
|
||||
guint probability, const GstCaps * caps);
|
||||
};
|
||||
|
||||
GType gst_type_find_element_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_TYPE_FIND_ELEMENT_H__ */
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#ifndef __GST_I18N_APP_H__
|
||||
#define __GST_I18N_APP_H__
|
||||
|
||||
#include "gettext.h" /* included with gettext distribution and copied */
|
||||
#include "gettext.h" /* included with gettext distribution and copied */
|
||||
|
||||
/* we want to use shorthand _() for translating and N_() for marking */
|
||||
#define _(String) gettext (String)
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#ifndef __GST_I18N_LIB_H__
|
||||
#define __GST_I18N_LIB_H__
|
||||
|
||||
#include "gettext.h" /* included with gettext distribution and copied */
|
||||
#include "gettext.h" /* included with gettext distribution and copied */
|
||||
|
||||
#ifndef GETTEXT_PACKAGE
|
||||
#error You must define GETTEXT_PACKAGE before including this header.
|
||||
|
|
360
gst/gst.c
360
gst/gst.c
|
@ -53,6 +53,7 @@ static gboolean _gst_use_threads = TRUE;
|
|||
static gboolean _gst_enable_cpu_opt = TRUE;
|
||||
|
||||
static gboolean gst_initialized = FALSE;
|
||||
|
||||
/* this will be set in popt callbacks when a problem has been encountered */
|
||||
static gboolean _gst_initialization_failure = FALSE;
|
||||
extern gint _gst_trace_on;
|
||||
|
@ -63,23 +64,20 @@ gboolean _gst_disable_segtrap = FALSE;
|
|||
extern GThreadFunctions gst_thread_dummy_functions;
|
||||
|
||||
|
||||
static void load_plugin_func (gpointer data, gpointer user_data);
|
||||
static void init_popt_callback (poptContext context,
|
||||
enum poptCallbackReason reason,
|
||||
const GstPoptOption *option,
|
||||
const char *arg, void *data);
|
||||
static gboolean init_pre (void);
|
||||
static gboolean init_post (void);
|
||||
static void load_plugin_func (gpointer data, gpointer user_data);
|
||||
static void init_popt_callback (poptContext context,
|
||||
enum poptCallbackReason reason,
|
||||
const GstPoptOption * option, const char *arg, void *data);
|
||||
static gboolean init_pre (void);
|
||||
static gboolean init_post (void);
|
||||
|
||||
static GSList *preload_plugins = NULL;
|
||||
|
||||
const gchar *g_log_domain_gstreamer = "GStreamer";
|
||||
|
||||
static void
|
||||
debug_log_handler (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *message,
|
||||
gpointer user_data)
|
||||
debug_log_handler (const gchar * log_domain,
|
||||
GLogLevelFlags log_level, const gchar * message, gpointer user_data)
|
||||
{
|
||||
g_log_default_handler (log_domain, log_level, message, user_data);
|
||||
/* FIXME: do we still need this ? fatal errors these days are all
|
||||
|
@ -87,8 +85,9 @@ debug_log_handler (const gchar *log_domain,
|
|||
/* g_on_error_query (NULL); */
|
||||
}
|
||||
|
||||
enum {
|
||||
ARG_VERSION=1,
|
||||
enum
|
||||
{
|
||||
ARG_VERSION = 1,
|
||||
ARG_FATAL_WARNINGS,
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
ARG_DEBUG_LEVEL,
|
||||
|
@ -114,27 +113,56 @@ enum {
|
|||
* the GST_SCHEDULER_DEFAULT_NAME define.
|
||||
*/
|
||||
static const GstPoptOption gstreamer_options[] = {
|
||||
{NULL, NUL, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST, (void *) &init_popt_callback, 0, NULL, NULL},
|
||||
{NULL, NUL, POPT_ARG_CALLBACK | POPT_CBFLAG_PRE | POPT_CBFLAG_POST,
|
||||
(void *) &init_popt_callback, 0, NULL, NULL},
|
||||
/* make sure we use our GETTEXT_PACKAGE as the domain for popt translations */
|
||||
{NULL, NUL, POPT_ARG_INTL_DOMAIN, GETTEXT_PACKAGE, 0, NULL, NULL},
|
||||
{"gst-version", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_VERSION, N_("Print the GStreamer version"), NULL},
|
||||
{"gst-fatal-warnings", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_FATAL_WARNINGS, N_("Make all warnings fatal"), NULL},
|
||||
{"gst-version", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL, ARG_VERSION,
|
||||
N_("Print the GStreamer version"), NULL},
|
||||
{"gst-fatal-warnings", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
|
||||
ARG_FATAL_WARNINGS, N_("Make all warnings fatal"), NULL},
|
||||
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
{"gst-debug-help", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_DEBUG_HELP, N_("Print available debug categories and exit"), NULL},
|
||||
{"gst-debug-level", NUL, POPT_ARG_INT|POPT_ARGFLAG_STRIP, NULL, ARG_DEBUG_LEVEL, N_("Default debug level from 1 (only error) to 5 (anything) or 0 for no output"), N_("LEVEL")},
|
||||
{"gst-debug", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_DEBUG, N_("Comma-separated list of category_name:level pairs to set specific levels for the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"), N_("LIST")},
|
||||
{"gst-debug-no-color", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_DEBUG_NO_COLOR, N_("Disable colored debugging output"), NULL},
|
||||
{"gst-debug-disable", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_DEBUG_DISABLE, N_("Disable debugging")},
|
||||
{"gst-debug-help", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
|
||||
ARG_DEBUG_HELP, N_("Print available debug categories and exit"), NULL},
|
||||
{"gst-debug-level", NUL, POPT_ARG_INT | POPT_ARGFLAG_STRIP, NULL,
|
||||
ARG_DEBUG_LEVEL,
|
||||
N_
|
||||
("Default debug level from 1 (only error) to 5 (anything) or 0 for no output"),
|
||||
N_("LEVEL")},
|
||||
{"gst-debug", NUL, POPT_ARG_STRING | POPT_ARGFLAG_STRIP, NULL, ARG_DEBUG,
|
||||
N_
|
||||
("Comma-separated list of category_name:level pairs to set specific levels for the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"),
|
||||
N_("LIST")},
|
||||
{"gst-debug-no-color", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
|
||||
ARG_DEBUG_NO_COLOR, N_("Disable colored debugging output"), NULL},
|
||||
{"gst-debug-disable", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
|
||||
ARG_DEBUG_DISABLE, N_("Disable debugging")},
|
||||
#endif
|
||||
|
||||
{"gst-disable-cpu-opt",NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_DISABLE_CPU_OPT,N_("Disable accelerated CPU instructions"), NULL},
|
||||
{"gst-plugin-spew", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_PLUGIN_SPEW, N_("Enable verbose plugin loading diagnostics"), NULL},
|
||||
{"gst-plugin-path", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_PLUGIN_PATH, N_("path list for loading plugins (separated by '" G_SEARCHPATH_SEPARATOR_S "')"),N_("PATHS")},
|
||||
{"gst-plugin-load", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_PLUGIN_LOAD, N_("Comma-separated list of plugins to preload in addition to the list stored in env variable GST_PLUGIN_PATH"), N_("PLUGINS")},
|
||||
{"gst-disable-segtrap",NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_SEGTRAP_DISABLE,N_("Disable trapping of segmentation faults during plugin loading"), NULL},
|
||||
{"gst-scheduler", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_SCHEDULER, N_("Scheduler to use ('"GST_SCHEDULER_DEFAULT_NAME"' is the default)"), N_("SCHEDULER")},
|
||||
{"gst-registry", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_REGISTRY, N_("Registry to use") , N_("REGISTRY")},
|
||||
{"gst-disable-cpu-opt", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
|
||||
ARG_DISABLE_CPU_OPT, N_("Disable accelerated CPU instructions"), NULL},
|
||||
{"gst-plugin-spew", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
|
||||
ARG_PLUGIN_SPEW, N_("Enable verbose plugin loading diagnostics"), NULL},
|
||||
{"gst-plugin-path", NUL, POPT_ARG_STRING | POPT_ARGFLAG_STRIP, NULL,
|
||||
ARG_PLUGIN_PATH,
|
||||
N_("path list for loading plugins (separated by '"
|
||||
G_SEARCHPATH_SEPARATOR_S "')"), N_("PATHS")},
|
||||
{"gst-plugin-load", NUL, POPT_ARG_STRING | POPT_ARGFLAG_STRIP, NULL,
|
||||
ARG_PLUGIN_LOAD,
|
||||
N_
|
||||
("Comma-separated list of plugins to preload in addition to the list stored in env variable GST_PLUGIN_PATH"),
|
||||
N_("PLUGINS")},
|
||||
{"gst-disable-segtrap", NUL, POPT_ARG_NONE | POPT_ARGFLAG_STRIP, NULL,
|
||||
ARG_SEGTRAP_DISABLE,
|
||||
N_("Disable trapping of segmentation faults during plugin loading"),
|
||||
NULL},
|
||||
{"gst-scheduler", NUL, POPT_ARG_STRING | POPT_ARGFLAG_STRIP, NULL,
|
||||
ARG_SCHEDULER,
|
||||
N_("Scheduler to use ('" GST_SCHEDULER_DEFAULT_NAME
|
||||
"' is the default)"), N_("SCHEDULER")},
|
||||
{"gst-registry", NUL, POPT_ARG_STRING | POPT_ARGFLAG_STRIP, NULL,
|
||||
ARG_REGISTRY, N_("Registry to use"), N_("REGISTRY")},
|
||||
POPT_TABLEEND
|
||||
};
|
||||
|
||||
|
@ -212,13 +240,14 @@ gst_init (int *argc, char **argv[])
|
|||
*/
|
||||
void
|
||||
gst_init_with_popt_table (int *argc, char **argv[],
|
||||
const GstPoptOption *popt_options)
|
||||
const GstPoptOption * popt_options)
|
||||
{
|
||||
if (!gst_init_check_with_popt_table (argc, argv, popt_options)) {
|
||||
g_print ("Could not initialize GStreamer !\n");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_init_check_with_popt_table:
|
||||
* @argc: pointer to application's argc
|
||||
|
@ -233,25 +262,29 @@ gst_init_with_popt_table (int *argc, char **argv[],
|
|||
*/
|
||||
gboolean
|
||||
gst_init_check_with_popt_table (int *argc, char **argv[],
|
||||
const GstPoptOption *popt_options)
|
||||
const GstPoptOption * popt_options)
|
||||
{
|
||||
poptContext context;
|
||||
gint nextopt;
|
||||
GstPoptOption *options;
|
||||
GstPoptOption options_with[] = {
|
||||
{NULL, NUL, POPT_ARG_INCLUDE_TABLE, poptHelpOptions, 0, "Help options:", NULL},
|
||||
{NULL, NUL, POPT_ARG_INCLUDE_TABLE, (GstPoptOption *) gstreamer_options, 0, "GStreamer options:", NULL},
|
||||
{NULL, NUL, POPT_ARG_INCLUDE_TABLE, (GstPoptOption *) popt_options, 0, "Application options:", NULL},
|
||||
{NULL, NUL, POPT_ARG_INCLUDE_TABLE, poptHelpOptions, 0, "Help options:",
|
||||
NULL},
|
||||
{NULL, NUL, POPT_ARG_INCLUDE_TABLE, (GstPoptOption *) gstreamer_options, 0,
|
||||
"GStreamer options:", NULL},
|
||||
{NULL, NUL, POPT_ARG_INCLUDE_TABLE, (GstPoptOption *) popt_options, 0,
|
||||
"Application options:", NULL},
|
||||
POPT_TABLEEND
|
||||
};
|
||||
GstPoptOption options_without[] = {
|
||||
{NULL, NUL, POPT_ARG_INCLUDE_TABLE, poptHelpOptions, 0, "Help options:", NULL},
|
||||
{NULL, NUL, POPT_ARG_INCLUDE_TABLE, (GstPoptOption *) gstreamer_options, 0, "GStreamer options:", NULL},
|
||||
{NULL, NUL, POPT_ARG_INCLUDE_TABLE, poptHelpOptions, 0, "Help options:",
|
||||
NULL},
|
||||
{NULL, NUL, POPT_ARG_INCLUDE_TABLE, (GstPoptOption *) gstreamer_options, 0,
|
||||
"GStreamer options:", NULL},
|
||||
POPT_TABLEEND
|
||||
};
|
||||
|
||||
if (gst_initialized)
|
||||
{
|
||||
if (gst_initialized) {
|
||||
GST_DEBUG ("already initialized gst");
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -260,8 +293,10 @@ gst_init_check_with_popt_table (int *argc, char **argv[],
|
|||
if (argc || argv)
|
||||
g_warning ("gst_init: Only one of argc or argv was NULL");
|
||||
|
||||
if (!init_pre ()) return FALSE;
|
||||
if (!init_post ()) return FALSE;
|
||||
if (!init_pre ())
|
||||
return FALSE;
|
||||
if (!init_post ())
|
||||
return FALSE;
|
||||
gst_initialized = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -271,21 +306,19 @@ gst_init_check_with_popt_table (int *argc, char **argv[],
|
|||
} else {
|
||||
options = options_with;
|
||||
}
|
||||
context = poptGetContext ("GStreamer", *argc, (const char**)*argv,
|
||||
options, 0);
|
||||
context = poptGetContext ("GStreamer", *argc, (const char **) *argv,
|
||||
options, 0);
|
||||
|
||||
while ((nextopt = poptGetNextOpt (context)) > 0)
|
||||
{
|
||||
while ((nextopt = poptGetNextOpt (context)) > 0) {
|
||||
/* we only check for failures here, actual work is done in callbacks */
|
||||
if (_gst_initialization_failure) return FALSE;
|
||||
if (_gst_initialization_failure)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nextopt != -1) {
|
||||
g_print ("Error on option %s: %s.\nRun '%s --help' "
|
||||
"to see a full list of available command line options.\n",
|
||||
poptBadOption (context, 0),
|
||||
poptStrerror (nextopt),
|
||||
(*argv)[0]);
|
||||
"to see a full list of available command line options.\n",
|
||||
poptBadOption (context, 0), poptStrerror (nextopt), (*argv)[0]);
|
||||
|
||||
poptFreeContext (context);
|
||||
return FALSE;
|
||||
|
@ -305,7 +338,7 @@ add_path_func (gpointer data, gpointer user_data)
|
|||
GstRegistry *registry = GST_REGISTRY (user_data);
|
||||
|
||||
GST_INFO ("Adding plugin path: \"%s\"", (gchar *) data);
|
||||
gst_registry_add_path (registry, (gchar *)data);
|
||||
gst_registry_add_path (registry, (gchar *) data);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -316,7 +349,7 @@ prepare_for_load_plugin_func (gpointer data, gpointer user_data)
|
|||
}
|
||||
|
||||
static void
|
||||
parse_debug_list (const gchar *list)
|
||||
parse_debug_list (const gchar * list)
|
||||
{
|
||||
gchar **split;
|
||||
gchar **walk;
|
||||
|
@ -326,16 +359,18 @@ parse_debug_list (const gchar *list)
|
|||
walk = split = g_strsplit (list, ",", 0);
|
||||
|
||||
while (walk[0]) {
|
||||
gchar **values = g_strsplit ( walk[0], ":", 2);
|
||||
gchar **values = g_strsplit (walk[0], ":", 2);
|
||||
|
||||
if (values[0] && values[1]) {
|
||||
gint level = 0;
|
||||
|
||||
g_strstrip (values[0]);
|
||||
g_strstrip (values[1]);
|
||||
level = strtol (values[1], NULL, 0);
|
||||
if (level >= 0 && level < GST_LEVEL_COUNT) {
|
||||
GST_DEBUG ("setting debugging to level %d for name \"%s\"",
|
||||
level, values[0]);
|
||||
gst_debug_set_threshold_for_name (values[0], level);
|
||||
GST_DEBUG ("setting debugging to level %d for name \"%s\"",
|
||||
level, values[0]);
|
||||
gst_debug_set_threshold_for_name (values[0], level);
|
||||
}
|
||||
}
|
||||
g_strfreev (values);
|
||||
|
@ -365,7 +400,8 @@ load_plugin_func (gpointer data, gpointer user_data)
|
|||
}
|
||||
|
||||
static void
|
||||
split_and_iterate (const gchar *stringlist, gchar *separator, GFunc iterator, gpointer user_data)
|
||||
split_and_iterate (const gchar * stringlist, gchar * separator, GFunc iterator,
|
||||
gpointer user_data)
|
||||
{
|
||||
gchar **strings;
|
||||
gint j = 0;
|
||||
|
@ -379,10 +415,10 @@ split_and_iterate (const gchar *stringlist, gchar *separator, GFunc iterator, gp
|
|||
while (strings[j]) {
|
||||
iterator (strings[j], user_data);
|
||||
if (++j == MAX_PATH_SPLIT) {
|
||||
lastlist = g_strdup (strings[j]);
|
||||
g_strfreev (strings);
|
||||
j=0;
|
||||
break;
|
||||
lastlist = g_strdup (strings[j]);
|
||||
g_strfreev (strings);
|
||||
j = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -404,7 +440,7 @@ init_pre (void)
|
|||
g_thread_init (&gst_thread_dummy_functions);
|
||||
}
|
||||
/* we need threading to be enabled right here */
|
||||
_gst_debug_init();
|
||||
_gst_debug_init ();
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
setlocale (LC_ALL, "");
|
||||
|
@ -426,7 +462,8 @@ init_pre (void)
|
|||
gchar *user_reg;
|
||||
const gchar *homedir;
|
||||
|
||||
_global_registry = gst_xml_registry_new ("global_registry", GLOBAL_REGISTRY_FILE);
|
||||
_global_registry =
|
||||
gst_xml_registry_new ("global_registry", GLOBAL_REGISTRY_FILE);
|
||||
|
||||
#ifdef PLUGINS_USE_BUILDDIR
|
||||
/* location libgstelements.so */
|
||||
|
@ -434,19 +471,17 @@ init_pre (void)
|
|||
gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/elements");
|
||||
gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/types");
|
||||
gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/autoplug");
|
||||
gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/schedulers");
|
||||
gst_registry_add_path (_global_registry,
|
||||
PLUGINS_BUILDDIR "/gst/schedulers");
|
||||
gst_registry_add_path (_global_registry, PLUGINS_BUILDDIR "/gst/indexers");
|
||||
#else
|
||||
/* add the main (installed) library path */
|
||||
gst_registry_add_path (_global_registry, PLUGINS_DIR);
|
||||
#endif /* PLUGINS_USE_BUILDDIR */
|
||||
|
||||
if (g_getenv ("GST_REGISTRY"))
|
||||
{
|
||||
if (g_getenv ("GST_REGISTRY")) {
|
||||
user_reg = g_strdup (g_getenv ("GST_REGISTRY"));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
homedir = g_get_home_dir ();
|
||||
user_reg = g_strjoin ("/", homedir, LOCAL_REGISTRY_FILE, NULL);
|
||||
}
|
||||
|
@ -460,13 +495,17 @@ init_pre (void)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_register_core_elements (GstPlugin *plugin)
|
||||
gst_register_core_elements (GstPlugin * plugin)
|
||||
{
|
||||
/* register some standard builtin types */
|
||||
g_assert (gst_element_register (plugin, "bin", GST_RANK_PRIMARY, GST_TYPE_BIN));
|
||||
g_assert (gst_element_register (plugin, "pipeline", GST_RANK_PRIMARY, GST_TYPE_PIPELINE));
|
||||
g_assert (gst_element_register (plugin, "thread", GST_RANK_PRIMARY, GST_TYPE_THREAD));
|
||||
g_assert (gst_element_register (plugin, "queue", GST_RANK_PRIMARY, GST_TYPE_QUEUE));
|
||||
g_assert (gst_element_register (plugin, "bin", GST_RANK_PRIMARY,
|
||||
GST_TYPE_BIN));
|
||||
g_assert (gst_element_register (plugin, "pipeline", GST_RANK_PRIMARY,
|
||||
GST_TYPE_PIPELINE));
|
||||
g_assert (gst_element_register (plugin, "thread", GST_RANK_PRIMARY,
|
||||
GST_TYPE_THREAD));
|
||||
g_assert (gst_element_register (plugin, "queue", GST_RANK_PRIMARY,
|
||||
GST_TYPE_QUEUE));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -502,6 +541,7 @@ init_post (void)
|
|||
{
|
||||
GLogLevelFlags llf;
|
||||
const gchar *plugin_path;
|
||||
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
GstTrace *gst_trace;
|
||||
#endif /* GST_DISABLE_TRACE */
|
||||
|
@ -510,7 +550,7 @@ init_post (void)
|
|||
g_log_set_handler (g_log_domain_gstreamer, llf, debug_log_handler, NULL);
|
||||
|
||||
GST_INFO ("Initializing GStreamer Core Library version %s %s",
|
||||
VERSION, _gst_use_threads ? "" : "(no threads)");
|
||||
VERSION, _gst_use_threads ? "" : "(no threads)");
|
||||
|
||||
_gst_format_initialize ();
|
||||
_gst_query_type_initialize ();
|
||||
|
@ -532,7 +572,8 @@ init_post (void)
|
|||
|
||||
plugin_path = g_getenv ("GST_PLUGIN_PATH");
|
||||
#ifndef GST_DISABLE_REGISTRY
|
||||
split_and_iterate (plugin_path, G_SEARCHPATH_SEPARATOR_S, add_path_func, _global_registry);
|
||||
split_and_iterate (plugin_path, G_SEARCHPATH_SEPARATOR_S, add_path_func,
|
||||
_global_registry);
|
||||
#endif /* GST_DISABLE_REGISTRY */
|
||||
|
||||
/* register core plugins */
|
||||
|
@ -551,7 +592,8 @@ init_post (void)
|
|||
if (!_gst_registry_fixed) {
|
||||
/* don't override command-line options */
|
||||
if (g_getenv ("GST_REGISTRY")) {
|
||||
g_object_set (_global_registry, "location", g_getenv ("GST_REGISTRY"), NULL);
|
||||
g_object_set (_global_registry, "location", g_getenv ("GST_REGISTRY"),
|
||||
NULL);
|
||||
_gst_registry_fixed = TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -574,7 +616,6 @@ init_post (void)
|
|||
g_slist_free (preload_plugins);
|
||||
preload_plugins = NULL;
|
||||
}
|
||||
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
_gst_trace_on = 0;
|
||||
if (_gst_trace_on) {
|
||||
|
@ -594,7 +635,7 @@ static gint
|
|||
sort_by_category_name (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
return strcmp (gst_debug_category_get_name ((GstDebugCategory *) a),
|
||||
gst_debug_category_get_name ((GstDebugCategory *) b));
|
||||
gst_debug_category_get_name ((GstDebugCategory *) b));
|
||||
}
|
||||
static void
|
||||
gst_debug_help (void)
|
||||
|
@ -608,14 +649,18 @@ gst_debug_help (void)
|
|||
walk2 = list2 = gst_registry_pool_plugin_list ();
|
||||
while (walk2) {
|
||||
GstPlugin *plugin = GST_PLUGIN (walk2->data);
|
||||
|
||||
walk2 = g_list_next (walk2);
|
||||
|
||||
if (!gst_plugin_is_loaded (plugin)) {
|
||||
#ifndef GST_DISABLE_REGISTRY
|
||||
if (GST_IS_REGISTRY (plugin->manager)) {
|
||||
GST_CAT_LOG (GST_CAT_PLUGIN_LOADING, "loading plugin %s", plugin->desc.name);
|
||||
if (gst_registry_load_plugin (GST_REGISTRY (plugin->manager), plugin) != GST_REGISTRY_OK)
|
||||
GST_CAT_WARNING (GST_CAT_PLUGIN_LOADING, "loading plugin %s failed", plugin->desc.name);
|
||||
GST_CAT_LOG (GST_CAT_PLUGIN_LOADING, "loading plugin %s",
|
||||
plugin->desc.name);
|
||||
if (gst_registry_load_plugin (GST_REGISTRY (plugin->manager),
|
||||
plugin) != GST_REGISTRY_OK)
|
||||
GST_CAT_WARNING (GST_CAT_PLUGIN_LOADING, "loading plugin %s failed",
|
||||
plugin->desc.name);
|
||||
}
|
||||
#endif /* GST_DISABLE_REGISTRY */
|
||||
}
|
||||
|
@ -634,19 +679,19 @@ gst_debug_help (void)
|
|||
|
||||
if (gst_debug_is_colored ()) {
|
||||
gchar *color = gst_debug_construct_term_color (cat->color);
|
||||
|
||||
g_print ("%s%-20s\033[00m %1d %s %s%s\033[00m\n",
|
||||
color,
|
||||
gst_debug_category_get_name (cat),
|
||||
gst_debug_category_get_threshold (cat),
|
||||
gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
|
||||
color,
|
||||
gst_debug_category_get_description (cat));
|
||||
color,
|
||||
gst_debug_category_get_name (cat),
|
||||
gst_debug_category_get_threshold (cat),
|
||||
gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
|
||||
color, gst_debug_category_get_description (cat));
|
||||
g_free (color);
|
||||
} else {
|
||||
g_print ("%-20s %1d %s %s\n", gst_debug_category_get_name (cat),
|
||||
gst_debug_category_get_threshold (cat),
|
||||
gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
|
||||
gst_debug_category_get_description (cat));
|
||||
gst_debug_category_get_threshold (cat),
|
||||
gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
|
||||
gst_debug_category_get_description (cat));
|
||||
}
|
||||
walk = g_slist_next (walk);
|
||||
}
|
||||
|
@ -657,82 +702,86 @@ gst_debug_help (void)
|
|||
|
||||
static void
|
||||
init_popt_callback (poptContext context, enum poptCallbackReason reason,
|
||||
const GstPoptOption *option, const char *arg, void *data)
|
||||
const GstPoptOption * option, const char *arg, void *data)
|
||||
{
|
||||
GLogLevelFlags fatal_mask;
|
||||
|
||||
if (gst_initialized)
|
||||
return;
|
||||
switch (reason) {
|
||||
case POPT_CALLBACK_REASON_PRE:
|
||||
if (!init_pre ()) _gst_initialization_failure = TRUE;
|
||||
break;
|
||||
case POPT_CALLBACK_REASON_OPTION:
|
||||
switch (option->val) {
|
||||
case ARG_VERSION:
|
||||
g_print ("GStreamer Core Library version %s\n", GST_VERSION);
|
||||
exit (0);
|
||||
case ARG_FATAL_WARNINGS:
|
||||
fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
|
||||
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
|
||||
g_log_set_always_fatal (fatal_mask);
|
||||
case POPT_CALLBACK_REASON_PRE:
|
||||
if (!init_pre ())
|
||||
_gst_initialization_failure = TRUE;
|
||||
break;
|
||||
case POPT_CALLBACK_REASON_OPTION:
|
||||
switch (option->val) {
|
||||
case ARG_VERSION:
|
||||
g_print ("GStreamer Core Library version %s\n", GST_VERSION);
|
||||
exit (0);
|
||||
case ARG_FATAL_WARNINGS:
|
||||
fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
|
||||
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
|
||||
g_log_set_always_fatal (fatal_mask);
|
||||
break;
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
case ARG_DEBUG_LEVEL: {
|
||||
gint tmp = 0;
|
||||
tmp = strtol (arg, NULL, 0);
|
||||
if (tmp >= 0 && tmp < GST_LEVEL_COUNT) {
|
||||
gst_debug_set_default_threshold (tmp);
|
||||
case ARG_DEBUG_LEVEL:{
|
||||
gint tmp = 0;
|
||||
|
||||
tmp = strtol (arg, NULL, 0);
|
||||
if (tmp >= 0 && tmp < GST_LEVEL_COUNT) {
|
||||
gst_debug_set_default_threshold (tmp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARG_DEBUG:
|
||||
parse_debug_list (arg);
|
||||
break;
|
||||
case ARG_DEBUG_NO_COLOR:
|
||||
gst_debug_set_colored (FALSE);
|
||||
break;
|
||||
case ARG_DEBUG_DISABLE:
|
||||
gst_debug_set_active (FALSE);
|
||||
break;
|
||||
case ARG_DEBUG_HELP:
|
||||
gst_debug_help ();
|
||||
exit (0);
|
||||
#endif
|
||||
case ARG_DISABLE_CPU_OPT:
|
||||
_gst_enable_cpu_opt = FALSE;
|
||||
break;
|
||||
case ARG_PLUGIN_SPEW:
|
||||
break;
|
||||
case ARG_PLUGIN_PATH:
|
||||
#ifndef GST_DISABLE_REGISTRY
|
||||
split_and_iterate (arg, G_SEARCHPATH_SEPARATOR_S, add_path_func,
|
||||
_user_registry);
|
||||
#endif /* GST_DISABLE_REGISTRY */
|
||||
break;
|
||||
case ARG_PLUGIN_LOAD:
|
||||
split_and_iterate (arg, ",", prepare_for_load_plugin_func, NULL);
|
||||
break;
|
||||
case ARG_SEGTRAP_DISABLE:
|
||||
_gst_disable_segtrap = TRUE;
|
||||
break;
|
||||
case ARG_SCHEDULER:
|
||||
gst_scheduler_factory_set_default_name (arg);
|
||||
break;
|
||||
case ARG_REGISTRY:
|
||||
#ifndef GST_DISABLE_REGISTRY
|
||||
g_object_set (G_OBJECT (_user_registry), "location", arg, NULL);
|
||||
_gst_registry_fixed = TRUE;
|
||||
#endif /* GST_DISABLE_REGISTRY */
|
||||
break;
|
||||
default:
|
||||
g_warning ("option %d not recognized", option->val);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARG_DEBUG:
|
||||
parse_debug_list (arg);
|
||||
case POPT_CALLBACK_REASON_POST:
|
||||
if (!init_post ())
|
||||
_gst_initialization_failure = TRUE;
|
||||
gst_initialized = TRUE;
|
||||
break;
|
||||
case ARG_DEBUG_NO_COLOR:
|
||||
gst_debug_set_colored (FALSE);
|
||||
break;
|
||||
case ARG_DEBUG_DISABLE:
|
||||
gst_debug_set_active (FALSE);
|
||||
break;
|
||||
case ARG_DEBUG_HELP:
|
||||
gst_debug_help ();
|
||||
exit (0);
|
||||
#endif
|
||||
case ARG_DISABLE_CPU_OPT:
|
||||
_gst_enable_cpu_opt = FALSE;
|
||||
break;
|
||||
case ARG_PLUGIN_SPEW:
|
||||
break;
|
||||
case ARG_PLUGIN_PATH:
|
||||
#ifndef GST_DISABLE_REGISTRY
|
||||
split_and_iterate (arg, G_SEARCHPATH_SEPARATOR_S, add_path_func, _user_registry);
|
||||
#endif /* GST_DISABLE_REGISTRY */
|
||||
break;
|
||||
case ARG_PLUGIN_LOAD:
|
||||
split_and_iterate (arg, ",", prepare_for_load_plugin_func, NULL);
|
||||
break;
|
||||
case ARG_SEGTRAP_DISABLE:
|
||||
_gst_disable_segtrap = TRUE;
|
||||
break;
|
||||
case ARG_SCHEDULER:
|
||||
gst_scheduler_factory_set_default_name (arg);
|
||||
break;
|
||||
case ARG_REGISTRY:
|
||||
#ifndef GST_DISABLE_REGISTRY
|
||||
g_object_set (G_OBJECT (_user_registry), "location", arg, NULL);
|
||||
_gst_registry_fixed = TRUE;
|
||||
#endif /* GST_DISABLE_REGISTRY */
|
||||
break;
|
||||
default:
|
||||
g_warning ("option %d not recognized", option->val);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case POPT_CALLBACK_REASON_POST:
|
||||
if (!init_post ()) _gst_initialization_failure = TRUE;
|
||||
gst_initialized = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -802,6 +851,7 @@ gst_main_quit (void)
|
|||
g_error ("Quit more loops than there are");
|
||||
else {
|
||||
GMainLoop *loop = mainloops->data;
|
||||
|
||||
mainloops = g_slist_delete_link (mainloops, mainloops);
|
||||
g_main_loop_quit (loop);
|
||||
g_main_loop_unref (loop);
|
||||
|
@ -817,7 +867,7 @@ gst_main_quit (void)
|
|||
* Gets the version number of the GStreamer library.
|
||||
*/
|
||||
void
|
||||
gst_version (guint *major, guint *minor, guint *micro)
|
||||
gst_version (guint * major, guint * minor, guint * micro)
|
||||
{
|
||||
g_return_if_fail (major);
|
||||
g_return_if_fail (minor);
|
||||
|
|
27
gst/gst.h
27
gst/gst.h
|
@ -69,31 +69,26 @@
|
|||
#include <gst/gstcompat.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* make our own type for poptOption because the struct poptOption
|
||||
* definition is iffy */
|
||||
typedef struct poptOption GstPoptOption;
|
||||
|
||||
/* initialize GST */
|
||||
void gst_init (int *argc, char **argv[]);
|
||||
gboolean gst_init_check (int *argc, char **argv[]);
|
||||
void gst_init_with_popt_table (int *argc, char **argv[],
|
||||
const GstPoptOption
|
||||
*popt_options);
|
||||
gboolean gst_init_check_with_popt_table (int *argc, char **argv[],
|
||||
const GstPoptOption
|
||||
*popt_options);
|
||||
void gst_init (int *argc, char **argv[]);
|
||||
gboolean gst_init_check (int *argc, char **argv[]);
|
||||
void gst_init_with_popt_table (int *argc, char **argv[],
|
||||
const GstPoptOption * popt_options);
|
||||
gboolean gst_init_check_with_popt_table (int *argc, char **argv[],
|
||||
const GstPoptOption * popt_options);
|
||||
|
||||
const GstPoptOption * gst_init_get_popt_table (void);
|
||||
const GstPoptOption *gst_init_get_popt_table (void);
|
||||
|
||||
void gst_use_threads (gboolean use_threads);
|
||||
gboolean gst_has_threads (void);
|
||||
void gst_use_threads (gboolean use_threads);
|
||||
gboolean gst_has_threads (void);
|
||||
|
||||
void gst_main (void);
|
||||
void gst_main_quit (void);
|
||||
void gst_main (void);
|
||||
void gst_main_quit (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#include <gst/gstlog.h>
|
||||
|
||||
#endif /* __GST_H__ */
|
||||
|
|
|
@ -47,17 +47,18 @@
|
|||
|
||||
#define GST_ARCH_SET_SP(stackpointer) \
|
||||
__asm__("lwz r1,%0" : : "m"(stackpointer))
|
||||
|
||||
|
||||
#define GST_ARCH_CALL(target) \
|
||||
__asm__( "mr r0,%0\n\t" \
|
||||
"mtlr r0\n\t" \
|
||||
"blrl" : : "r"(target) );
|
||||
|
||||
struct minimal_ppc_stackframe {
|
||||
unsigned long back_chain;
|
||||
unsigned long LR_save;
|
||||
unsigned long unused1;
|
||||
unsigned long unused2;
|
||||
|
||||
struct minimal_ppc_stackframe
|
||||
{
|
||||
unsigned long back_chain;
|
||||
unsigned long LR_save;
|
||||
unsigned long unused1;
|
||||
unsigned long unused2;
|
||||
};
|
||||
|
||||
#define GST_ARCH_SETUP_STACK(sp) \
|
||||
|
@ -79,11 +80,12 @@ struct minimal_ppc_stackframe {
|
|||
/* Need to get more information about the stackframe format
|
||||
* and get the fields more correct. Check GDB sources maybe?
|
||||
*/
|
||||
struct minimal_stackframe {
|
||||
unsigned long back_chain;
|
||||
unsigned long LR_save;
|
||||
unsigned long unused1;
|
||||
unsigned long unused2;
|
||||
struct minimal_stackframe
|
||||
{
|
||||
unsigned long back_chain;
|
||||
unsigned long LR_save;
|
||||
unsigned long unused1;
|
||||
unsigned long unused2;
|
||||
};
|
||||
|
||||
#define GST_ARCH_SETUP_STACK(sp) \
|
||||
|
@ -141,7 +143,7 @@ struct minimal_stackframe {
|
|||
|
||||
/* assuming the stackframe is 16 bytes */
|
||||
#define GST_ARCH_SETUP_STACK(sp) sp -= 4
|
||||
|
||||
|
||||
|
||||
|
||||
/***** HP-PA *****/
|
||||
|
@ -167,11 +169,12 @@ struct minimal_stackframe {
|
|||
#define GST_ARCH_CALL(target) \
|
||||
__asm__( "basr 14,%0" : : "a"(target) );
|
||||
|
||||
struct minimal_s390_stackframe {
|
||||
unsigned long back_chain;
|
||||
unsigned long reserved;
|
||||
unsigned long greg[14];
|
||||
double freg[4];
|
||||
struct minimal_s390_stackframe
|
||||
{
|
||||
unsigned long back_chain;
|
||||
unsigned long reserved;
|
||||
unsigned long greg[14];
|
||||
double freg[4];
|
||||
};
|
||||
|
||||
#define GST_ARCH_SETUP_STACK(sp) \
|
||||
|
|
|
@ -22,4 +22,3 @@
|
|||
|
||||
#include "gstatomic.h"
|
||||
#include "gstatomic_impl.h"
|
||||
|
||||
|
|
|
@ -22,27 +22,25 @@
|
|||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef volatile gint gst_vgint; /* gtk-doc volatile workaround */
|
||||
G_BEGIN_DECLS typedef volatile gint gst_vgint; /* gtk-doc volatile workaround */
|
||||
|
||||
typedef struct _GstAtomicInt GstAtomicInt;
|
||||
|
||||
struct _GstAtomicInt {
|
||||
gst_vgint counter;
|
||||
GMutex *lock; /* for C fallback */
|
||||
struct _GstAtomicInt
|
||||
{
|
||||
gst_vgint counter;
|
||||
GMutex *lock; /* for C fallback */
|
||||
};
|
||||
|
||||
|
||||
void gst_atomic_int_init (GstAtomicInt *aint, gint val);
|
||||
void gst_atomic_int_destroy (GstAtomicInt *aint);
|
||||
void gst_atomic_int_set (GstAtomicInt *aint, gint val);
|
||||
gint gst_atomic_int_read (GstAtomicInt *aint);
|
||||
void gst_atomic_int_add (GstAtomicInt *aint, gint val);
|
||||
void gst_atomic_int_inc (GstAtomicInt *aint);
|
||||
gboolean gst_atomic_int_dec_and_test (GstAtomicInt *aint);
|
||||
void gst_atomic_int_init (GstAtomicInt * aint, gint val);
|
||||
void gst_atomic_int_destroy (GstAtomicInt * aint);
|
||||
void gst_atomic_int_set (GstAtomicInt * aint, gint val);
|
||||
gint gst_atomic_int_read (GstAtomicInt * aint);
|
||||
void gst_atomic_int_add (GstAtomicInt * aint, gint val);
|
||||
void gst_atomic_int_inc (GstAtomicInt * aint);
|
||||
gboolean gst_atomic_int_dec_and_test (GstAtomicInt * aint);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_ATOMIC_H__ */
|
||||
|
|
|
@ -34,57 +34,62 @@
|
|||
#include "gstmacros.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#if defined (GST_CAN_INLINE) || defined (__GST_ATOMIC_C__)
|
||||
|
||||
/***** Intel x86 *****/
|
||||
#if defined (HAVE_CPU_I386) && defined(__GNUC__)
|
||||
|
||||
#ifdef GST_CONFIG_NO_SMP
|
||||
#define SMP_LOCK ""
|
||||
#else
|
||||
#define SMP_LOCK "lock ; "
|
||||
#endif
|
||||
|
||||
GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = val; }
|
||||
GST_INLINE_FUNC void gst_atomic_int_destroy (GstAtomicInt *aint) { }
|
||||
GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = val; }
|
||||
GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { return aint->counter; }
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_add (GstAtomicInt *aint, gint val)
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_init (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
SMP_LOCK "addl %1,%0"
|
||||
:"=m" (aint->counter)
|
||||
aint->counter = val;
|
||||
}
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_destroy (GstAtomicInt * aint)
|
||||
{
|
||||
}
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_set (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
aint->counter = val;
|
||||
}
|
||||
GST_INLINE_FUNC gint
|
||||
gst_atomic_int_read (GstAtomicInt * aint)
|
||||
{
|
||||
return aint->counter;
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_add (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
__asm__ __volatile__ (SMP_LOCK "addl %1,%0":"=m" (aint->counter)
|
||||
:"ir" (val), "m" (aint->counter));
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_inc (GstAtomicInt *aint)
|
||||
gst_atomic_int_inc (GstAtomicInt * aint)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
SMP_LOCK "incl %0"
|
||||
:"=m" (aint->counter)
|
||||
__asm__ __volatile__ (SMP_LOCK "incl %0":"=m" (aint->counter)
|
||||
:"m" (aint->counter));
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC gboolean
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt *aint)
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt * aint)
|
||||
{
|
||||
guchar res;
|
||||
|
||||
__asm__ __volatile__(
|
||||
SMP_LOCK "decl %0; sete %1"
|
||||
:"=m" (aint->counter), "=qm" (res)
|
||||
:"m" (aint->counter) : "memory");
|
||||
__asm__ __volatile__ (SMP_LOCK "decl %0; sete %1":"=m" (aint->counter),
|
||||
"=qm" (res)
|
||||
:"m" (aint->counter):"memory");
|
||||
|
||||
return res != 0;
|
||||
}
|
||||
|
||||
/***** PowerPC *****/
|
||||
#elif defined (HAVE_CPU_PPC) && defined(__GNUC__)
|
||||
|
||||
#ifdef GST_CONFIG_NO_SMP
|
||||
#define SMP_SYNC ""
|
||||
#define SMP_ISYNC
|
||||
|
@ -92,7 +97,6 @@ gst_atomic_int_dec_and_test (GstAtomicInt *aint)
|
|||
#define SMP_SYNC "\tsync\n"
|
||||
#define SMP_ISYNC "\tisync\n"
|
||||
#endif
|
||||
|
||||
/* Erratum #77 on the 405 means we need a sync or dcbt before every stwcx.
|
||||
* The old ATOMIC_SYNC_FIX covered some but not all of this.
|
||||
*/
|
||||
|
@ -101,111 +105,123 @@ gst_atomic_int_dec_and_test (GstAtomicInt *aint)
|
|||
#else
|
||||
#define PPC405_ERR77(ra,rb)
|
||||
#endif
|
||||
|
||||
GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = val; }
|
||||
GST_INLINE_FUNC void gst_atomic_int_destroy (GstAtomicInt *aint) { }
|
||||
GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = val; }
|
||||
GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { return aint->counter; }
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_add (GstAtomicInt *aint, gint val)
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_init (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
int t;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: lwarx %0,0,%3\n"
|
||||
" add %0,%2,%0\n"
|
||||
PPC405_ERR77(0,%3)
|
||||
" stwcx. %0,0,%3 \n"
|
||||
" bne- 1b\n"
|
||||
: "=&r" (t), "=m" (aint->counter)
|
||||
: "r" (val), "r" (&aint->counter), "m" (aint->counter)
|
||||
: "cc");
|
||||
aint->counter = val;
|
||||
}
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_destroy (GstAtomicInt * aint)
|
||||
{
|
||||
}
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_set (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
aint->counter = val;
|
||||
}
|
||||
GST_INLINE_FUNC gint
|
||||
gst_atomic_int_read (GstAtomicInt * aint)
|
||||
{
|
||||
return aint->counter;
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_inc (GstAtomicInt *aint)
|
||||
gst_atomic_int_add (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
int t;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: lwarx %0,0,%2\n"
|
||||
" addic %0,%0,1\n"
|
||||
PPC405_ERR77(0,%2)
|
||||
" stwcx. %0,0,%2\n"
|
||||
" bne- 1b\n"
|
||||
: "=&r" (t), "=m" (aint->counter)
|
||||
: "r" (&aint->counter), "m" (aint->counter)
|
||||
: "cc");
|
||||
__asm__ __volatile__ ("1: lwarx %0,0,%3\n"
|
||||
" add %0,%2,%0\n" PPC405_ERR77 (0, %3)
|
||||
" stwcx. %0,0,%3 \n"
|
||||
" bne- 1b\n":"=&r" (t), "=m" (aint->counter)
|
||||
:"r" (val), "r" (&aint->counter), "m" (aint->counter)
|
||||
:"cc");
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_inc (GstAtomicInt * aint)
|
||||
{
|
||||
int t;
|
||||
|
||||
__asm__ __volatile__ ("1: lwarx %0,0,%2\n"
|
||||
" addic %0,%0,1\n" PPC405_ERR77 (0, %2)
|
||||
" stwcx. %0,0,%2\n"
|
||||
" bne- 1b\n":"=&r" (t), "=m" (aint->counter)
|
||||
:"r" (&aint->counter), "m" (aint->counter)
|
||||
:"cc");
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC gboolean
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt *aint)
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt * aint)
|
||||
{
|
||||
int t;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: lwarx %0,0,%1\n"
|
||||
" addic %0,%0,-1\n"
|
||||
PPC405_ERR77(0,%1)
|
||||
" stwcx. %0,0,%1\n"
|
||||
" bne- 1b\n"
|
||||
SMP_ISYNC
|
||||
: "=&r" (t)
|
||||
: "r" (&aint->counter)
|
||||
: "cc", "memory");
|
||||
__asm__ __volatile__ ("1: lwarx %0,0,%1\n"
|
||||
" addic %0,%0,-1\n" PPC405_ERR77 (0, %1)
|
||||
" stwcx. %0,0,%1\n" " bne- 1b\n" SMP_ISYNC:"=&r" (t)
|
||||
:"r" (&aint->counter)
|
||||
:"cc", "memory");
|
||||
|
||||
return t == 0;
|
||||
}
|
||||
|
||||
/***** DEC[/Compaq/HP?/Intel?] Alpha *****/
|
||||
#elif defined(HAVE_CPU_ALPHA) && defined(__GNUC__)
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_init (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
aint->counter = val;
|
||||
}
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_destroy (GstAtomicInt * aint)
|
||||
{
|
||||
}
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_set (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
aint->counter = val;
|
||||
}
|
||||
GST_INLINE_FUNC gint
|
||||
gst_atomic_int_read (GstAtomicInt * aint)
|
||||
{
|
||||
return aint->counter;
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = val; }
|
||||
GST_INLINE_FUNC void gst_atomic_int_destroy (GstAtomicInt *aint) { }
|
||||
GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = val; }
|
||||
GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { return aint->counter; }
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_add (GstAtomicInt *aint, gint val)
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_add (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
unsigned long temp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0,%1\n"
|
||||
" addl %0,%2,%0\n"
|
||||
" stl_c %0,%1\n"
|
||||
" beq %0,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
:"=&r" (temp), "=m" (aint->counter)
|
||||
__asm__ __volatile__ ("1: ldl_l %0,%1\n"
|
||||
" addl %0,%2,%0\n"
|
||||
" stl_c %0,%1\n"
|
||||
" beq %0,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n" ".previous":"=&r" (temp), "=m" (aint->counter)
|
||||
:"Ir" (val), "m" (aint->counter));
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_inc (GstAtomicInt *aint)
|
||||
gst_atomic_int_inc (GstAtomicInt * aint)
|
||||
{
|
||||
gst_atomic_int_add (aint, 1);
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC gboolean
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt *aint)
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt * aint)
|
||||
{
|
||||
long temp, result;
|
||||
int val = 1;
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0,%1\n"
|
||||
" subl %0,%3,%2\n"
|
||||
" subl %0,%3,%0\n"
|
||||
" stl_c %0,%1\n"
|
||||
" beq %0,2f\n"
|
||||
" mb\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
:"=&r" (temp), "=m" (aint->counter), "=&r" (result)
|
||||
:"Ir" (val), "m" (aint->counter) : "memory");
|
||||
__asm__ __volatile__ ("1: ldl_l %0,%1\n"
|
||||
" subl %0,%3,%2\n"
|
||||
" subl %0,%3,%0\n"
|
||||
" stl_c %0,%1\n"
|
||||
" beq %0,2f\n"
|
||||
" mb\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous":"=&r" (temp), "=m" (aint->counter), "=&r" (result)
|
||||
:"Ir" (val), "m" (aint->counter):"memory");
|
||||
|
||||
return result == 0;
|
||||
}
|
||||
|
@ -213,16 +229,38 @@ gst_atomic_int_dec_and_test (GstAtomicInt *aint)
|
|||
/***** Sun SPARC *****/
|
||||
#elif 0 && defined(HAVE_CPU_SPARC) && defined(__GNUC__)
|
||||
/* allegedly broken again */
|
||||
|
||||
GST_INLINE_FUNC void gst_atomic_int_destroy (GstAtomicInt *aint) { }
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_destroy (GstAtomicInt * aint)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef GST_CONFIG_NO_SMP
|
||||
GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = val; }
|
||||
GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = val; }
|
||||
GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { return aint->counter; }
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_init (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
aint->counter = val;
|
||||
}
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_set (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
aint->counter = val;
|
||||
}
|
||||
GST_INLINE_FUNC gint
|
||||
gst_atomic_int_read (GstAtomicInt * aint)
|
||||
{
|
||||
return aint->counter;
|
||||
}
|
||||
#else
|
||||
GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = (val<<8); }
|
||||
GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = (val<<8); }
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_init (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
aint->counter = (val << 8);
|
||||
}
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_set (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
aint->counter = (val << 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* For SMP the trick is you embed the spin lock byte within
|
||||
|
@ -235,8 +273,8 @@ GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint-
|
|||
* 31 8 7 0
|
||||
*/
|
||||
GST_INLINE_FUNC gint
|
||||
gst_atomic_int_read (GstAtomicInt *aint)
|
||||
{
|
||||
gst_atomic_int_read (GstAtomicInt * aint)
|
||||
{
|
||||
int ret = aint->counter;
|
||||
|
||||
while (ret & 0xff)
|
||||
|
@ -246,8 +284,8 @@ gst_atomic_int_read (GstAtomicInt *aint)
|
|||
}
|
||||
#endif /* GST_CONFIG_NO_SMP */
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_add (GstAtomicInt *aint, gint val)
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_add (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
volatile int increment, *ptr;
|
||||
int lock = 1;
|
||||
|
@ -256,41 +294,28 @@ gst_atomic_int_add (GstAtomicInt *aint, gint val)
|
|||
ptr = &(aint->counter);
|
||||
|
||||
#if __GNUC__ > 3 || (__GNUC__ >=3 && __GNUC_MINOR__ >= 2)
|
||||
__asm__ __volatile__("1: ldstub [%[ptr] + 3], %[lock]\n"
|
||||
"\torcc %[lock], 0, %[ignore]\n"
|
||||
"\tbne 1b\n" /* go back until we have the lock */
|
||||
"\tld [%[ptr]], %[inc]\n"
|
||||
"\tsra %[inc], 8, %[inc]\n"
|
||||
"\tadd %[inc], %[val], %[inc]\n"
|
||||
"\tsll %[inc], 8, %[lock]\n"
|
||||
"\tst %[lock],[%[ptr]]\n" /* Release the lock */
|
||||
: [inc] "=&r" (increment), [lock] "=r" (lock),
|
||||
[ignore] "=&r" (ignore)
|
||||
: "0" (increment), [ptr] "r" (ptr), [val] "r" (val)
|
||||
);
|
||||
__asm__ __volatile__ ("1: ldstub [%[ptr] + 3], %[lock]\n" "\torcc %[lock], 0, %[ignore]\n" "\tbne 1b\n" /* go back until we have the lock */
|
||||
"\tld [%[ptr]], %[inc]\n" "\tsra %[inc], 8, %[inc]\n" "\tadd %[inc], %[val], %[inc]\n" "\tsll %[inc], 8, %[lock]\n" "\tst %[lock],[%[ptr]]\n" /* Release the lock */
|
||||
:[inc] "=&r" (increment),[lock] "=r" (lock),[ignore] "=&r" (ignore)
|
||||
:"0" (increment),[ptr] "r" (ptr),[val] "r" (val)
|
||||
);
|
||||
#else
|
||||
__asm__ __volatile__("1: ldstub [%4 + 3], %1\n"
|
||||
"\torcc %1, 0, %2\n"
|
||||
"\tbne 1b\n" /* go back until we have the lock */
|
||||
"\tld [%4], %0\n"
|
||||
"\tsra %0, 8, %0\n"
|
||||
"\tadd %0, %5, %0\n"
|
||||
"\tsll %0, 8, %1\n"
|
||||
"\tst %1,[%4]\n" /* Release the lock */
|
||||
: "=&r" (increment), "=r" (lock), "=&r" (ignore)
|
||||
: "0" (increment), "r" (ptr), "r" (val)
|
||||
);
|
||||
__asm__ __volatile__ ("1: ldstub [%4 + 3], %1\n" "\torcc %1, 0, %2\n" "\tbne 1b\n" /* go back until we have the lock */
|
||||
"\tld [%4], %0\n" "\tsra %0, 8, %0\n" "\tadd %0, %5, %0\n" "\tsll %0, 8, %1\n" "\tst %1,[%4]\n" /* Release the lock */
|
||||
:"=&r" (increment), "=r" (lock), "=&r" (ignore)
|
||||
:"0" (increment), "r" (ptr), "r" (val)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_inc (GstAtomicInt *aint)
|
||||
gst_atomic_int_inc (GstAtomicInt * aint)
|
||||
{
|
||||
gst_atomic_int_add (aint, 1);
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC gboolean
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt *aint)
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt * aint)
|
||||
{
|
||||
volatile int increment, *ptr;
|
||||
int lock = 1;
|
||||
|
@ -299,30 +324,17 @@ gst_atomic_int_dec_and_test (GstAtomicInt *aint)
|
|||
ptr = &aint->counter;
|
||||
|
||||
#if __GNUC__ > 3 || (__GNUC__ >=3 && __GNUC_MINOR__ >= 2)
|
||||
__asm__ __volatile__("1: ldstub [%[ptr] + 3], %[lock]\n"
|
||||
"\torcc %[lock], 0, %[ignore]\n"
|
||||
"\tbne 1b\n" /* go back until we have the lock */
|
||||
"\tld [%[ptr]], %[inc]\n"
|
||||
"\tsra %[inc], 8, %[inc]\n"
|
||||
"\tsub %[inc], 1, %[inc]\n"
|
||||
"\tsll %[inc], 8, %[lock]\n"
|
||||
"\tst %[lock],[%[ptr]]\n" /* Release the lock */
|
||||
: [inc] "=&r" (increment), [lock] "=r" (lock),
|
||||
[ignore] "=&r" (ignore)
|
||||
: "0" (increment), [ptr] "r" (ptr)
|
||||
);
|
||||
__asm__ __volatile__ ("1: ldstub [%[ptr] + 3], %[lock]\n" "\torcc %[lock], 0, %[ignore]\n" "\tbne 1b\n" /* go back until we have the lock */
|
||||
"\tld [%[ptr]], %[inc]\n" "\tsra %[inc], 8, %[inc]\n" "\tsub %[inc], 1, %[inc]\n" "\tsll %[inc], 8, %[lock]\n" "\tst %[lock],[%[ptr]]\n" /* Release the lock */
|
||||
:[inc] "=&r" (increment),[lock] "=r" (lock),[ignore] "=&r" (ignore)
|
||||
:"0" (increment),[ptr] "r" (ptr)
|
||||
);
|
||||
#else
|
||||
__asm__ __volatile__("1: ldstub [%4 + 3], %1\n"
|
||||
"\torcc %1, 0, %2\n"
|
||||
"\tbne 1b\n" /* go back until we have the lock */
|
||||
"\tld [%4], %0\n"
|
||||
"\tsra %0, 8, %0\n"
|
||||
"\tsub %0, 1, %0\n"
|
||||
"\tsll %0, 8, %1\n"
|
||||
"\tst %1,[%4]\n" /* Release the lock */
|
||||
: "=&r" (increment), "=r" (lock), "=&r" (ignore)
|
||||
: "0" (increment), "r" (ptr)
|
||||
);
|
||||
__asm__ __volatile__ ("1: ldstub [%4 + 3], %1\n" "\torcc %1, 0, %2\n" "\tbne 1b\n" /* go back until we have the lock */
|
||||
"\tld [%4], %0\n" "\tsra %0, 8, %0\n" "\tsub %0, 1, %0\n" "\tsll %0, 8, %1\n" "\tst %1,[%4]\n" /* Release the lock */
|
||||
:"=&r" (increment), "=r" (lock), "=&r" (ignore)
|
||||
:"0" (increment), "r" (ptr)
|
||||
);
|
||||
#endif
|
||||
|
||||
return increment == 0;
|
||||
|
@ -332,63 +344,93 @@ gst_atomic_int_dec_and_test (GstAtomicInt *aint)
|
|||
/* This is disabled because the asm code is broken on most MIPS
|
||||
* processors and doesn't generally compile. */
|
||||
#elif defined(HAVE_CPU_MIPS) && defined(__GNUC__) && 0
|
||||
|
||||
GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = val; }
|
||||
GST_INLINE_FUNC void gst_atomic_int_destroy (GstAtomicInt *aint) { }
|
||||
GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = val; }
|
||||
GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { return aint->counter; }
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_init (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
aint->counter = val;
|
||||
}
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_destroy (GstAtomicInt * aint)
|
||||
{
|
||||
}
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_set (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
aint->counter = val;
|
||||
}
|
||||
GST_INLINE_FUNC gint
|
||||
gst_atomic_int_read (GstAtomicInt * aint)
|
||||
{
|
||||
return aint->counter;
|
||||
}
|
||||
|
||||
/* this only works on MIPS II and better */
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_add (GstAtomicInt *aint, gint val)
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_add (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
unsigned long temp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ll %0, %1 # atomic_add\n"
|
||||
" addu %0, %2 \n"
|
||||
" sc %0, %1 \n"
|
||||
" beqz %0, 1b \n"
|
||||
: "=&r" (temp), "=m" (aint->counter)
|
||||
: "Ir" (val), "m" (aint->counter));
|
||||
__asm__ __volatile__ ("1: ll %0, %1 # atomic_add\n"
|
||||
" addu %0, %2 \n"
|
||||
" sc %0, %1 \n"
|
||||
" beqz %0, 1b \n":"=&r" (temp),
|
||||
"=m" (aint->counter)
|
||||
:"Ir" (val), "m" (aint->counter));
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_inc (GstAtomicInt *aint)
|
||||
gst_atomic_int_inc (GstAtomicInt * aint)
|
||||
{
|
||||
gst_atomic_int_add (aint, 1);
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC gboolean
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt *aint)
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt * aint)
|
||||
{
|
||||
unsigned long temp, result;
|
||||
int val = 1;
|
||||
|
||||
__asm__ __volatile__(
|
||||
".set push \n"
|
||||
".set noreorder # atomic_sub_return\n"
|
||||
"1: ll %1, %2 \n"
|
||||
" subu %0, %1, %3 \n"
|
||||
" sc %0, %2 \n"
|
||||
" beqz %0, 1b \n"
|
||||
" subu %0, %1, %3 \n"
|
||||
".set pop \n"
|
||||
: "=&r" (result), "=&r" (temp), "=m" (aint->counter)
|
||||
: "Ir" (val), "m" (aint->counter)
|
||||
: "memory");
|
||||
__asm__ __volatile__ (".set push \n"
|
||||
".set noreorder # atomic_sub_return\n"
|
||||
"1: ll %1, %2 \n"
|
||||
" subu %0, %1, %3 \n"
|
||||
" sc %0, %2 \n"
|
||||
" beqz %0, 1b \n"
|
||||
" subu %0, %1, %3 \n"
|
||||
".set pop \n":"=&r" (result),
|
||||
"=&r" (temp), "=m" (aint->counter)
|
||||
:"Ir" (val), "m" (aint->counter)
|
||||
:"memory");
|
||||
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
/***** S/390 *****/
|
||||
#elif defined(HAVE_CPU_S390) && defined(__GNUC__)
|
||||
typedef struct { volatile int counter; } atomic_t __attribute__ ((aligned (4)));
|
||||
typedef struct
|
||||
{
|
||||
volatile int counter;
|
||||
} atomic_t __attribute__ ((aligned (4)));
|
||||
|
||||
GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = val; }
|
||||
GST_INLINE_FUNC void gst_atomic_int_destroy (GstAtomicInt *aint) { }
|
||||
GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = val; }
|
||||
GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { return aint->counter; }
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_init (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
aint->counter = val;
|
||||
}
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_destroy (GstAtomicInt * aint)
|
||||
{
|
||||
}
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_set (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
aint->counter = val;
|
||||
}
|
||||
GST_INLINE_FUNC gint
|
||||
gst_atomic_int_read (GstAtomicInt * aint)
|
||||
{
|
||||
return aint->counter;
|
||||
}
|
||||
|
||||
#define __CS_LOOP(old_val, new_val, ptr, op_val, op_string) \
|
||||
__asm__ __volatile__(" l %0,0(%3)\n" \
|
||||
|
@ -400,49 +442,51 @@ GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { return aint->c
|
|||
"+m" (((atomic_t *)(ptr))->counter) \
|
||||
: "a" (ptr), "d" (op_val) : "cc" );
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_add (GstAtomicInt *aint, gint val)
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_add (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
int old_val, new_val;
|
||||
__CS_LOOP(old_val, new_val, aint, val, "ar");
|
||||
|
||||
__CS_LOOP (old_val, new_val, aint, val, "ar");
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_inc (GstAtomicInt *aint)
|
||||
gst_atomic_int_inc (GstAtomicInt * aint)
|
||||
{
|
||||
int old_val, new_val;
|
||||
__CS_LOOP(old_val, new_val, aint, 1, "ar");
|
||||
|
||||
__CS_LOOP (old_val, new_val, aint, 1, "ar");
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC gboolean
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt *aint)
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt * aint)
|
||||
{
|
||||
int old_val, new_val;
|
||||
__CS_LOOP(old_val, new_val, aint, 1, "sr");
|
||||
|
||||
__CS_LOOP (old_val, new_val, aint, 1, "sr");
|
||||
return new_val == 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#else
|
||||
#warning consider putting your architecture specific atomic implementations here
|
||||
|
||||
/*
|
||||
* generic implementation
|
||||
*/
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_init (GstAtomicInt *aint, gint val)
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_init (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
aint->counter = val;
|
||||
aint->lock = g_mutex_new ();
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_destroy (GstAtomicInt *aint)
|
||||
gst_atomic_int_destroy (GstAtomicInt * aint)
|
||||
{
|
||||
g_mutex_free (aint->lock);
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_set (GstAtomicInt *aint, gint val)
|
||||
gst_atomic_int_set (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
g_mutex_lock (aint->lock);
|
||||
aint->counter = val;
|
||||
|
@ -450,7 +494,7 @@ gst_atomic_int_set (GstAtomicInt *aint, gint val)
|
|||
}
|
||||
|
||||
GST_INLINE_FUNC gint
|
||||
gst_atomic_int_read (GstAtomicInt *aint)
|
||||
gst_atomic_int_read (GstAtomicInt * aint)
|
||||
{
|
||||
gint res;
|
||||
|
||||
|
@ -461,8 +505,8 @@ gst_atomic_int_read (GstAtomicInt *aint)
|
|||
return res;
|
||||
}
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_add (GstAtomicInt *aint, gint val)
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_add (GstAtomicInt * aint, gint val)
|
||||
{
|
||||
g_mutex_lock (aint->lock);
|
||||
aint->counter += val;
|
||||
|
@ -470,7 +514,7 @@ gst_atomic_int_add (GstAtomicInt *aint, gint val)
|
|||
}
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_inc (GstAtomicInt *aint)
|
||||
gst_atomic_int_inc (GstAtomicInt * aint)
|
||||
{
|
||||
g_mutex_lock (aint->lock);
|
||||
aint->counter++;
|
||||
|
@ -478,10 +522,10 @@ gst_atomic_int_inc (GstAtomicInt *aint)
|
|||
}
|
||||
|
||||
GST_INLINE_FUNC gboolean
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt *aint)
|
||||
gst_atomic_int_dec_and_test (GstAtomicInt * aint)
|
||||
{
|
||||
gboolean res;
|
||||
|
||||
|
||||
g_mutex_lock (aint->lock);
|
||||
aint->counter--;
|
||||
res = (aint->counter == 0);
|
||||
|
@ -490,11 +534,11 @@ gst_atomic_int_dec_and_test (GstAtomicInt *aint)
|
|||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
* common functions
|
||||
*/
|
||||
GST_INLINE_FUNC GstAtomicInt*
|
||||
*/
|
||||
GST_INLINE_FUNC GstAtomicInt *
|
||||
gst_atomic_int_new (gint val)
|
||||
{
|
||||
GstAtomicInt *aint;
|
||||
|
@ -506,14 +550,13 @@ gst_atomic_int_new (gint val)
|
|||
}
|
||||
|
||||
GST_INLINE_FUNC void
|
||||
gst_atomic_int_free (GstAtomicInt *aint)
|
||||
gst_atomic_int_free (GstAtomicInt * aint)
|
||||
{
|
||||
gst_atomic_int_destroy (aint);
|
||||
g_free (aint);
|
||||
}
|
||||
|
||||
#endif /* defined (GST_CAN_INLINE) || defined (__GST_TRASH_STACK_C__)*/
|
||||
#endif /* defined (GST_CAN_INLINE) || defined (__GST_TRASH_STACK_C__) */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_ATOMIC_IMPL_H__ */
|
||||
|
|
432
gst/gstbin.c
432
gst/gstbin.c
|
@ -33,40 +33,38 @@
|
|||
#include "gstscheduler.h"
|
||||
#include "gstindex.h"
|
||||
|
||||
static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS (
|
||||
"Generic bin",
|
||||
"Generic/Bin",
|
||||
"Simple container object",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>"
|
||||
);
|
||||
static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS ("Generic bin",
|
||||
"Generic/Bin",
|
||||
"Simple container object",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>");
|
||||
|
||||
GType _gst_bin_type = 0;
|
||||
|
||||
static gboolean _gst_boolean_did_something_accumulator (GSignalInvocationHint *ihint,
|
||||
GValue *return_accu, const GValue *handler_return, gpointer dummy);
|
||||
static gboolean _gst_boolean_did_something_accumulator (GSignalInvocationHint *
|
||||
ihint, GValue * return_accu, const GValue * handler_return, gpointer dummy);
|
||||
|
||||
static void gst_bin_dispose (GObject * object);
|
||||
static void gst_bin_dispose (GObject * object);
|
||||
|
||||
static GstElementStateReturn gst_bin_change_state (GstElement *element);
|
||||
static GstElementStateReturn gst_bin_change_state_norecurse (GstBin *bin);
|
||||
static GstElementStateReturn gst_bin_change_state (GstElement * element);
|
||||
static GstElementStateReturn gst_bin_change_state_norecurse (GstBin * bin);
|
||||
|
||||
#ifndef GST_DISABLE_INDEX
|
||||
static void gst_bin_set_index (GstElement *element, GstIndex *index);
|
||||
static void gst_bin_set_index (GstElement * element, GstIndex * index);
|
||||
#endif
|
||||
|
||||
static void gst_bin_add_func (GstBin *bin, GstElement *element);
|
||||
static void gst_bin_remove_func (GstBin *bin, GstElement *element);
|
||||
static void gst_bin_child_state_change_func (GstBin *bin, GstElementState oldstate,
|
||||
GstElementState newstate, GstElement *child);
|
||||
static void gst_bin_add_func (GstBin * bin, GstElement * element);
|
||||
static void gst_bin_remove_func (GstBin * bin, GstElement * element);
|
||||
static void gst_bin_child_state_change_func (GstBin * bin,
|
||||
GstElementState oldstate, GstElementState newstate, GstElement * child);
|
||||
|
||||
static GstClock* gst_bin_get_clock_func (GstElement *element);
|
||||
static void gst_bin_set_clock_func (GstElement *element, GstClock *clock);
|
||||
static GstClock *gst_bin_get_clock_func (GstElement * element);
|
||||
static void gst_bin_set_clock_func (GstElement * element, GstClock * clock);
|
||||
|
||||
static gboolean gst_bin_iterate_func (GstBin *bin);
|
||||
static gboolean gst_bin_iterate_func (GstBin * bin);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
|
||||
static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
|
||||
static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
|
||||
static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
|
||||
#endif
|
||||
|
||||
/* Bin signals and args */
|
||||
|
@ -81,12 +79,12 @@ enum
|
|||
enum
|
||||
{
|
||||
ARG_0
|
||||
/* FILL ME */
|
||||
/* FILL ME */
|
||||
};
|
||||
|
||||
static void gst_bin_base_init (gpointer g_class);
|
||||
static void gst_bin_class_init (GstBinClass * klass);
|
||||
static void gst_bin_init (GstBin * bin);
|
||||
static void gst_bin_base_init (gpointer g_class);
|
||||
static void gst_bin_class_init (GstBinClass * klass);
|
||||
static void gst_bin_init (GstBin * bin);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
|
||||
|
@ -108,7 +106,8 @@ gst_bin_get_type (void)
|
|||
NULL
|
||||
};
|
||||
|
||||
_gst_bin_type = g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
|
||||
_gst_bin_type =
|
||||
g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
|
||||
}
|
||||
return _gst_bin_type;
|
||||
}
|
||||
|
@ -117,7 +116,7 @@ static void
|
|||
gst_bin_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &gst_bin_details);
|
||||
}
|
||||
|
||||
|
@ -135,40 +134,42 @@ gst_bin_class_init (GstBinClass * klass)
|
|||
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
|
||||
|
||||
gst_bin_signals[ELEMENT_ADDED] =
|
||||
g_signal_new ("element-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (GstBinClass, element_added), NULL, NULL,
|
||||
gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
|
||||
g_signal_new ("element-added", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_added), NULL,
|
||||
NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
|
||||
gst_bin_signals[ELEMENT_REMOVED] =
|
||||
g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (GstBinClass, element_removed), NULL, NULL,
|
||||
gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
|
||||
g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL,
|
||||
NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
|
||||
gst_bin_signals[ITERATE] =
|
||||
g_signal_new ("iterate", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstBinClass, iterate),
|
||||
_gst_boolean_did_something_accumulator, NULL,
|
||||
gst_marshal_BOOLEAN__VOID, G_TYPE_BOOLEAN, 0);
|
||||
g_signal_new ("iterate", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstBinClass, iterate),
|
||||
_gst_boolean_did_something_accumulator, NULL, gst_marshal_BOOLEAN__VOID,
|
||||
G_TYPE_BOOLEAN, 0);
|
||||
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
|
||||
gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
|
||||
gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
|
||||
gstobject_class->restore_thyself =
|
||||
GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
|
||||
#endif
|
||||
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
|
||||
#ifndef GST_DISABLE_INDEX
|
||||
gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index);
|
||||
gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index);
|
||||
#endif
|
||||
|
||||
klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
|
||||
klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
|
||||
klass->child_state_change = GST_DEBUG_FUNCPTR (gst_bin_child_state_change_func);
|
||||
klass->iterate = GST_DEBUG_FUNCPTR (gst_bin_iterate_func);
|
||||
klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
|
||||
klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
|
||||
klass->child_state_change =
|
||||
GST_DEBUG_FUNCPTR (gst_bin_child_state_change_func);
|
||||
klass->iterate = GST_DEBUG_FUNCPTR (gst_bin_iterate_func);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_gst_boolean_did_something_accumulator (GSignalInvocationHint *ihint,
|
||||
GValue *return_accu, const GValue *handler_return, gpointer dummy)
|
||||
_gst_boolean_did_something_accumulator (GSignalInvocationHint * ihint,
|
||||
GValue * return_accu, const GValue * handler_return, gpointer dummy)
|
||||
{
|
||||
gboolean did_something;
|
||||
|
||||
|
@ -205,19 +206,19 @@ gst_bin_new (const gchar * name)
|
|||
return gst_element_factory_make ("bin", name);
|
||||
}
|
||||
|
||||
static GstClock*
|
||||
gst_bin_get_clock_func (GstElement *element)
|
||||
static GstClock *
|
||||
gst_bin_get_clock_func (GstElement * element)
|
||||
{
|
||||
if (GST_ELEMENT_SCHED (element))
|
||||
if (GST_ELEMENT_SCHED (element))
|
||||
return gst_scheduler_get_clock (GST_ELEMENT_SCHED (element));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_bin_set_clock_func (GstElement *element, GstClock *clock)
|
||||
gst_bin_set_clock_func (GstElement * element, GstClock * clock)
|
||||
{
|
||||
if (GST_ELEMENT_SCHED (element))
|
||||
if (GST_ELEMENT_SCHED (element))
|
||||
gst_scheduler_use_clock (GST_ELEMENT_SCHED (element), clock);
|
||||
}
|
||||
|
||||
|
@ -229,8 +230,8 @@ gst_bin_set_clock_func (GstElement *element, GstClock *clock)
|
|||
*
|
||||
* Returns: the #GstClock of the bin
|
||||
*/
|
||||
GstClock*
|
||||
gst_bin_get_clock (GstBin *bin)
|
||||
GstClock *
|
||||
gst_bin_get_clock (GstBin * bin)
|
||||
{
|
||||
g_return_val_if_fail (bin != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
||||
|
@ -247,7 +248,7 @@ gst_bin_get_clock (GstBin *bin)
|
|||
* force it to use no clock at all.
|
||||
*/
|
||||
void
|
||||
gst_bin_use_clock (GstBin *bin, GstClock *clock)
|
||||
gst_bin_use_clock (GstBin * bin, GstClock * clock)
|
||||
{
|
||||
g_return_if_fail (GST_IS_BIN (bin));
|
||||
|
||||
|
@ -261,20 +262,20 @@ gst_bin_use_clock (GstBin *bin, GstClock *clock)
|
|||
* Let the bin select a clock automatically.
|
||||
*/
|
||||
void
|
||||
gst_bin_auto_clock (GstBin *bin)
|
||||
gst_bin_auto_clock (GstBin * bin)
|
||||
{
|
||||
g_return_if_fail (GST_IS_BIN (bin));
|
||||
|
||||
if (GST_ELEMENT_SCHED (bin))
|
||||
if (GST_ELEMENT_SCHED (bin))
|
||||
gst_scheduler_auto_clock (GST_ELEMENT_SCHED (bin));
|
||||
}
|
||||
|
||||
#ifndef GST_DISABLE_INDEX
|
||||
static void
|
||||
gst_bin_set_index (GstElement *element, GstIndex *index)
|
||||
gst_bin_set_index (GstElement * element, GstIndex * index)
|
||||
{
|
||||
GstBin *bin = GST_BIN (element);
|
||||
|
||||
|
||||
g_return_if_fail (GST_IS_BIN (bin));
|
||||
|
||||
g_list_foreach (bin->children, (GFunc) gst_element_set_index, index);
|
||||
|
@ -282,27 +283,28 @@ gst_bin_set_index (GstElement *element, GstIndex *index)
|
|||
#endif
|
||||
|
||||
static void
|
||||
gst_bin_set_element_sched (GstElement *element, GstScheduler *sched)
|
||||
gst_bin_set_element_sched (GstElement * element, GstScheduler * sched)
|
||||
{
|
||||
GST_CAT_LOG (GST_CAT_SCHEDULING, "setting element \"%s\" sched to %p",
|
||||
GST_ELEMENT_NAME (element), sched);
|
||||
GST_ELEMENT_NAME (element), sched);
|
||||
|
||||
/* if it's actually a Bin */
|
||||
if (GST_IS_BIN (element)) {
|
||||
if (GST_FLAG_IS_SET (element, GST_BIN_FLAG_MANAGER)) {
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element,
|
||||
"child is already a manager, not resetting sched");
|
||||
"child is already a manager, not resetting sched");
|
||||
if (GST_ELEMENT_SCHED (element))
|
||||
gst_scheduler_add_scheduler (sched, GST_ELEMENT_SCHED (element));
|
||||
gst_scheduler_add_scheduler (sched, GST_ELEMENT_SCHED (element));
|
||||
return;
|
||||
}
|
||||
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element,
|
||||
"setting child bin's scheduler to be the same as the parent's");
|
||||
"setting child bin's scheduler to be the same as the parent's");
|
||||
gst_scheduler_add_element (sched, element);
|
||||
|
||||
/* set the children's schedule */
|
||||
g_list_foreach (GST_BIN (element)->children, (GFunc) gst_bin_set_element_sched, sched);
|
||||
g_list_foreach (GST_BIN (element)->children,
|
||||
(GFunc) gst_bin_set_element_sched, sched);
|
||||
}
|
||||
/* otherwise, if it's just a regular old element */
|
||||
else {
|
||||
|
@ -320,19 +322,19 @@ gst_bin_set_element_sched (GstElement *element, GstScheduler *sched)
|
|||
|
||||
/* we only operate on real pads */
|
||||
if (!GST_IS_REAL_PAD (pad))
|
||||
continue;
|
||||
continue;
|
||||
|
||||
/* if the peer element exists and is a candidate */
|
||||
if (GST_PAD_PEER (pad)) {
|
||||
if (gst_pad_get_scheduler (GST_PAD_PEER (pad)) == sched) {
|
||||
GST_CAT_LOG (GST_CAT_SCHEDULING,
|
||||
"peer is in same scheduler, telling scheduler");
|
||||
if (gst_pad_get_scheduler (GST_PAD_PEER (pad)) == sched) {
|
||||
GST_CAT_LOG (GST_CAT_SCHEDULING,
|
||||
"peer is in same scheduler, telling scheduler");
|
||||
|
||||
if (GST_PAD_IS_SRC (pad))
|
||||
gst_scheduler_pad_link (sched, pad, GST_PAD_PEER (pad));
|
||||
else
|
||||
gst_scheduler_pad_link (sched, GST_PAD_PEER (pad), pad);
|
||||
}
|
||||
if (GST_PAD_IS_SRC (pad))
|
||||
gst_scheduler_pad_link (sched, pad, GST_PAD_PEER (pad));
|
||||
else
|
||||
gst_scheduler_pad_link (sched, GST_PAD_PEER (pad), pad);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -340,30 +342,32 @@ gst_bin_set_element_sched (GstElement *element, GstScheduler *sched)
|
|||
|
||||
|
||||
static void
|
||||
gst_bin_unset_element_sched (GstElement *element, GstScheduler *sched)
|
||||
gst_bin_unset_element_sched (GstElement * element, GstScheduler * sched)
|
||||
{
|
||||
if (GST_ELEMENT_SCHED (element) == NULL) {
|
||||
GST_CAT_DEBUG (GST_CAT_SCHEDULING, "element \"%s\" has no scheduler",
|
||||
GST_ELEMENT_NAME (element));
|
||||
GST_ELEMENT_NAME (element));
|
||||
return;
|
||||
}
|
||||
|
||||
GST_CAT_DEBUG (GST_CAT_SCHEDULING, "removing element \"%s\" from its sched %p",
|
||||
GST_ELEMENT_NAME (element), GST_ELEMENT_SCHED (element));
|
||||
GST_CAT_DEBUG (GST_CAT_SCHEDULING,
|
||||
"removing element \"%s\" from its sched %p", GST_ELEMENT_NAME (element),
|
||||
GST_ELEMENT_SCHED (element));
|
||||
|
||||
/* if it's actually a Bin */
|
||||
if (GST_IS_BIN (element)) {
|
||||
|
||||
if (GST_FLAG_IS_SET (element, GST_BIN_FLAG_MANAGER)) {
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element,
|
||||
"child is already a manager, not unsetting sched");
|
||||
"child is already a manager, not unsetting sched");
|
||||
if (sched) {
|
||||
gst_scheduler_remove_scheduler (sched, GST_ELEMENT_SCHED (element));
|
||||
gst_scheduler_remove_scheduler (sched, GST_ELEMENT_SCHED (element));
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* for each child, remove them from their schedule */
|
||||
g_list_foreach (GST_BIN (element)->children, (GFunc) gst_bin_unset_element_sched, sched);
|
||||
g_list_foreach (GST_BIN (element)->children,
|
||||
(GFunc) gst_bin_unset_element_sched, sched);
|
||||
|
||||
gst_scheduler_remove_element (GST_ELEMENT_SCHED (element), element);
|
||||
}
|
||||
|
@ -381,18 +385,19 @@ gst_bin_unset_element_sched (GstElement *element, GstScheduler *sched)
|
|||
|
||||
/* we only operate on real pads */
|
||||
if (!GST_IS_REAL_PAD (pad))
|
||||
continue;
|
||||
continue;
|
||||
|
||||
/* if the peer element exists and is a candidate */
|
||||
if (GST_PAD_PEER (pad)) {
|
||||
if (gst_pad_get_scheduler (GST_PAD_PEER (pad)) == sched) {
|
||||
GST_CAT_LOG (GST_CAT_SCHEDULING, "peer is in same scheduler, telling scheduler");
|
||||
if (gst_pad_get_scheduler (GST_PAD_PEER (pad)) == sched) {
|
||||
GST_CAT_LOG (GST_CAT_SCHEDULING,
|
||||
"peer is in same scheduler, telling scheduler");
|
||||
|
||||
if (GST_PAD_IS_SRC (pad))
|
||||
gst_scheduler_pad_unlink (sched, pad, GST_PAD_PEER (pad));
|
||||
else
|
||||
gst_scheduler_pad_unlink (sched, GST_PAD_PEER (pad), pad);
|
||||
}
|
||||
if (GST_PAD_IS_SRC (pad))
|
||||
gst_scheduler_pad_unlink (sched, pad, GST_PAD_PEER (pad));
|
||||
else
|
||||
gst_scheduler_pad_unlink (sched, GST_PAD_PEER (pad), pad);
|
||||
}
|
||||
}
|
||||
}
|
||||
gst_scheduler_remove_element (GST_ELEMENT_SCHED (element), element);
|
||||
|
@ -409,7 +414,7 @@ gst_bin_unset_element_sched (GstElement *element, GstScheduler *sched)
|
|||
* Add a list of elements to a bin. Uses #gst_bin_add.
|
||||
*/
|
||||
void
|
||||
gst_bin_add_many (GstBin *bin, GstElement *element_1, ...)
|
||||
gst_bin_add_many (GstBin * bin, GstElement * element_1, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
|
@ -420,15 +425,15 @@ gst_bin_add_many (GstBin *bin, GstElement *element_1, ...)
|
|||
|
||||
while (element_1) {
|
||||
gst_bin_add (bin, element_1);
|
||||
|
||||
element_1 = va_arg (args, GstElement*);
|
||||
|
||||
element_1 = va_arg (args, GstElement *);
|
||||
}
|
||||
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_bin_add_func (GstBin *bin, GstElement *element)
|
||||
gst_bin_add_func (GstBin * bin, GstElement * element)
|
||||
{
|
||||
gint state_idx = 0;
|
||||
GstElementState state;
|
||||
|
@ -438,11 +443,10 @@ gst_bin_add_func (GstBin *bin, GstElement *element)
|
|||
g_return_if_fail (GST_ELEMENT_PARENT (element) == NULL);
|
||||
|
||||
/* then check to see if the element's name is already taken in the bin */
|
||||
if (gst_object_check_uniqueness (bin->children,
|
||||
GST_ELEMENT_NAME (element)) == FALSE)
|
||||
{
|
||||
if (gst_object_check_uniqueness (bin->children,
|
||||
GST_ELEMENT_NAME (element)) == FALSE) {
|
||||
g_warning ("Name %s is not unique in bin %s, not adding\n",
|
||||
GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
|
||||
GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -454,7 +458,8 @@ gst_bin_add_func (GstBin *bin, GstElement *element)
|
|||
|
||||
/* bump our internal state counter */
|
||||
state = GST_STATE (element);
|
||||
while (state >>= 1) state_idx++;
|
||||
while (state >>= 1)
|
||||
state_idx++;
|
||||
bin->child_states[state_idx]++;
|
||||
|
||||
/* now we have to deal with manager stuff
|
||||
|
@ -465,8 +470,8 @@ gst_bin_add_func (GstBin *bin, GstElement *element)
|
|||
gst_bin_set_element_sched (element, sched);
|
||||
}
|
||||
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
|
||||
GST_OBJECT_NAME (element));
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
|
||||
GST_OBJECT_NAME (element));
|
||||
|
||||
g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element);
|
||||
}
|
||||
|
@ -480,30 +485,29 @@ gst_bin_add_func (GstBin *bin, GstElement *element)
|
|||
* add a reference.
|
||||
*/
|
||||
void
|
||||
gst_bin_add (GstBin *bin, GstElement *element)
|
||||
gst_bin_add (GstBin * bin, GstElement * element)
|
||||
{
|
||||
GstBinClass *bclass;
|
||||
|
||||
|
||||
g_return_if_fail (GST_IS_BIN (bin));
|
||||
g_return_if_fail (GST_IS_ELEMENT (element));
|
||||
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "adding element \"%s\"",
|
||||
GST_OBJECT_NAME (element));
|
||||
GST_OBJECT_NAME (element));
|
||||
|
||||
bclass = GST_BIN_GET_CLASS (bin);
|
||||
|
||||
if (bclass->add_element) {
|
||||
bclass->add_element (bin, element);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
GST_ELEMENT_ERROR (bin, CORE, FAILED, (NULL),
|
||||
("cannot add element %s to bin %s",
|
||||
GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin)));
|
||||
("cannot add element %s to bin %s",
|
||||
GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin)));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_bin_remove_func (GstBin *bin, GstElement *element)
|
||||
gst_bin_remove_func (GstBin * bin, GstElement * element)
|
||||
{
|
||||
gint state_idx = 0;
|
||||
GstElementState state;
|
||||
|
@ -514,7 +518,7 @@ gst_bin_remove_func (GstBin *bin, GstElement *element)
|
|||
/* the element must be in the bin's list of children */
|
||||
if (g_list_find (bin->children, element) == NULL) {
|
||||
g_warning ("no element \"%s\" in bin \"%s\"\n", GST_ELEMENT_NAME (element),
|
||||
GST_ELEMENT_NAME (bin));
|
||||
GST_ELEMENT_NAME (bin));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -527,11 +531,12 @@ gst_bin_remove_func (GstBin *bin, GstElement *element)
|
|||
|
||||
/* bump our internal state counter */
|
||||
state = GST_STATE (element);
|
||||
while (state >>= 1) state_idx++;
|
||||
while (state >>= 1)
|
||||
state_idx++;
|
||||
bin->child_states[state_idx]--;
|
||||
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
|
||||
GST_OBJECT_NAME (element));
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
|
||||
GST_OBJECT_NAME (element));
|
||||
|
||||
/* ref as we're going to emit a signal */
|
||||
gst_object_ref (GST_OBJECT (element));
|
||||
|
@ -560,12 +565,12 @@ gst_bin_remove_func (GstBin *bin, GstElement *element)
|
|||
* #gst_object_ref before removing it from the bin.
|
||||
*/
|
||||
void
|
||||
gst_bin_remove (GstBin *bin, GstElement *element)
|
||||
gst_bin_remove (GstBin * bin, GstElement * element)
|
||||
{
|
||||
GstBinClass *bclass;
|
||||
|
||||
GST_CAT_DEBUG (GST_CAT_PARENTAGE, "[%s]: trying to remove child %s",
|
||||
GST_ELEMENT_NAME (bin), GST_ELEMENT_NAME (element));
|
||||
GST_ELEMENT_NAME (bin), GST_ELEMENT_NAME (element));
|
||||
|
||||
g_return_if_fail (GST_IS_BIN (bin));
|
||||
g_return_if_fail (GST_IS_ELEMENT (element));
|
||||
|
@ -575,8 +580,7 @@ gst_bin_remove (GstBin *bin, GstElement *element)
|
|||
|
||||
if (bclass->remove_element) {
|
||||
bclass->remove_element (bin, element);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
g_warning ("cannot remove elements from bin %s\n", GST_ELEMENT_NAME (bin));
|
||||
}
|
||||
}
|
||||
|
@ -590,7 +594,7 @@ gst_bin_remove (GstBin *bin, GstElement *element)
|
|||
* Remove a list of elements from a bin. Uses #gst_bin_remove.
|
||||
*/
|
||||
void
|
||||
gst_bin_remove_many (GstBin *bin, GstElement *element_1, ...)
|
||||
gst_bin_remove_many (GstBin * bin, GstElement * element_1, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
|
@ -601,8 +605,8 @@ gst_bin_remove_many (GstBin *bin, GstElement *element_1, ...)
|
|||
|
||||
while (element_1) {
|
||||
gst_bin_remove (bin, element_1);
|
||||
|
||||
element_1 = va_arg (args, GstElement*);
|
||||
|
||||
element_1 = va_arg (args, GstElement *);
|
||||
}
|
||||
|
||||
va_end (args);
|
||||
|
@ -619,57 +623,58 @@ gst_bin_remove_many (GstBin *bin, GstElement *element_1, ...)
|
|||
* of a child.
|
||||
*/
|
||||
void
|
||||
gst_bin_child_state_change (GstBin *bin, GstElementState oldstate,
|
||||
GstElementState newstate, GstElement *child)
|
||||
gst_bin_child_state_change (GstBin * bin, GstElementState oldstate,
|
||||
GstElementState newstate, GstElement * child)
|
||||
{
|
||||
GstBinClass *bclass;
|
||||
|
||||
|
||||
g_return_if_fail (GST_IS_BIN (bin));
|
||||
g_return_if_fail (GST_IS_ELEMENT (child));
|
||||
|
||||
GST_CAT_LOG (GST_CAT_STATES, "child %s changed state in bin %s from %s to %s",
|
||||
GST_ELEMENT_NAME (child), GST_ELEMENT_NAME (bin),
|
||||
gst_element_state_get_name (oldstate),
|
||||
gst_element_state_get_name (newstate));
|
||||
GST_ELEMENT_NAME (child), GST_ELEMENT_NAME (bin),
|
||||
gst_element_state_get_name (oldstate),
|
||||
gst_element_state_get_name (newstate));
|
||||
|
||||
bclass = GST_BIN_GET_CLASS (bin);
|
||||
|
||||
if (bclass->child_state_change) {
|
||||
bclass->child_state_change (bin, oldstate, newstate, child);
|
||||
}
|
||||
else {
|
||||
g_warning ("cannot signal state change of child %s to bin %s\n",
|
||||
GST_ELEMENT_NAME (child), GST_ELEMENT_NAME (bin));
|
||||
} else {
|
||||
g_warning ("cannot signal state change of child %s to bin %s\n",
|
||||
GST_ELEMENT_NAME (child), GST_ELEMENT_NAME (bin));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_bin_child_state_change_func (GstBin *bin, GstElementState oldstate,
|
||||
GstElementState newstate, GstElement *child)
|
||||
gst_bin_child_state_change_func (GstBin * bin, GstElementState oldstate,
|
||||
GstElementState newstate, GstElement * child)
|
||||
{
|
||||
gint old_idx = 0, new_idx = 0, i;
|
||||
|
||||
while (oldstate >>= 1) old_idx++;
|
||||
while (newstate >>= 1) new_idx++;
|
||||
while (oldstate >>= 1)
|
||||
old_idx++;
|
||||
while (newstate >>= 1)
|
||||
new_idx++;
|
||||
|
||||
GST_LOCK (bin);
|
||||
bin->child_states[old_idx]--;
|
||||
bin->child_states[new_idx]++;
|
||||
|
||||
|
||||
for (i = GST_NUM_STATES - 1; i >= 0; i--) {
|
||||
if (bin->child_states[i] != 0) {
|
||||
gint state = (1 << i);
|
||||
|
||||
if (GST_STATE (bin) != state) {
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
||||
"highest child state is %s, changing bin state accordingly",
|
||||
gst_element_state_get_name (state));
|
||||
"highest child state is %s, changing bin state accordingly",
|
||||
gst_element_state_get_name (state));
|
||||
GST_STATE_PENDING (bin) = state;
|
||||
GST_UNLOCK (bin);
|
||||
GST_UNLOCK (bin);
|
||||
gst_bin_change_state_norecurse (bin);
|
||||
if (state != GST_STATE (bin)) {
|
||||
g_warning ("%s: state change in callback %d %d",
|
||||
GST_ELEMENT_NAME (bin),
|
||||
state, GST_STATE (bin));
|
||||
g_warning ("%s: state change in callback %d %d",
|
||||
GST_ELEMENT_NAME (bin), state, GST_STATE (bin));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -699,18 +704,17 @@ gst_bin_change_state (GstElement * element)
|
|||
transition = GST_STATE_TRANSITION (element);
|
||||
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||
"changing state of children from %s to %s",
|
||||
gst_element_state_get_name (old_state),
|
||||
gst_element_state_get_name (pending));
|
||||
"changing state of children from %s to %s",
|
||||
gst_element_state_get_name (old_state),
|
||||
gst_element_state_get_name (pending));
|
||||
|
||||
if (pending == GST_STATE_VOID_PENDING)
|
||||
return GST_STATE_SUCCESS;
|
||||
|
||||
if (old_state == pending)
|
||||
{
|
||||
GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
|
||||
"old and pending state are both %s, returning",
|
||||
gst_element_state_get_name (pending));
|
||||
if (old_state == pending) {
|
||||
GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
|
||||
"old and pending state are both %s, returning",
|
||||
gst_element_state_get_name (pending));
|
||||
return GST_STATE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -728,16 +732,16 @@ gst_bin_change_state (GstElement * element)
|
|||
old_child_state = GST_STATE (child);
|
||||
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||
"changing state of child %s from current %s to pending %s",
|
||||
GST_ELEMENT_NAME (child), gst_element_state_get_name (old_child_state),
|
||||
gst_element_state_get_name (pending));
|
||||
"changing state of child %s from current %s to pending %s",
|
||||
GST_ELEMENT_NAME (child), gst_element_state_get_name (old_child_state),
|
||||
gst_element_state_get_name (pending));
|
||||
|
||||
switch (gst_element_set_state (child, pending)) {
|
||||
case GST_STATE_FAILURE:
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
|
||||
"child '%s' failed to go to state %d(%s)",
|
||||
GST_ELEMENT_NAME (child),
|
||||
pending, gst_element_state_get_name (pending));
|
||||
"child '%s' failed to go to state %d(%s)",
|
||||
GST_ELEMENT_NAME (child),
|
||||
pending, gst_element_state_get_name (pending));
|
||||
|
||||
gst_element_set_state (child, old_child_state);
|
||||
/* There was a check for elements being in the same scheduling group
|
||||
|
@ -750,30 +754,31 @@ gst_bin_change_state (GstElement * element)
|
|||
break;
|
||||
case GST_STATE_ASYNC:
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
|
||||
"child '%s' is changing state asynchronously",
|
||||
GST_ELEMENT_NAME (child));
|
||||
"child '%s' is changing state asynchronously",
|
||||
GST_ELEMENT_NAME (child));
|
||||
have_async = TRUE;
|
||||
break;
|
||||
case GST_STATE_SUCCESS:
|
||||
GST_CAT_DEBUG (GST_CAT_STATES, "child '%s' changed state to %d(%s) successfully",
|
||||
GST_ELEMENT_NAME (child), pending, gst_element_state_get_name (pending));
|
||||
break;
|
||||
GST_CAT_DEBUG (GST_CAT_STATES,
|
||||
"child '%s' changed state to %d(%s) successfully",
|
||||
GST_ELEMENT_NAME (child), pending,
|
||||
gst_element_state_get_name (pending));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||
"done changing bin's state from %s to %s, now in %s",
|
||||
gst_element_state_get_name (old_state),
|
||||
gst_element_state_get_name (pending),
|
||||
gst_element_state_get_name (GST_STATE (element)));
|
||||
"done changing bin's state from %s to %s, now in %s",
|
||||
gst_element_state_get_name (old_state),
|
||||
gst_element_state_get_name (pending),
|
||||
gst_element_state_get_name (GST_STATE (element)));
|
||||
|
||||
if (have_async)
|
||||
ret = GST_STATE_ASYNC;
|
||||
else {
|
||||
if (parent_class->change_state) {
|
||||
ret = parent_class->change_state(element);
|
||||
}
|
||||
else
|
||||
ret = parent_class->change_state (element);
|
||||
} else
|
||||
ret = GST_STATE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
|
@ -790,8 +795,7 @@ gst_bin_change_state_norecurse (GstBin * bin)
|
|||
ret = parent_class->change_state (GST_ELEMENT (bin));
|
||||
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
} else
|
||||
return GST_STATE_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -842,8 +846,8 @@ gst_bin_get_by_name (GstBin * bin, const gchar * name)
|
|||
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s",
|
||||
GST_ELEMENT_NAME (bin), name);
|
||||
GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s",
|
||||
GST_ELEMENT_NAME (bin), name);
|
||||
|
||||
children = bin->children;
|
||||
while (children) {
|
||||
|
@ -925,10 +929,10 @@ gst_bin_get_list (GstBin * bin)
|
|||
* Returns: An element inside the bin implementing the interface.
|
||||
*/
|
||||
GstElement *
|
||||
gst_bin_get_by_interface (GstBin *bin, GType interface)
|
||||
gst_bin_get_by_interface (GstBin * bin, GType interface)
|
||||
{
|
||||
GList *walk;
|
||||
|
||||
|
||||
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
||||
g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface), NULL);
|
||||
|
||||
|
@ -938,6 +942,7 @@ gst_bin_get_by_interface (GstBin *bin, GType interface)
|
|||
return GST_ELEMENT (walk->data);
|
||||
if (GST_IS_BIN (walk->data)) {
|
||||
GstElement *ret;
|
||||
|
||||
ret = gst_bin_get_by_interface (GST_BIN (walk->data), interface);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -961,10 +966,10 @@ gst_bin_get_by_interface (GstBin *bin, GType interface)
|
|||
* Returns: An element inside the bin implementing the interface.
|
||||
*/
|
||||
GList *
|
||||
gst_bin_get_all_by_interface (GstBin *bin, GType interface)
|
||||
gst_bin_get_all_by_interface (GstBin * bin, GType interface)
|
||||
{
|
||||
GList *walk, *ret = NULL;
|
||||
|
||||
|
||||
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
||||
g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface), NULL);
|
||||
|
||||
|
@ -973,13 +978,13 @@ gst_bin_get_all_by_interface (GstBin *bin, GType interface)
|
|||
if (G_TYPE_CHECK_INSTANCE_TYPE (walk->data, interface))
|
||||
ret = g_list_prepend (ret, walk->data);
|
||||
if (GST_IS_BIN (walk->data)) {
|
||||
ret = g_list_concat (ret,
|
||||
ret = g_list_concat (ret,
|
||||
gst_bin_get_all_by_interface (GST_BIN (walk->data), interface));
|
||||
}
|
||||
walk = g_list_next (walk);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -995,7 +1000,7 @@ gst_bin_get_all_by_interface (GstBin *bin, GType interface)
|
|||
* this function returns #GST_STATE_FAILURE.
|
||||
*/
|
||||
GstElementStateReturn
|
||||
gst_bin_sync_children_state (GstBin *bin)
|
||||
gst_bin_sync_children_state (GstBin * bin)
|
||||
{
|
||||
GList *children;
|
||||
GstElement *element;
|
||||
|
@ -1006,31 +1011,33 @@ gst_bin_sync_children_state (GstBin *bin)
|
|||
|
||||
state = GST_STATE (bin);
|
||||
children = bin->children;
|
||||
GST_CAT_INFO (GST_CAT_STATES, "syncing state of children with bin \"%s\"'s state %s",
|
||||
GST_ELEMENT_NAME (bin), gst_element_state_get_name (state));
|
||||
GST_CAT_INFO (GST_CAT_STATES,
|
||||
"syncing state of children with bin \"%s\"'s state %s",
|
||||
GST_ELEMENT_NAME (bin), gst_element_state_get_name (state));
|
||||
|
||||
while (children) {
|
||||
element = GST_ELEMENT (children->data);
|
||||
children = children->next;
|
||||
if (GST_STATE(element) != state) {
|
||||
if (GST_STATE (element) != state) {
|
||||
switch (gst_element_set_state (element, state)) {
|
||||
case GST_STATE_SUCCESS:
|
||||
break;
|
||||
case GST_STATE_ASYNC:
|
||||
if (ret == GST_STATE_SUCCESS)
|
||||
ret = GST_STATE_ASYNC;
|
||||
break;
|
||||
case GST_STATE_FAILURE:
|
||||
ret = GST_STATE_FAILURE;
|
||||
default:
|
||||
/* make sure gst_element_set_state never returns this */
|
||||
g_assert_not_reached ();
|
||||
case GST_STATE_SUCCESS:
|
||||
break;
|
||||
case GST_STATE_ASYNC:
|
||||
if (ret == GST_STATE_SUCCESS)
|
||||
ret = GST_STATE_ASYNC;
|
||||
break;
|
||||
case GST_STATE_FAILURE:
|
||||
ret = GST_STATE_FAILURE;
|
||||
default:
|
||||
/* make sure gst_element_set_state never returns this */
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
static xmlNodePtr
|
||||
gst_bin_save_thyself (GstObject * object, xmlNodePtr parent)
|
||||
|
@ -1045,8 +1052,8 @@ gst_bin_save_thyself (GstObject * object, xmlNodePtr parent)
|
|||
|
||||
childlist = xmlNewChild (parent, NULL, "children", NULL);
|
||||
|
||||
GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
|
||||
GST_ELEMENT_NAME (bin), bin->numchildren);
|
||||
GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
|
||||
GST_ELEMENT_NAME (bin), bin->numchildren);
|
||||
|
||||
children = bin->children;
|
||||
while (children) {
|
||||
|
@ -1067,17 +1074,19 @@ gst_bin_restore_thyself (GstObject * object, xmlNodePtr self)
|
|||
|
||||
while (field) {
|
||||
if (!strcmp (field->name, "children")) {
|
||||
GST_CAT_INFO (GST_CAT_XML, "[%s]: loading children", GST_ELEMENT_NAME (object));
|
||||
GST_CAT_INFO (GST_CAT_XML, "[%s]: loading children",
|
||||
GST_ELEMENT_NAME (object));
|
||||
childlist = field->xmlChildrenNode;
|
||||
while (childlist) {
|
||||
if (!strcmp (childlist->name, "element")) {
|
||||
GstElement *element = gst_xml_make_element (childlist, GST_OBJECT (bin));
|
||||
|
||||
/* it had to be parented to find the pads, now we ref and unparent so
|
||||
* we can add it to the bin */
|
||||
gst_object_ref (GST_OBJECT (element));
|
||||
gst_object_unparent (GST_OBJECT (element));
|
||||
|
||||
GstElement *element =
|
||||
gst_xml_make_element (childlist, GST_OBJECT (bin));
|
||||
|
||||
/* it had to be parented to find the pads, now we ref and unparent so
|
||||
* we can add it to the bin */
|
||||
gst_object_ref (GST_OBJECT (element));
|
||||
gst_object_unparent (GST_OBJECT (element));
|
||||
|
||||
gst_bin_add (bin, element);
|
||||
}
|
||||
childlist = childlist->next;
|
||||
|
@ -1101,14 +1110,12 @@ gst_bin_iterate_func (GstBin * bin)
|
|||
|
||||
if (state == GST_SCHEDULER_STATE_RUNNING) {
|
||||
return TRUE;
|
||||
}
|
||||
else if (state == GST_SCHEDULER_STATE_ERROR) {
|
||||
} else if (state == GST_SCHEDULER_STATE_ERROR) {
|
||||
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
|
||||
}
|
||||
}
|
||||
else {
|
||||
g_warning ("bin \"%s\" is not the managing bin, can't be iterated on!\n",
|
||||
GST_ELEMENT_NAME (bin));
|
||||
} else {
|
||||
g_warning ("bin \"%s\" is not the managing bin, can't be iterated on!\n",
|
||||
GST_ELEMENT_NAME (bin));
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
@ -1124,7 +1131,7 @@ gst_bin_iterate_func (GstBin * bin)
|
|||
* can be used to determine it the bin is in EOS.
|
||||
*/
|
||||
gboolean
|
||||
gst_bin_iterate (GstBin *bin)
|
||||
gst_bin_iterate (GstBin * bin)
|
||||
{
|
||||
gboolean running;
|
||||
|
||||
|
@ -1141,10 +1148,11 @@ gst_bin_iterate (GstBin *bin)
|
|||
GST_CAT_LOG_OBJECT (GST_CAT_DATAFLOW, bin, "finished iteration");
|
||||
|
||||
if (!running) {
|
||||
if (GST_STATE (bin) == GST_STATE_PLAYING &&
|
||||
if (GST_STATE (bin) == GST_STATE_PLAYING &&
|
||||
GST_STATE_PENDING (bin) == GST_STATE_VOID_PENDING) {
|
||||
GST_CAT_DEBUG (GST_CAT_DATAFLOW, "[%s]: polling for child shutdown after useless iteration",
|
||||
GST_ELEMENT_NAME (bin));
|
||||
GST_CAT_DEBUG (GST_CAT_DATAFLOW,
|
||||
"[%s]: polling for child shutdown after useless iteration",
|
||||
GST_ELEMENT_NAME (bin));
|
||||
g_usleep (1);
|
||||
running = TRUE;
|
||||
}
|
||||
|
|
88
gst/gstbin.h
88
gst/gstbin.h
|
@ -26,9 +26,7 @@
|
|||
|
||||
#include <gst/gstelement.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
extern GType _gst_bin_type;
|
||||
G_BEGIN_DECLS extern GType _gst_bin_type;
|
||||
|
||||
#define GST_TYPE_BIN (_gst_bin_type)
|
||||
#define GST_IS_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_BIN))
|
||||
|
@ -37,11 +35,12 @@ extern GType _gst_bin_type;
|
|||
#define GST_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_BIN, GstBin))
|
||||
#define GST_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_BIN, GstBinClass))
|
||||
|
||||
typedef void (*GstBinPrePostIterateFunction) (GstBin *bin, gpointer user_data);
|
||||
typedef void (*GstBinPrePostIterateFunction) (GstBin * bin, gpointer user_data);
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
/* this bin is a manager of child elements, i.e. a pipeline or thread */
|
||||
GST_BIN_FLAG_MANAGER = GST_ELEMENT_FLAG_LAST,
|
||||
GST_BIN_FLAG_MANAGER = GST_ELEMENT_FLAG_LAST,
|
||||
|
||||
/* this bin iterates itself */
|
||||
GST_BIN_SELF_SCHEDULABLE,
|
||||
|
@ -52,81 +51,78 @@ typedef enum {
|
|||
GST_BIN_FLAG_FIXED_CLOCK,
|
||||
|
||||
/* padding */
|
||||
GST_BIN_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 5
|
||||
GST_BIN_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 5
|
||||
} GstBinFlags;
|
||||
|
||||
/*typedef struct _GstBin GstBin; */
|
||||
/*typedef struct _GstBinClass GstBinClass; */
|
||||
|
||||
struct _GstBin {
|
||||
GstElement element;
|
||||
struct _GstBin
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
/* our children */
|
||||
gint numchildren;
|
||||
GList *children;
|
||||
gint numchildren;
|
||||
GList *children;
|
||||
|
||||
GstElementState child_states[GST_NUM_STATES];
|
||||
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
struct _GstBinClass {
|
||||
struct _GstBinClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
|
||||
/* vtable */
|
||||
void (*add_element) (GstBin *bin, GstElement *element);
|
||||
void (*remove_element) (GstBin *bin, GstElement *element);
|
||||
void (*child_state_change) (GstBin *bin, GstElementState oldstate,
|
||||
GstElementState newstate, GstElement *element);
|
||||
void (*add_element) (GstBin * bin, GstElement * element);
|
||||
void (*remove_element) (GstBin * bin, GstElement * element);
|
||||
void (*child_state_change) (GstBin * bin, GstElementState oldstate,
|
||||
GstElementState newstate, GstElement * element);
|
||||
|
||||
/* run a full iteration of operation */
|
||||
gboolean (*iterate) (GstBin *bin);
|
||||
gboolean (*iterate) (GstBin * bin);
|
||||
|
||||
/* signals */
|
||||
void (*element_added) (GstBin *bin, GstElement *child);
|
||||
void (*element_removed) (GstBin *bin, GstElement *child);
|
||||
void (*element_added) (GstBin * bin, GstElement * child);
|
||||
void (*element_removed) (GstBin * bin, GstElement * child);
|
||||
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
GType gst_bin_get_type (void);
|
||||
GstElement* gst_bin_new (const gchar *name);
|
||||
GType gst_bin_get_type (void);
|
||||
GstElement *gst_bin_new (const gchar * name);
|
||||
|
||||
/* add and remove elements from the bin */
|
||||
void gst_bin_add (GstBin *bin, GstElement *element);
|
||||
void gst_bin_add_many (GstBin *bin, GstElement *element_1, ...);
|
||||
void gst_bin_remove (GstBin *bin, GstElement *element);
|
||||
void gst_bin_remove_many (GstBin *bin, GstElement *element_1, ...);
|
||||
void gst_bin_add (GstBin * bin, GstElement * element);
|
||||
void gst_bin_add_many (GstBin * bin, GstElement * element_1, ...);
|
||||
void gst_bin_remove (GstBin * bin, GstElement * element);
|
||||
void gst_bin_remove_many (GstBin * bin, GstElement * element_1, ...);
|
||||
|
||||
/* retrieve a single element or the list of children */
|
||||
GstElement* gst_bin_get_by_name (GstBin *bin, const gchar *name);
|
||||
GstElement* gst_bin_get_by_name_recurse_up (GstBin *bin, const gchar *name);
|
||||
G_CONST_RETURN GList*
|
||||
gst_bin_get_list (GstBin *bin);
|
||||
GstElement* gst_bin_get_by_interface (GstBin *bin, GType interface);
|
||||
GList * gst_bin_get_all_by_interface (GstBin *bin, GType interface);
|
||||
GstElement *gst_bin_get_by_name (GstBin * bin, const gchar * name);
|
||||
GstElement *gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name);
|
||||
G_CONST_RETURN GList *gst_bin_get_list (GstBin * bin);
|
||||
GstElement *gst_bin_get_by_interface (GstBin * bin, GType interface);
|
||||
GList *gst_bin_get_all_by_interface (GstBin * bin, GType interface);
|
||||
|
||||
gboolean gst_bin_iterate (GstBin *bin);
|
||||
gboolean gst_bin_iterate (GstBin * bin);
|
||||
|
||||
void gst_bin_use_clock (GstBin *bin, GstClock *clock);
|
||||
GstClock* gst_bin_get_clock (GstBin *bin);
|
||||
void gst_bin_auto_clock (GstBin *bin);
|
||||
void gst_bin_use_clock (GstBin * bin, GstClock * clock);
|
||||
GstClock *gst_bin_get_clock (GstBin * bin);
|
||||
void gst_bin_auto_clock (GstBin * bin);
|
||||
|
||||
GstElementStateReturn gst_bin_sync_children_state (GstBin *bin);
|
||||
GstElementStateReturn gst_bin_sync_children_state (GstBin * bin);
|
||||
|
||||
/* internal */
|
||||
/* one of our childs signaled a state change */
|
||||
void gst_bin_child_state_change (GstBin *bin, GstElementState oldstate,
|
||||
GstElementState newstate, GstElement *child);
|
||||
void gst_bin_child_state_change (GstBin * bin, GstElementState oldstate,
|
||||
GstElementState newstate, GstElement * child);
|
||||
|
||||
void gst_bin_set_pre_iterate_function (GstBin *bin,
|
||||
GstBinPrePostIterateFunction func,
|
||||
gpointer user_data);
|
||||
void gst_bin_set_post_iterate_function (GstBin *bin,
|
||||
GstBinPrePostIterateFunction func,
|
||||
gpointer user_data);
|
||||
void gst_bin_set_pre_iterate_function (GstBin * bin,
|
||||
GstBinPrePostIterateFunction func, gpointer user_data);
|
||||
void gst_bin_set_post_iterate_function (GstBin * bin,
|
||||
GstBinPrePostIterateFunction func, gpointer user_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
#endif /* __GST_BIN_H__ */
|
||||
|
|
161
gst/gstbuffer.c
161
gst/gstbuffer.c
|
@ -43,15 +43,14 @@ void
|
|||
_gst_buffer_initialize (void)
|
||||
{
|
||||
_gst_buffer_type = g_boxed_type_register_static ("GstBuffer",
|
||||
(GBoxedCopyFunc) gst_data_copy,
|
||||
(GBoxedFreeFunc) gst_data_unref);
|
||||
(GBoxedCopyFunc) gst_data_copy, (GBoxedFreeFunc) gst_data_unref);
|
||||
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
_gst_buffer_trace = gst_alloc_trace_register (GST_BUFFER_TRACE_NAME);
|
||||
#endif
|
||||
|
||||
chunk = gst_mem_chunk_new ("GstBufferChunk", sizeof (GstBuffer),
|
||||
sizeof (GstBuffer) * 200, 0);
|
||||
chunk = gst_mem_chunk_new ("GstBufferChunk", sizeof (GstBuffer),
|
||||
sizeof (GstBuffer) * 200, 0);
|
||||
|
||||
GST_CAT_LOG (GST_CAT_BUFFER, "Buffers are initialized now");
|
||||
}
|
||||
|
@ -63,7 +62,7 @@ gst_buffer_get_type (void)
|
|||
}
|
||||
|
||||
static void
|
||||
_gst_buffer_sub_free (GstBuffer *buffer)
|
||||
_gst_buffer_sub_free (GstBuffer * buffer)
|
||||
{
|
||||
gst_data_unref (GST_DATA (buffer->buffer_private));
|
||||
|
||||
|
@ -71,7 +70,7 @@ _gst_buffer_sub_free (GstBuffer *buffer)
|
|||
GST_BUFFER_SIZE (buffer) = 0;
|
||||
|
||||
_GST_DATA_DISPOSE (GST_DATA (buffer));
|
||||
|
||||
|
||||
gst_mem_chunk_free (chunk, GST_DATA (buffer));
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
gst_alloc_trace_free (_gst_buffer_trace, buffer);
|
||||
|
@ -86,14 +85,14 @@ _gst_buffer_sub_free (GstBuffer *buffer)
|
|||
* unless the GST_BUFFER_DONTFREE flags was set or the buffer data is NULL.
|
||||
*/
|
||||
void
|
||||
gst_buffer_default_free (GstBuffer *buffer)
|
||||
gst_buffer_default_free (GstBuffer * buffer)
|
||||
{
|
||||
g_return_if_fail (buffer != NULL);
|
||||
|
||||
/* free our data */
|
||||
if (GST_BUFFER_FREE_DATA_FUNC (buffer)) {
|
||||
GST_BUFFER_FREE_DATA_FUNC (buffer) (buffer);
|
||||
} else if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_DONTFREE)) {
|
||||
} else if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_DONTFREE)) {
|
||||
g_free (GST_BUFFER_DATA (buffer));
|
||||
}
|
||||
|
||||
|
@ -118,16 +117,17 @@ gst_buffer_default_free (GstBuffer *buffer)
|
|||
* the other.
|
||||
*/
|
||||
void
|
||||
gst_buffer_stamp (GstBuffer *dest, const GstBuffer *src)
|
||||
gst_buffer_stamp (GstBuffer * dest, const GstBuffer * src)
|
||||
{
|
||||
g_return_if_fail (dest != NULL);
|
||||
g_return_if_fail (src != NULL);
|
||||
|
||||
GST_BUFFER_TIMESTAMP (dest) = GST_BUFFER_TIMESTAMP (src);
|
||||
GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src);
|
||||
GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src);
|
||||
GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src);
|
||||
|
||||
GST_BUFFER_TIMESTAMP (dest) = GST_BUFFER_TIMESTAMP (src);
|
||||
GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src);
|
||||
GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src);
|
||||
GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_buffer_default_copy:
|
||||
* @buffer: a #GstBuffer to make a copy of.
|
||||
|
@ -136,8 +136,8 @@ gst_buffer_stamp (GstBuffer *dest, const GstBuffer *src)
|
|||
*
|
||||
* Returns: the new #GstBuffer.
|
||||
*/
|
||||
GstBuffer*
|
||||
gst_buffer_default_copy (GstBuffer *buffer)
|
||||
GstBuffer *
|
||||
gst_buffer_default_copy (GstBuffer * buffer)
|
||||
{
|
||||
GstBuffer *copy;
|
||||
|
||||
|
@ -149,17 +149,17 @@ gst_buffer_default_copy (GstBuffer *buffer)
|
|||
gst_alloc_trace_new (_gst_buffer_trace, copy);
|
||||
#endif
|
||||
|
||||
_GST_DATA_INIT (GST_DATA (copy),
|
||||
_gst_buffer_type,
|
||||
0,
|
||||
(GstDataFreeFunction) gst_buffer_default_free,
|
||||
(GstDataCopyFunction) gst_buffer_default_copy);
|
||||
_GST_DATA_INIT (GST_DATA (copy),
|
||||
_gst_buffer_type,
|
||||
0,
|
||||
(GstDataFreeFunction) gst_buffer_default_free,
|
||||
(GstDataCopyFunction) gst_buffer_default_copy);
|
||||
|
||||
/* we simply copy everything from our parent */
|
||||
GST_BUFFER_DATA (copy) = g_memdup (GST_BUFFER_DATA (buffer),
|
||||
GST_BUFFER_SIZE (buffer));
|
||||
GST_BUFFER_SIZE (copy) = GST_BUFFER_SIZE (buffer);
|
||||
GST_BUFFER_MAXSIZE (copy) = GST_BUFFER_SIZE (buffer);
|
||||
GST_BUFFER_DATA (copy) = g_memdup (GST_BUFFER_DATA (buffer),
|
||||
GST_BUFFER_SIZE (buffer));
|
||||
GST_BUFFER_SIZE (copy) = GST_BUFFER_SIZE (buffer);
|
||||
GST_BUFFER_MAXSIZE (copy) = GST_BUFFER_SIZE (buffer);
|
||||
|
||||
gst_buffer_stamp (copy, buffer);
|
||||
GST_BUFFER_FREE_DATA_FUNC (copy) = NULL;
|
||||
|
@ -175,11 +175,11 @@ gst_buffer_default_copy (GstBuffer *buffer)
|
|||
*
|
||||
* Returns: the new #GstBuffer.
|
||||
*/
|
||||
GstBuffer*
|
||||
GstBuffer *
|
||||
gst_buffer_new (void)
|
||||
{
|
||||
GstBuffer *newbuf;
|
||||
|
||||
|
||||
newbuf = gst_mem_chunk_alloc (chunk);
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
gst_alloc_trace_new (_gst_buffer_trace, newbuf);
|
||||
|
@ -187,19 +187,19 @@ gst_buffer_new (void)
|
|||
|
||||
GST_CAT_LOG (GST_CAT_BUFFER, "new %p", newbuf);
|
||||
|
||||
_GST_DATA_INIT (GST_DATA (newbuf),
|
||||
_gst_buffer_type,
|
||||
0,
|
||||
(GstDataFreeFunction) gst_buffer_default_free,
|
||||
(GstDataCopyFunction) gst_buffer_default_copy);
|
||||
_GST_DATA_INIT (GST_DATA (newbuf),
|
||||
_gst_buffer_type,
|
||||
0,
|
||||
(GstDataFreeFunction) gst_buffer_default_free,
|
||||
(GstDataCopyFunction) gst_buffer_default_copy);
|
||||
|
||||
GST_BUFFER_DATA (newbuf) = NULL;
|
||||
GST_BUFFER_SIZE (newbuf) = 0;
|
||||
GST_BUFFER_MAXSIZE (newbuf) = GST_BUFFER_MAXSIZE_NONE;
|
||||
GST_BUFFER_TIMESTAMP (newbuf) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_DURATION (newbuf) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET_NONE;
|
||||
GST_BUFFER_OFFSET_END (newbuf) = GST_BUFFER_OFFSET_NONE;
|
||||
GST_BUFFER_DATA (newbuf) = NULL;
|
||||
GST_BUFFER_SIZE (newbuf) = 0;
|
||||
GST_BUFFER_MAXSIZE (newbuf) = GST_BUFFER_MAXSIZE_NONE;
|
||||
GST_BUFFER_TIMESTAMP (newbuf) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_DURATION (newbuf) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET_NONE;
|
||||
GST_BUFFER_OFFSET_END (newbuf) = GST_BUFFER_OFFSET_NONE;
|
||||
GST_BUFFER_FREE_DATA_FUNC (newbuf) = NULL;
|
||||
GST_BUFFER_PRIVATE (newbuf) = NULL;
|
||||
|
||||
|
@ -214,15 +214,15 @@ gst_buffer_new (void)
|
|||
*
|
||||
* Returns: the new #GstBuffer.
|
||||
*/
|
||||
GstBuffer*
|
||||
GstBuffer *
|
||||
gst_buffer_new_and_alloc (guint size)
|
||||
{
|
||||
GstBuffer *newbuf;
|
||||
|
||||
newbuf = gst_buffer_new ();
|
||||
|
||||
GST_BUFFER_DATA (newbuf) = g_malloc (size);
|
||||
GST_BUFFER_SIZE (newbuf) = size;
|
||||
GST_BUFFER_DATA (newbuf) = g_malloc (size);
|
||||
GST_BUFFER_SIZE (newbuf) = size;
|
||||
GST_BUFFER_MAXSIZE (newbuf) = size;
|
||||
|
||||
return newbuf;
|
||||
|
@ -242,12 +242,12 @@ gst_buffer_new_and_alloc (guint size)
|
|||
*
|
||||
* Returns: the new #GstBuffer, or NULL if there was an error.
|
||||
*/
|
||||
GstBuffer*
|
||||
gst_buffer_create_sub (GstBuffer *parent, guint offset, guint size)
|
||||
GstBuffer *
|
||||
gst_buffer_create_sub (GstBuffer * parent, guint offset, guint size)
|
||||
{
|
||||
GstBuffer *buffer;
|
||||
gpointer buffer_data;
|
||||
|
||||
|
||||
g_return_val_if_fail (parent != NULL, NULL);
|
||||
g_return_val_if_fail (GST_BUFFER_REFCOUNT_VALUE (parent) > 0, NULL);
|
||||
g_return_val_if_fail (size > 0, NULL);
|
||||
|
@ -272,32 +272,31 @@ gst_buffer_create_sub (GstBuffer *parent, guint offset, guint size)
|
|||
|
||||
/* make sure nobody overwrites data in the new buffer
|
||||
* by setting the READONLY flag */
|
||||
_GST_DATA_INIT (GST_DATA (buffer),
|
||||
_gst_buffer_type,
|
||||
GST_DATA_FLAG_SHIFT (GST_BUFFER_SUBBUFFER) |
|
||||
GST_DATA_FLAG_SHIFT (GST_DATA_READONLY),
|
||||
(GstDataFreeFunction) _gst_buffer_sub_free,
|
||||
(GstDataCopyFunction) gst_buffer_default_copy);
|
||||
_GST_DATA_INIT (GST_DATA (buffer),
|
||||
_gst_buffer_type,
|
||||
GST_DATA_FLAG_SHIFT (GST_BUFFER_SUBBUFFER) |
|
||||
GST_DATA_FLAG_SHIFT (GST_DATA_READONLY),
|
||||
(GstDataFreeFunction) _gst_buffer_sub_free,
|
||||
(GstDataCopyFunction) gst_buffer_default_copy);
|
||||
|
||||
/* set the right values in the child */
|
||||
GST_BUFFER_DATA (buffer) = buffer_data;
|
||||
GST_BUFFER_SIZE (buffer) = size;
|
||||
GST_BUFFER_MAXSIZE (buffer) = size;
|
||||
GST_BUFFER_DATA (buffer) = buffer_data;
|
||||
GST_BUFFER_SIZE (buffer) = size;
|
||||
GST_BUFFER_MAXSIZE (buffer) = size;
|
||||
GST_BUFFER_FREE_DATA_FUNC (buffer) = NULL;
|
||||
GST_BUFFER_PRIVATE (buffer) = parent;
|
||||
/* we can copy the timestamp and offset if the new buffer starts at
|
||||
* offset 0 */
|
||||
if (offset == 0) {
|
||||
GST_BUFFER_TIMESTAMP (buffer) = GST_BUFFER_TIMESTAMP (parent);
|
||||
GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET (parent);
|
||||
}
|
||||
else {
|
||||
GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
|
||||
GST_BUFFER_TIMESTAMP (buffer) = GST_BUFFER_TIMESTAMP (parent);
|
||||
GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET (parent);
|
||||
} else {
|
||||
GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
|
||||
}
|
||||
|
||||
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;
|
||||
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;
|
||||
|
||||
if (GST_BUFFER_FLAG_IS_SET (parent, GST_BUFFER_DONTKEEP)) {
|
||||
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_DONTKEEP);
|
||||
|
@ -324,8 +323,8 @@ gst_buffer_create_sub (GstBuffer *parent, guint offset, guint size)
|
|||
*
|
||||
* Returns: the new #GstBuffer that's the concatenation of the source buffers.
|
||||
*/
|
||||
GstBuffer*
|
||||
gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2)
|
||||
GstBuffer *
|
||||
gst_buffer_merge (GstBuffer * buf1, GstBuffer * buf2)
|
||||
{
|
||||
GstBuffer *result;
|
||||
|
||||
|
@ -347,7 +346,7 @@ gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2)
|
|||
* FALSE if a copy would be required.
|
||||
*/
|
||||
gboolean
|
||||
gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2)
|
||||
gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2)
|
||||
{
|
||||
g_return_val_if_fail (buf1 != NULL && buf2 != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_BUFFER_REFCOUNT_VALUE (buf1) > 0, FALSE);
|
||||
|
@ -355,9 +354,9 @@ gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2)
|
|||
|
||||
/* it's only fast if we have subbuffers of the same parent */
|
||||
return ((GST_BUFFER_FLAG_IS_SET (buf1, GST_BUFFER_SUBBUFFER)) &&
|
||||
(GST_BUFFER_FLAG_IS_SET (buf2, GST_BUFFER_SUBBUFFER)) &&
|
||||
(buf1->buffer_private == buf2->buffer_private) &&
|
||||
((buf1->data + buf1->size) == buf2->data));
|
||||
(GST_BUFFER_FLAG_IS_SET (buf2, GST_BUFFER_SUBBUFFER)) &&
|
||||
(buf1->buffer_private == buf2->buffer_private) &&
|
||||
((buf1->data + buf1->size) == buf2->data));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -380,8 +379,9 @@ gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2)
|
|||
*
|
||||
* Returns: the new #GstBuffer that spans the two source buffers.
|
||||
*/
|
||||
GstBuffer*
|
||||
gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
|
||||
GstBuffer *
|
||||
gst_buffer_span (GstBuffer * buf1, guint32 offset, GstBuffer * buf2,
|
||||
guint32 len)
|
||||
{
|
||||
GstBuffer *newbuf;
|
||||
|
||||
|
@ -394,21 +394,21 @@ gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
|
|||
/* if the two buffers have the same parent and are adjacent */
|
||||
if (gst_buffer_is_span_fast (buf1, buf2)) {
|
||||
GstBuffer *parent = GST_BUFFER (buf1->buffer_private);
|
||||
|
||||
/* we simply create a subbuffer of the common parent */
|
||||
newbuf = gst_buffer_create_sub (parent,
|
||||
buf1->data - parent->data + offset, len);
|
||||
}
|
||||
else {
|
||||
GST_CAT_DEBUG (GST_CAT_BUFFER, "slow path taken while spanning buffers %p and %p",
|
||||
buf1, buf2);
|
||||
newbuf = gst_buffer_create_sub (parent,
|
||||
buf1->data - parent->data + offset, len);
|
||||
} else {
|
||||
GST_CAT_DEBUG (GST_CAT_BUFFER,
|
||||
"slow path taken while spanning buffers %p and %p", buf1, buf2);
|
||||
/* otherwise we simply have to brute-force copy the buffers */
|
||||
newbuf = gst_buffer_new_and_alloc (len);
|
||||
|
||||
/* copy the first buffer's data across */
|
||||
memcpy (newbuf->data, buf1->data + offset, buf1->size - offset);
|
||||
/* copy the second buffer's data across */
|
||||
memcpy (newbuf->data + (buf1->size - offset), buf2->data,
|
||||
len - (buf1->size - offset));
|
||||
memcpy (newbuf->data + (buf1->size - offset), buf2->data,
|
||||
len - (buf1->size - offset));
|
||||
/* if the offset is 0, the new buffer has the same timestamp as buf1 */
|
||||
if (offset == 0) {
|
||||
GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET (buf1);
|
||||
|
@ -422,8 +422,8 @@ gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
|
|||
if (GST_BUFFER_DURATION_IS_VALID (buf1) &&
|
||||
GST_BUFFER_DURATION_IS_VALID (buf2)) {
|
||||
/* add duration */
|
||||
GST_BUFFER_DURATION (newbuf) = GST_BUFFER_DURATION (buf1) +
|
||||
GST_BUFFER_DURATION (buf2);
|
||||
GST_BUFFER_DURATION (newbuf) = GST_BUFFER_DURATION (buf1) +
|
||||
GST_BUFFER_DURATION (buf2);
|
||||
}
|
||||
if (GST_BUFFER_OFFSET_END_IS_VALID (buf2)) {
|
||||
/* add offset_end */
|
||||
|
@ -433,4 +433,3 @@ gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
|
|||
|
||||
return newbuf;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,11 +27,9 @@
|
|||
#include <gst/gstdata.h>
|
||||
#include <gst/gstclock.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
G_BEGIN_DECLS typedef struct _GstBuffer GstBuffer;
|
||||
|
||||
typedef struct _GstBuffer GstBuffer;
|
||||
|
||||
typedef void (*GstBufferFreeDataFunc) (GstBuffer *buffer);
|
||||
typedef void (*GstBufferFreeDataFunc) (GstBuffer * buffer);
|
||||
|
||||
#define GST_BUFFER_TRACE_NAME "GstBuffer"
|
||||
|
||||
|
@ -74,27 +72,29 @@ extern GType _gst_buffer_type;
|
|||
#define GST_BUFFER_OFFSET_END_IS_VALID(buffer) (GST_BUFFER_OFFSET_END (buffer) != GST_BUFFER_OFFSET_NONE)
|
||||
#define GST_BUFFER_MAXSIZE_IS_VALID(buffer) (GST_BUFFER_MAXSIZE (buffer) != GST_BUFFER_MAXSIZE_NONE)
|
||||
|
||||
typedef enum {
|
||||
GST_BUFFER_READONLY = GST_DATA_READONLY,
|
||||
GST_BUFFER_SUBBUFFER = GST_DATA_FLAG_LAST,
|
||||
typedef enum
|
||||
{
|
||||
GST_BUFFER_READONLY = GST_DATA_READONLY,
|
||||
GST_BUFFER_SUBBUFFER = GST_DATA_FLAG_LAST,
|
||||
GST_BUFFER_ORIGINAL,
|
||||
GST_BUFFER_DONTFREE,
|
||||
GST_BUFFER_KEY_UNIT,
|
||||
GST_BUFFER_DONTKEEP,
|
||||
GST_BUFFER_FLAG_LAST = GST_DATA_FLAG_LAST + 8
|
||||
GST_BUFFER_FLAG_LAST = GST_DATA_FLAG_LAST + 8
|
||||
} GstBufferFlag;
|
||||
|
||||
struct _GstBuffer {
|
||||
GstData data_type;
|
||||
struct _GstBuffer
|
||||
{
|
||||
GstData data_type;
|
||||
|
||||
/* pointer to data and its size */
|
||||
guint8 *data; /* pointer to buffer data */
|
||||
guint size; /* size of buffer data */
|
||||
guint maxsize; /* max size of this buffer */
|
||||
guint8 *data; /* pointer to buffer data */
|
||||
guint size; /* size of buffer data */
|
||||
guint maxsize; /* max size of this buffer */
|
||||
|
||||
/* timestamp */
|
||||
GstClockTime timestamp;
|
||||
GstClockTime duration;
|
||||
GstClockTime timestamp;
|
||||
GstClockTime duration;
|
||||
|
||||
/* media specific offset
|
||||
* for video frames, this could be the number of frames,
|
||||
|
@ -103,19 +103,19 @@ struct _GstBuffer {
|
|||
* offset_end is the last offset contained in the buffer. The format specifies
|
||||
* the meaning of both of them exactly.
|
||||
*/
|
||||
guint64 offset;
|
||||
guint64 offset_end;
|
||||
guint64 offset;
|
||||
guint64 offset_end;
|
||||
|
||||
GstBufferFreeDataFunc free_data;
|
||||
gpointer buffer_private;
|
||||
GstBufferFreeDataFunc free_data;
|
||||
gpointer buffer_private;
|
||||
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
/* allocation */
|
||||
GType gst_buffer_get_type (void);
|
||||
GstBuffer* gst_buffer_new (void);
|
||||
GstBuffer* gst_buffer_new_and_alloc (guint size);
|
||||
GType gst_buffer_get_type (void);
|
||||
GstBuffer *gst_buffer_new (void);
|
||||
GstBuffer *gst_buffer_new_and_alloc (guint size);
|
||||
|
||||
#define gst_buffer_set_data(buf, data, size) \
|
||||
G_STMT_START { \
|
||||
|
@ -128,25 +128,26 @@ G_STMT_START { \
|
|||
#define gst_buffer_ref_by_count(buf,c) GST_BUFFER (gst_data_ref_by_count (GST_DATA (buf), c))
|
||||
#define gst_buffer_unref(buf) gst_data_unref (GST_DATA (buf))
|
||||
/* copy buffer */
|
||||
void gst_buffer_stamp (GstBuffer *dest, const GstBuffer *src);
|
||||
void gst_buffer_stamp (GstBuffer * dest, const GstBuffer * src);
|
||||
|
||||
#define gst_buffer_copy(buf) GST_BUFFER (gst_data_copy (GST_DATA (buf)))
|
||||
#define gst_buffer_is_writable(buf) gst_data_is_writable (GST_DATA (buf))
|
||||
#define gst_buffer_copy_on_write(buf) GST_BUFFER (gst_data_copy_on_write (GST_DATA (buf)))
|
||||
|
||||
/* creating a subbuffer */
|
||||
GstBuffer* gst_buffer_create_sub (GstBuffer *parent, guint offset, guint size);
|
||||
GstBuffer *gst_buffer_create_sub (GstBuffer * parent, guint offset, guint size);
|
||||
|
||||
/* merge, span, or append two buffers, intelligently */
|
||||
GstBuffer* gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2);
|
||||
gboolean gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2);
|
||||
GstBuffer* gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len);
|
||||
GstBuffer *gst_buffer_merge (GstBuffer * buf1, GstBuffer * buf2);
|
||||
gboolean gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2);
|
||||
GstBuffer *gst_buffer_span (GstBuffer * buf1, guint32 offset, GstBuffer * buf2,
|
||||
guint32 len);
|
||||
|
||||
/* --- private --- */
|
||||
void _gst_buffer_initialize (void);
|
||||
void _gst_buffer_initialize (void);
|
||||
|
||||
void gst_buffer_default_free (GstBuffer *buffer);
|
||||
GstBuffer* gst_buffer_default_copy (GstBuffer *buffer);
|
||||
void gst_buffer_default_free (GstBuffer * buffer);
|
||||
GstBuffer *gst_buffer_default_copy (GstBuffer * buffer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_BUFFER_H__ */
|
||||
|
|
443
gst/gstcaps.c
443
gst/gstcaps.c
File diff suppressed because it is too large
Load diff
114
gst/gstcaps.h
114
gst/gstcaps.h
|
@ -24,119 +24,103 @@
|
|||
#include <gst/gststructure.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_CAPS gst_caps_get_type()
|
||||
#define GST_CAPS(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GST_TYPE_CAPS, GstCaps))
|
||||
#define GST_IS_CAPS(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GST_TYPE_CAPS))
|
||||
|
||||
#define GST_CAPS_FLAGS_ANY (1 << 0)
|
||||
|
||||
#define GST_CAPS_ANY gst_caps_new_any()
|
||||
#define GST_CAPS_NONE gst_caps_new_empty()
|
||||
|
||||
#define GST_STATIC_CAPS_ANY GST_STATIC_CAPS("ANY")
|
||||
#define GST_STATIC_CAPS_NONE GST_STATIC_CAPS("NONE")
|
||||
|
||||
#define GST_CAPS_IS_SIMPLE(caps) (gst_caps_get_size(caps) == 1)
|
||||
#define gst_caps_is_simple(caps) GST_CAPS_IS_SIMPLE(caps)
|
||||
|
||||
#ifndef GST_DISABLE_DEPRECATED
|
||||
#define GST_DEBUG_CAPS(string, caps) \
|
||||
GST_DEBUG ( string "%s: " GST_PTR_FORMAT, caps)
|
||||
#endif
|
||||
|
||||
#define GST_STATIC_CAPS(string) \
|
||||
{ \
|
||||
/* caps */ { 0 }, \
|
||||
/* string */ string, \
|
||||
}
|
||||
|
||||
typedef struct _GstCaps GstCaps;
|
||||
typedef struct _GstStaticCaps GstStaticCaps;
|
||||
|
||||
struct _GstCaps {
|
||||
struct _GstCaps
|
||||
{
|
||||
GType type;
|
||||
|
||||
guint16 flags;
|
||||
GPtrArray *structs;
|
||||
};
|
||||
|
||||
struct _GstStaticCaps {
|
||||
struct _GstStaticCaps
|
||||
{
|
||||
GstCaps caps;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
GType gst_caps_get_type (void) G_GNUC_CONST;
|
||||
GstCaps * gst_caps_new_empty (void);
|
||||
GstCaps * gst_caps_new_any (void);
|
||||
GstCaps * gst_caps_new_simple (const char *media_type,
|
||||
const char *fieldname,
|
||||
...);
|
||||
GstCaps * gst_caps_new_full (GstStructure *struct1,
|
||||
...);
|
||||
GstCaps * gst_caps_new_full_valist (GstStructure *structure,
|
||||
va_list var_args);
|
||||
GstCaps * gst_caps_copy (const GstCaps *caps);
|
||||
void gst_caps_free (GstCaps *caps);
|
||||
G_CONST_RETURN GstCaps * gst_static_caps_get (GstStaticCaps *caps);
|
||||
GType
|
||||
gst_caps_get_type (void)
|
||||
G_GNUC_CONST;
|
||||
GstCaps *gst_caps_new_empty (void);
|
||||
GstCaps *gst_caps_new_any (void);
|
||||
GstCaps *gst_caps_new_simple (const char *media_type,
|
||||
const char *fieldname, ...);
|
||||
GstCaps *gst_caps_new_full (GstStructure * struct1, ...);
|
||||
GstCaps *gst_caps_new_full_valist (GstStructure * structure,
|
||||
va_list var_args);
|
||||
GstCaps *gst_caps_copy (const GstCaps * caps);
|
||||
void gst_caps_free (GstCaps * caps);
|
||||
G_CONST_RETURN GstCaps *gst_static_caps_get (GstStaticCaps * caps);
|
||||
|
||||
/* manipulation */
|
||||
void gst_caps_append (GstCaps *caps1,
|
||||
GstCaps *caps2);
|
||||
void gst_caps_append_structure (GstCaps *caps1,
|
||||
GstStructure *structure);
|
||||
GstCaps * gst_caps_split_one (GstCaps *caps);
|
||||
int gst_caps_get_size (const GstCaps *caps);
|
||||
GstStructure * gst_caps_get_structure (const GstCaps *caps,
|
||||
int index);
|
||||
void gst_caps_append (GstCaps * caps1, GstCaps * caps2);
|
||||
void gst_caps_append_structure (GstCaps * caps1, GstStructure * structure);
|
||||
GstCaps *gst_caps_split_one (GstCaps * caps);
|
||||
int gst_caps_get_size (const GstCaps * caps);
|
||||
GstStructure *gst_caps_get_structure (const GstCaps * caps, int index);
|
||||
|
||||
#ifndef GST_DISABLE_DEPRECATED
|
||||
GstCaps * gst_caps_copy_1 (const GstCaps *caps);
|
||||
GstCaps *gst_caps_copy_1 (const GstCaps * caps);
|
||||
#endif
|
||||
void gst_caps_set_simple (GstCaps *caps,
|
||||
char *field, ...);
|
||||
void gst_caps_set_simple_valist (GstCaps *caps,
|
||||
char *field,
|
||||
va_list varargs);
|
||||
void gst_caps_set_simple (GstCaps * caps, char *field, ...);
|
||||
void gst_caps_set_simple_valist (GstCaps * caps,
|
||||
char *field, va_list varargs);
|
||||
|
||||
/* tests */
|
||||
gboolean gst_caps_is_any (const GstCaps *caps);
|
||||
gboolean gst_caps_is_empty (const GstCaps *caps);
|
||||
gboolean gst_caps_is_any (const GstCaps * caps);
|
||||
gboolean gst_caps_is_empty (const GstCaps * caps);
|
||||
|
||||
#ifndef GST_DISABLE_DEPRECATED
|
||||
gboolean gst_caps_is_chained (const GstCaps *caps);
|
||||
gboolean gst_caps_is_chained (const GstCaps * caps);
|
||||
#endif
|
||||
gboolean gst_caps_is_fixed (const GstCaps *caps);
|
||||
gboolean gst_caps_is_equal_fixed (const GstCaps *caps1,
|
||||
const GstCaps *caps2);
|
||||
gboolean gst_caps_is_always_compatible (const GstCaps *caps1,
|
||||
const GstCaps *caps2);
|
||||
gboolean gst_caps_is_fixed (const GstCaps * caps);
|
||||
gboolean gst_caps_is_equal_fixed (const GstCaps * caps1,
|
||||
const GstCaps * caps2);
|
||||
gboolean gst_caps_is_always_compatible (const GstCaps * caps1,
|
||||
const GstCaps * caps2);
|
||||
|
||||
/* operations */
|
||||
GstCaps * gst_caps_intersect (const GstCaps *caps1,
|
||||
const GstCaps *caps2);
|
||||
GstCaps * gst_caps_union (const GstCaps *caps1,
|
||||
const GstCaps *caps2);
|
||||
GstCaps * gst_caps_normalize (const GstCaps *caps);
|
||||
GstCaps * gst_caps_simplify (const GstCaps *caps);
|
||||
GstCaps *gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2);
|
||||
GstCaps *gst_caps_union (const GstCaps * caps1, const GstCaps * caps2);
|
||||
GstCaps *gst_caps_normalize (const GstCaps * caps);
|
||||
GstCaps *gst_caps_simplify (const GstCaps * caps);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
xmlNodePtr gst_caps_save_thyself (const GstCaps *caps,
|
||||
xmlNodePtr parent);
|
||||
GstCaps * gst_caps_load_thyself (xmlNodePtr parent);
|
||||
xmlNodePtr gst_caps_save_thyself (const GstCaps * caps, xmlNodePtr parent);
|
||||
GstCaps *gst_caps_load_thyself (xmlNodePtr parent);
|
||||
#endif
|
||||
|
||||
/* utility */
|
||||
void gst_caps_replace (GstCaps **caps,
|
||||
GstCaps *newcaps);
|
||||
gchar * gst_caps_to_string (const GstCaps *caps);
|
||||
GstCaps * gst_caps_from_string (const gchar *string);
|
||||
void gst_caps_replace (GstCaps ** caps, GstCaps * newcaps);
|
||||
gchar *gst_caps_to_string (const GstCaps * caps);
|
||||
GstCaps *gst_caps_from_string (const gchar * string);
|
||||
|
||||
gboolean gst_caps_structure_fixate_field_nearest_int (GstStructure *structure,
|
||||
const char *field_name,
|
||||
int target);
|
||||
gboolean gst_caps_structure_fixate_field_nearest_double (GstStructure *structure,
|
||||
const char *field_name,
|
||||
double target);
|
||||
gboolean gst_caps_structure_fixate_field_nearest_int (GstStructure *
|
||||
structure, const char *field_name, int target);
|
||||
gboolean gst_caps_structure_fixate_field_nearest_double (GstStructure *
|
||||
structure, const char *field_name, double target);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_CAPS_H__ */
|
||||
|
|
174
gst/gstclock.c
174
gst/gstclock.c
|
@ -37,35 +37,37 @@ static GstAllocTrace *_gst_clock_entry_trace;
|
|||
#define DEFAULT_EVENT_DIFF (GST_SECOND)
|
||||
#define DEFAULT_MAX_DIFF (2 * GST_SECOND)
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_STATS,
|
||||
ARG_MAX_DIFF,
|
||||
ARG_EVENT_DIFF
|
||||
};
|
||||
|
||||
static GstMemChunk *_gst_clock_entries_chunk;
|
||||
static GstMemChunk *_gst_clock_entries_chunk;
|
||||
|
||||
void gst_clock_id_unlock (GstClockID id);
|
||||
void gst_clock_id_unlock (GstClockID id);
|
||||
|
||||
|
||||
static void gst_clock_class_init (GstClockClass *klass);
|
||||
static void gst_clock_init (GstClock *clock);
|
||||
static void gst_clock_dispose (GObject *object);
|
||||
|
||||
static void gst_clock_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_clock_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec * pspec);
|
||||
static void gst_clock_update_stats (GstClock *clock);
|
||||
static void gst_clock_class_init (GstClockClass * klass);
|
||||
static void gst_clock_init (GstClock * clock);
|
||||
static void gst_clock_dispose (GObject * object);
|
||||
|
||||
static void gst_clock_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_clock_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
static void gst_clock_update_stats (GstClock * clock);
|
||||
|
||||
|
||||
static GstObjectClass *parent_class = NULL;
|
||||
|
||||
/* static guint gst_clock_signals[LAST_SIGNAL] = { 0 }; */
|
||||
|
||||
static GstClockID
|
||||
gst_clock_entry_new (GstClock *clock, GstClockTime time,
|
||||
GstClockTime interval, GstClockEntryType type)
|
||||
gst_clock_entry_new (GstClock * clock, GstClockTime time,
|
||||
GstClockTime interval, GstClockEntryType type)
|
||||
{
|
||||
GstClockEntry *entry;
|
||||
|
||||
|
@ -94,14 +96,12 @@ gst_clock_entry_new (GstClock *clock, GstClockTime time,
|
|||
* Returns: An id that can be used to request the time notification.
|
||||
*/
|
||||
GstClockID
|
||||
gst_clock_new_single_shot_id (GstClock *clock, GstClockTime time)
|
||||
gst_clock_new_single_shot_id (GstClock * clock, GstClockTime time)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
|
||||
|
||||
return gst_clock_entry_new (clock,
|
||||
time,
|
||||
GST_CLOCK_TIME_NONE,
|
||||
GST_CLOCK_ENTRY_SINGLE);
|
||||
return gst_clock_entry_new (clock,
|
||||
time, GST_CLOCK_TIME_NONE, GST_CLOCK_ENTRY_SINGLE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,17 +117,15 @@ gst_clock_new_single_shot_id (GstClock *clock, GstClockTime time)
|
|||
* Returns: An id that can be used to request the time notification.
|
||||
*/
|
||||
GstClockID
|
||||
gst_clock_new_periodic_id (GstClock *clock, GstClockTime start_time,
|
||||
GstClockTime interval)
|
||||
gst_clock_new_periodic_id (GstClock * clock, GstClockTime start_time,
|
||||
GstClockTime interval)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
|
||||
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (start_time), NULL);
|
||||
g_return_val_if_fail (interval != 0, NULL);
|
||||
|
||||
return gst_clock_entry_new (clock,
|
||||
start_time,
|
||||
interval,
|
||||
GST_CLOCK_ENTRY_PERIODIC);
|
||||
return gst_clock_entry_new (clock,
|
||||
start_time, interval, GST_CLOCK_ENTRY_PERIODIC);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -143,7 +141,7 @@ gst_clock_id_get_time (GstClockID id)
|
|||
{
|
||||
g_return_val_if_fail (id != NULL, GST_CLOCK_TIME_NONE);
|
||||
|
||||
return GST_CLOCK_ENTRY_TIME ((GstClockEntry *)id);
|
||||
return GST_CLOCK_ENTRY_TIME ((GstClockEntry *) id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -158,30 +156,30 @@ gst_clock_id_get_time (GstClockID id)
|
|||
* Returns: the result of the blocking wait.
|
||||
*/
|
||||
GstClockReturn
|
||||
gst_clock_id_wait (GstClockID id, GstClockTimeDiff *jitter)
|
||||
gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter)
|
||||
{
|
||||
GstClockEntry *entry;
|
||||
GstClock *clock;
|
||||
GstClockReturn res = GST_CLOCK_UNSUPPORTED;
|
||||
GstClockTime requested;
|
||||
GstClockClass *cclass;
|
||||
|
||||
|
||||
g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
|
||||
|
||||
entry = (GstClockEntry *) id;
|
||||
requested = GST_CLOCK_ENTRY_TIME (entry);
|
||||
|
||||
if (! GST_CLOCK_TIME_IS_VALID (requested)) {
|
||||
if (!GST_CLOCK_TIME_IS_VALID (requested)) {
|
||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "invalid time requested, returning _TIMEOUT");
|
||||
return GST_CLOCK_TIMEOUT;
|
||||
}
|
||||
|
||||
clock = GST_CLOCK_ENTRY_CLOCK (entry);
|
||||
cclass = GST_CLOCK_GET_CLASS (clock);
|
||||
|
||||
|
||||
if (cclass->wait) {
|
||||
GstClockTime now;
|
||||
|
||||
|
||||
GST_LOCK (clock);
|
||||
clock->entries = g_list_prepend (clock->entries, entry);
|
||||
GST_UNLOCK (clock);
|
||||
|
@ -223,20 +221,20 @@ gst_clock_id_wait (GstClockID id, GstClockTimeDiff *jitter)
|
|||
*/
|
||||
GstClockReturn
|
||||
gst_clock_id_wait_async (GstClockID id,
|
||||
GstClockCallback func, gpointer user_data)
|
||||
GstClockCallback func, gpointer user_data)
|
||||
{
|
||||
GstClockEntry *entry;
|
||||
GstClock *clock;
|
||||
GstClockReturn res = GST_CLOCK_UNSUPPORTED;
|
||||
GstClockClass *cclass;
|
||||
|
||||
|
||||
g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
|
||||
g_return_val_if_fail (func != NULL, GST_CLOCK_ERROR);
|
||||
|
||||
entry = (GstClockEntry *) id;
|
||||
clock = entry->clock;
|
||||
|
||||
if (! GST_CLOCK_TIME_IS_VALID (GST_CLOCK_ENTRY_TIME (entry))) {
|
||||
if (!GST_CLOCK_TIME_IS_VALID (GST_CLOCK_ENTRY_TIME (entry))) {
|
||||
(func) (clock, GST_CLOCK_TIME_NONE, id, user_data);
|
||||
return GST_CLOCK_TIMEOUT;
|
||||
}
|
||||
|
@ -254,11 +252,11 @@ gst_clock_id_wait_async (GstClockID id,
|
|||
}
|
||||
|
||||
static void
|
||||
gst_clock_reschedule_func (GstClockEntry *entry)
|
||||
gst_clock_reschedule_func (GstClockEntry * entry)
|
||||
{
|
||||
entry->status = GST_CLOCK_ENTRY_OK;
|
||||
|
||||
gst_clock_id_unlock ((GstClockID)entry);
|
||||
|
||||
gst_clock_id_unlock ((GstClockID) entry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -273,7 +271,7 @@ gst_clock_id_unschedule (GstClockID id)
|
|||
GstClockEntry *entry;
|
||||
GstClock *clock;
|
||||
GstClockClass *cclass;
|
||||
|
||||
|
||||
g_return_if_fail (id != NULL);
|
||||
|
||||
entry = (GstClockEntry *) id;
|
||||
|
@ -314,7 +312,7 @@ gst_clock_id_unlock (GstClockID id)
|
|||
GstClockEntry *entry;
|
||||
GstClock *clock;
|
||||
GstClockClass *cclass;
|
||||
|
||||
|
||||
g_return_if_fail (id != NULL);
|
||||
|
||||
entry = (GstClockEntry *) id;
|
||||
|
@ -348,20 +346,20 @@ gst_clock_get_type (void)
|
|||
(GInstanceInitFunc) gst_clock_init,
|
||||
NULL
|
||||
};
|
||||
clock_type = g_type_register_static (GST_TYPE_OBJECT, "GstClock",
|
||||
&clock_info, G_TYPE_FLAG_ABSTRACT);
|
||||
clock_type = g_type_register_static (GST_TYPE_OBJECT, "GstClock",
|
||||
&clock_info, G_TYPE_FLAG_ABSTRACT);
|
||||
}
|
||||
return clock_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clock_class_init (GstClockClass *klass)
|
||||
gst_clock_class_init (GstClockClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstObjectClass *gstobject_class;
|
||||
|
||||
gobject_class = (GObjectClass*) klass;
|
||||
gstobject_class = (GstObjectClass*) klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstobject_class = (GstObjectClass *) klass;
|
||||
|
||||
parent_class = g_type_class_ref (GST_TYPE_OBJECT);
|
||||
|
||||
|
@ -369,31 +367,33 @@ gst_clock_class_init (GstClockClass *klass)
|
|||
g_thread_init (NULL);
|
||||
|
||||
_gst_clock_entries_chunk = gst_mem_chunk_new ("GstClockEntries",
|
||||
sizeof (GstClockEntry), sizeof (GstClockEntry) * 32,
|
||||
G_ALLOC_AND_FREE);
|
||||
sizeof (GstClockEntry), sizeof (GstClockEntry) * 32, G_ALLOC_AND_FREE);
|
||||
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
_gst_clock_entry_trace = gst_alloc_trace_register (GST_CLOCK_ENTRY_TRACE_NAME);
|
||||
_gst_clock_entry_trace =
|
||||
gst_alloc_trace_register (GST_CLOCK_ENTRY_TRACE_NAME);
|
||||
#endif
|
||||
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_clock_dispose);
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_clock_dispose);
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_clock_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_clock_get_property);
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STATS,
|
||||
g_param_spec_boolean ("stats", "Stats", "Enable clock stats",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_param_spec_boolean ("stats", "Stats", "Enable clock stats",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_DIFF,
|
||||
g_param_spec_int64 ("max-diff", "Max diff", "The maximum amount of time to wait in nanoseconds",
|
||||
0, G_MAXINT64, DEFAULT_MAX_DIFF, G_PARAM_READWRITE));
|
||||
g_param_spec_int64 ("max-diff", "Max diff",
|
||||
"The maximum amount of time to wait in nanoseconds", 0, G_MAXINT64,
|
||||
DEFAULT_MAX_DIFF, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EVENT_DIFF,
|
||||
g_param_spec_uint64 ("event-diff", "event diff",
|
||||
"The amount of time that may elapse until 2 events are treated as happening at different times",
|
||||
0, G_MAXUINT64, DEFAULT_EVENT_DIFF, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_param_spec_uint64 ("event-diff", "event diff",
|
||||
"The amount of time that may elapse until 2 events are treated as happening at different times",
|
||||
0, G_MAXUINT64, DEFAULT_EVENT_DIFF,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clock_init (GstClock *clock)
|
||||
gst_clock_init (GstClock * clock)
|
||||
{
|
||||
clock->max_diff = DEFAULT_MAX_DIFF;
|
||||
|
||||
|
@ -408,7 +408,7 @@ gst_clock_init (GstClock *clock)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_clock_dispose (GObject *object)
|
||||
gst_clock_dispose (GObject * object)
|
||||
{
|
||||
GstClock *clock = GST_CLOCK (object);
|
||||
|
||||
|
@ -429,7 +429,7 @@ gst_clock_dispose (GObject *object)
|
|||
* Returns: the new speed of the clock.
|
||||
*/
|
||||
gdouble
|
||||
gst_clock_set_speed (GstClock *clock, gdouble speed)
|
||||
gst_clock_set_speed (GstClock * clock, gdouble speed)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_CLOCK (clock), 0.0);
|
||||
|
||||
|
@ -446,7 +446,7 @@ gst_clock_set_speed (GstClock *clock, gdouble speed)
|
|||
* Returns: the speed of the clock.
|
||||
*/
|
||||
gdouble
|
||||
gst_clock_get_speed (GstClock *clock)
|
||||
gst_clock_get_speed (GstClock * clock)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_CLOCK (clock), 0.0);
|
||||
|
||||
|
@ -464,7 +464,7 @@ gst_clock_get_speed (GstClock *clock)
|
|||
* Returns: the new resolution of the clock.
|
||||
*/
|
||||
guint64
|
||||
gst_clock_set_resolution (GstClock *clock, guint64 resolution)
|
||||
gst_clock_set_resolution (GstClock * clock, guint64 resolution)
|
||||
{
|
||||
GstClockClass *cclass;
|
||||
|
||||
|
@ -474,7 +474,8 @@ gst_clock_set_resolution (GstClock *clock, guint64 resolution)
|
|||
cclass = GST_CLOCK_GET_CLASS (clock);
|
||||
|
||||
if (cclass->change_resolution)
|
||||
clock->resolution = cclass->change_resolution (clock, clock->resolution, resolution);
|
||||
clock->resolution =
|
||||
cclass->change_resolution (clock, clock->resolution, resolution);
|
||||
|
||||
return clock->resolution;
|
||||
}
|
||||
|
@ -488,7 +489,7 @@ gst_clock_set_resolution (GstClock *clock, guint64 resolution)
|
|||
* Returns: the resolution of the clock in microseconds.
|
||||
*/
|
||||
guint64
|
||||
gst_clock_get_resolution (GstClock *clock)
|
||||
gst_clock_get_resolution (GstClock * clock)
|
||||
{
|
||||
GstClockClass *cclass;
|
||||
|
||||
|
@ -511,10 +512,10 @@ gst_clock_get_resolution (GstClock *clock)
|
|||
* As soon as the clock is activated, the time will start ticking.
|
||||
*/
|
||||
void
|
||||
gst_clock_set_active (GstClock *clock, gboolean active)
|
||||
gst_clock_set_active (GstClock * clock, gboolean active)
|
||||
{
|
||||
g_return_if_fail (GST_IS_CLOCK (clock));
|
||||
|
||||
|
||||
GST_ERROR_OBJECT (clock, "called deprecated function that does nothing now.");
|
||||
|
||||
return;
|
||||
|
@ -529,7 +530,7 @@ gst_clock_set_active (GstClock *clock, gboolean active)
|
|||
* Returns: TRUE if the clock is active.
|
||||
*/
|
||||
gboolean
|
||||
gst_clock_is_active (GstClock *clock)
|
||||
gst_clock_is_active (GstClock * clock)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
|
||||
|
||||
|
@ -545,7 +546,7 @@ gst_clock_is_active (GstClock *clock)
|
|||
* Reset the clock to time 0.
|
||||
*/
|
||||
void
|
||||
gst_clock_reset (GstClock *clock)
|
||||
gst_clock_reset (GstClock * clock)
|
||||
{
|
||||
GstClockTime time = G_GINT64_CONSTANT (0);
|
||||
GstClockClass *cclass;
|
||||
|
@ -555,7 +556,7 @@ gst_clock_reset (GstClock *clock)
|
|||
GST_ERROR_OBJECT (clock, "called deprecated function.");
|
||||
|
||||
cclass = GST_CLOCK_GET_CLASS (clock);
|
||||
|
||||
|
||||
if (cclass->get_internal_time) {
|
||||
time = cclass->get_internal_time (clock);
|
||||
}
|
||||
|
@ -580,7 +581,7 @@ gst_clock_reset (GstClock *clock)
|
|||
* discontinuitity in the pipeline is honoured.
|
||||
*/
|
||||
gboolean
|
||||
gst_clock_handle_discont (GstClock *clock, guint64 time)
|
||||
gst_clock_handle_discont (GstClock * clock, guint64 time)
|
||||
{
|
||||
GST_ERROR_OBJECT (clock, "called deprecated function.");
|
||||
|
||||
|
@ -597,7 +598,7 @@ gst_clock_handle_discont (GstClock *clock, guint64 time)
|
|||
* Returns: the time of the clock.
|
||||
*/
|
||||
GstClockTime
|
||||
gst_clock_get_time (GstClock *clock)
|
||||
gst_clock_get_time (GstClock * clock)
|
||||
{
|
||||
GstClockTime ret = G_GINT64_CONSTANT (0);
|
||||
GstClockClass *cclass;
|
||||
|
@ -612,8 +613,7 @@ gst_clock_get_time (GstClock *clock)
|
|||
/* make sure the time is increasing, else return last_time */
|
||||
if ((gint64) ret < (gint64) clock->last_time) {
|
||||
ret = clock->last_time;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
clock->last_time = ret;
|
||||
}
|
||||
|
||||
|
@ -632,23 +632,23 @@ gst_clock_get_time (GstClock *clock)
|
|||
* Returns: the time of the event
|
||||
*/
|
||||
GstClockTime
|
||||
gst_clock_get_event_time (GstClock *clock)
|
||||
gst_clock_get_event_time (GstClock * clock)
|
||||
{
|
||||
GstClockTime time;
|
||||
|
||||
|
||||
g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
|
||||
|
||||
|
||||
time = gst_clock_get_time (clock);
|
||||
|
||||
if (clock->last_event + clock->max_event_diff >= time) {
|
||||
GST_LOG_OBJECT (clock, "reporting last event time %"G_GUINT64_FORMAT,
|
||||
GST_LOG_OBJECT (clock, "reporting last event time %" G_GUINT64_FORMAT,
|
||||
clock->last_event);
|
||||
} else {
|
||||
GST_LOG_OBJECT (clock, "reporting new event time %"G_GUINT64_FORMAT,
|
||||
GST_LOG_OBJECT (clock, "reporting new event time %" G_GUINT64_FORMAT,
|
||||
clock->last_event);
|
||||
clock->last_event = time;
|
||||
}
|
||||
|
||||
|
||||
return clock->last_event;
|
||||
}
|
||||
|
||||
|
@ -661,7 +661,7 @@ gst_clock_get_event_time (GstClock *clock)
|
|||
* Returns: a clockid or NULL is no event is pending.
|
||||
*/
|
||||
GstClockID
|
||||
gst_clock_get_next_id (GstClock *clock)
|
||||
gst_clock_get_next_id (GstClock * clock)
|
||||
{
|
||||
GstClockEntry *entry = NULL;
|
||||
|
||||
|
@ -676,16 +676,16 @@ gst_clock_get_next_id (GstClock *clock)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_clock_update_stats (GstClock *clock)
|
||||
gst_clock_update_stats (GstClock * clock)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clock_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
gst_clock_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstClock *clock;
|
||||
|
||||
|
||||
clock = GST_CLOCK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
|
@ -704,15 +704,15 @@ gst_clock_set_property (GObject *object, guint prop_id,
|
|||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clock_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec * pspec)
|
||||
gst_clock_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstClock *clock;
|
||||
|
||||
|
||||
clock = GST_CLOCK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
|
@ -728,5 +728,5 @@ gst_clock_get_property (GObject *object, guint prop_id,
|
|||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue