Merged the AUTOPLUG2 branch

Original commit message from CVS:
Merged the AUTOPLUG2 branch
This commit is contained in:
Wim Taymans 2001-03-07 21:52:56 +00:00
parent 031e0a3acb
commit 55006f6367
57 changed files with 2837 additions and 1247 deletions

View file

@ -597,6 +597,7 @@ AM_CONDITIONAL(HAVE_LIBSHOUT, test "x$HAVE_LIBSHOUT" = "xyes")
AM_CONDITIONAL(HAVE_LIBESD, test "x$HAVE_LIBESD" = "xyes")
AM_CONDITIONAL(HAVE_LIBASOUND, test "x$HAVE_LIBASOUND" = "xyes")
AM_CONDITIONAL(HAVE_MPEG2DEC, test "x$HAVE_MPEG2DEC" = "xyes")
AM_CONDITIONAL(HAVE_LIBXMMS, test "x$HAVE_LIBXMMS" = "xyes")
@ -680,6 +681,7 @@ gst/Makefile
gst/types/Makefile
gst/meta/Makefile
gst/elements/Makefile
gst/autoplug/Makefile
libs/Makefile
libs/riff/Makefile
libs/colorspace/Makefile

View file

@ -15,60 +15,18 @@ to convert a certain GstCaps to another one.
</para>
<!-- ##### MACRO GST_AUTOPLUG_MAX_COST ##### -->
<para>
The maximum cost of a certain connection.
</para>
<!-- ##### USER_FUNCTION GstAutoplugCostFunction ##### -->
<para>
Calculate the cost between two elements.
</para>
@src: the source element
@dest: the destination element
@data: optional user data
@Returns: the cost for a connection between the two elements
<!-- ##### USER_FUNCTION GstAutoplugListFunction ##### -->
<para>
Get a list of all elements. These elements will be used in autoplugging.
</para>
@data: user data
@Returns: a GList of elements
<!-- ##### FUNCTION gst_autoplug_caps ##### -->
<para>
</para>
@srccaps:
@sinkcaps:
@Returns:
<!-- ##### FUNCTION gst_autoplug_pads ##### -->
<para>
</para>
@srcpad:
@sinkpad:
@Returns:
<!-- ##### FUNCTION gst_autoplug_caps_list ##### -->
<para>
</para>
@autoplug:
@srcpad:
@sinkpad:
@Varargs:
@Returns:
<!-- # Unused Parameters # -->
@srccaps:
@sinkcaps:
@Returns:

View file

@ -133,6 +133,8 @@ a start/stop timecode pair.
@offset: the offset of the region to get
@len: the length of the region to get
@Returns: a #GstBuffer
<!-- # Unused Parameters # -->
@size: the size of the region to get
<!-- ##### USER_FUNCTION GstPadQoSFunction ##### -->

View file

@ -38,33 +38,6 @@ pipeline figure out what plugins to use.
@Returns:
<!-- ##### FUNCTION gst_pipeline_add_sink ##### -->
<para>
</para>
@pipeline:
@sink:
<!-- ##### FUNCTION gst_pipeline_add_src ##### -->
<para>
</para>
@pipeline:
@src:
<!-- ##### FUNCTION gst_pipeline_autoplug ##### -->
<para>
</para>
@pipeline:
@Returns:
<!-- ##### MACRO gst_pipeline_destroy ##### -->
<para>
Destroys the pipeline.

View file

@ -27,6 +27,8 @@ GStreamer is extensible so <classname>GstElements</classname> can be loaded at r
@numtypes:
@elements:
@numelements:
@autopluggers:
@numautopluggers:
@loaded:
<!-- ##### STRUCT GstPluginElement ##### -->
@ -203,15 +205,6 @@ by the loader at statup.
@Returns:
<!-- ##### FUNCTION gst_plugin_find_elementfactory ##### -->
<para>
</para>
@name:
@Returns:
<!-- ##### FUNCTION gst_plugin_load_elementfactory ##### -->
<para>

View file

@ -780,10 +780,6 @@ Query whether this object has multiple input pads.
</para>
<!-- ##### SECTION ./tmpl/gstasyncdisksrc.sgml:Short_Description ##### -->
Asynchronous disk reader. (asyncdisksrc)
<!-- ##### FUNCTION gst_src_signal_eos ##### -->
<para>
@ -1383,11 +1379,15 @@ The start point of a filter graph
@klass:
<<<<<<< gstreamer-unused.sgml
<!-- ##### SECTION ./tmpl/gstasyncdisksrc.sgml:Title ##### -->
GstAsyncDiskSrc
<!-- ##### MACRO GST_TYPE_ASYNCDISKSRC ##### -->
=======
<!-- ##### MACRO GST_TYPE_ASYNCDISKSRC ##### -->
>>>>>>> 1.23.2.3
<para>
</para>
@ -2009,6 +2009,7 @@ GstFilter
</para>
<<<<<<< gstreamer-unused.sgml
<!-- ##### ENUM GstSrcFlags ##### -->
<para>
Flags for the GstSrc element
@ -2024,6 +2025,18 @@ Flags for the GstSrc element
<!-- ##### MACRO GST_HTTPSRC ##### -->
=======
<!-- ##### ENUM GstSrcFlags ##### -->
<para>
Flags for the GstSrc element
</para>
@GST_SRC_ASYNC: Indicates that this src is asynchronous
@GST_SRC_FLAG_LAST: subclasses can use this to number their flags
<!-- ##### MACRO GST_HTTPSRC ##### -->
>>>>>>> 1.23.2.3
<para>
</para>

149
docs/random/hierarchy Normal file
View file

@ -0,0 +1,149 @@
Face it, the plugins/ directory hierarchy is crap. We want to propose a
better layout for it now. Some things to consider:
- Elements have a klass member in the factory that is used to
denote the functional type of the element. For example, the
mp3 encoder has a klass of Filter/Encoder/Audio
- The plugins can be grouped together by the media type they
operate on or by the way they work (decoder/encoder)
In GStreamer all plugins are techically filters, the only way they
can be considered sources or sinks (input/output) elements is
by the absence of src/sink pads. At first sight the source/filter/
sink distinction is quite useless because most of the plugins
will go into the filters category anyway.
We don't want to make the hierarchy too deep, yet provide a
clean way to ask for a mp3 decoder element..
Anyway this is a rough proposal to fire off the discussions...
Wim
Source
Disk
disksrc
fdsrc
multifilesrc
Network
HTTPsrc
RTPsrc
CDDA
cdparanoia
XMMS
..
DVD
dvdsrc
Audio
ASLA
OSS
Capture
v4lsrc
firewire
Demuxer
AVI
MPEG1
MPEG2
QT
Muxer
AVI
MPEG1
QT
Aggregator
Tee
gsttee
Connection
queue
CORBA
Parser
MPEG1
MPEG2
AC3
Mixer
Audio
Merge
Video
Subtitles
Merge
Filters
Audio
ladspa
resample
Video
colorspace
Effect
Audio
stereo
volume
delay
chorus
Video
median
smooth
XMMS
Decoder
MPEG1
MPEG2
MP3
mpg123
xing
win32
AU
WAV
JPEG
AC3
ac3dec
RTJPEG
vorbis
Encoder
MPEG1
MPEG2
MP3
lame
mpegaudio
win32
JPEG
AU
WAV
RTJPEG
Vorbis
Visualisation
Video
histogram
Audio
smoothwave
spectrum
synaesthesia
vumeter
XMMS
Sink
Disk
filesink
multifilesink
Network
ICECASTsink
FTPsink
RTPsink
XMMS
ESD
Video
videosink
SDLsink
Audio
OSSsink
ALSAsink

View file

@ -42,22 +42,26 @@ any intermediate steps to accomplish this conversion.
The API for the user apps should be no more then this:
GstElement* gst_autoplug_construct (GstAutoplug *autoplug,
GstCaps *incaps,
GstCaps *outcaps, ...);
GstElement* gst_autoplug_caps_list (GstAutoplug *autoplug,
GList *incaps,
GList *outcaps, ...);
autoplug is a reference to the autoplug implementation
incaps is a GstCaps handle for the source pad, the last set
of arguments is a va_list of destination caps.
incaps is a GList of GstCaps* for the source pad, the last set
of arguments is a va_list of destination caps lists.
A handle to the autoplugger implementation can be obtained
with
GList* gst_autoplug_get_list (void);
GList* gst_autoplugfactory_get_list (void);
which will return a GList* of autopluggers.
GstAutoplug* gst_autoplug_get ("name");
GstAutoplug* gst_autoplugfactory_make ("name");
or
GstAutoplug* gst_autoplugfactory_create (GstAutoplugFactory *autoplug);
is used to get an autoplugger.
@ -72,11 +76,12 @@ overriding various methods.
the autoplugger can be registered with:
gst_plugin_add_autoplugger (GstPlugin *plugin,
GstAutoplug *autoplug);
GstAutoplugFactory *autoplug);
This will allow us to only load the autoplugger when needed.
4) implementation
-----------------
@ -108,11 +113,9 @@ properties:
- name, description, more text to identify the autoplugger.
- a class method autoplug_construct that has to be implemented by
- a class method autoplug_caps_list that has to be implemented by
the real autoplugger.
- possible PadTemplates that this autoplugger can handle well?
optionally, the core autoplugger code can provide convenience
functions to implement custom autopluggers. The shortest path
algorithm with pluggable weighting and list functions come to
@ -124,8 +127,9 @@ A possible use case would be to let gstmediaplay perform an
autoplug on the media stream and insert a custom sound/video
effect in the pipeline when an appropriate element is created.
the "new_object" signal will be fired by the autoplugger whenever
a new object has been created. This signal can be caught by the
user app to perform an introspection on the newly created object.
comments?
Wim

View file

@ -155,14 +155,14 @@ struct _GstEditorElement {
struct _GstEditorElementClass {
GnomeCanvasGroupClass parent_class;
void (*name_changed) (GstEditorElement *element);
void (*position_changed) (GstEditorElement *element);
void (*size_changed) (GstEditorElement *element);
void (*realize) (GstEditorElement *element);
gint (*event) (GnomeCanvasItem *item,GdkEvent *event,
GstEditorElement *element);
gint (*button_event) (GnomeCanvasItem *item,GdkEvent *event,
GstEditorElement *element);
void (*name_changed) (GstEditorElement *element);
void (*position_changed) (GstEditorElement *element);
void (*size_changed) (GstEditorElement *element);
void (*realize) (GstEditorElement *element);
gint (*event) (GnomeCanvasItem *item,GdkEvent *event,
GstEditorElement *element);
gint (*button_event) (GnomeCanvasItem *item,GdkEvent *event,
GstEditorElement *element);
};
@ -188,11 +188,11 @@ const gchar *gst_editor_element_get_name(GstEditorElement *element);
(GTK_CHECK_TYPE((obj),GST_TYPE_EDITOR_BIN))
#define GST_IS_EDITOR_BIN_CLASS(obj) \
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EDITOR_BIN))
struct _GstEditorBin {
GstEditorElement element;
/* lists of GUI elements and connections */
/* lists of GUI elements and connections */
GList *elements, *connections;
/* connection state */
@ -213,11 +213,11 @@ struct _GstEditorBinClass {
GtkType gst_editor_bin_get_type();
GstEditorBin* gst_editor_bin_new (GstBin *bin, const gchar *first_arg_name,...);
void gst_editor_bin_add (GstEditorBin *bin, GstEditorElement *element);
void gst_editor_bin_connection_drag (GstEditorBin *bin,
gdouble wx,gdouble wy);
void gst_editor_bin_start_banding (GstEditorBin *bin,GstEditorPad *pad);
void gst_editor_bin_add (GstEditorBin *bin, GstEditorElement *element);
void gst_editor_bin_connection_drag (GstEditorBin *bin,
gdouble wx,gdouble wy);
void gst_editor_bin_start_banding (GstEditorBin *bin,GstEditorPad *pad);
#define GST_TYPE_EDITOR_CANVAS \
@ -246,8 +246,8 @@ struct _GstEditorCanvasClass {
GstEditorCanvas* gst_editor_canvas_new (void);
GstEditorCanvas* gst_editor_canvas_new_with_bin (GstEditorBin *bin);
void gst_editor_canvas_set_bin (GstEditorCanvas *canvas,
GstEditorBin *element);
void gst_editor_canvas_set_bin (GstEditorCanvas *canvas,
GstEditorBin *element);
GstEditorElement* gst_editor_canvas_get_bin (GstEditorCanvas *canvas);
@ -263,7 +263,7 @@ GstEditorElement* gst_editor_canvas_get_bin (GstEditorCanvas *canvas);
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EDITOR_PAD))
struct _GstEditorPad {
GtkObject object;
GtkObject object;
/* parent element */
GstEditorElement *parent;
@ -291,7 +291,7 @@ struct _GstEditorPad {
gdouble width,height; // actual size
gdouble boxwidth,boxheight; // size of pad box
gboolean resize; // does it need resizing?
/* interaction state */
gboolean dragging,resizing,moved;
gdouble dragx,dragy;
@ -300,13 +300,13 @@ struct _GstEditorPad {
// GnomeCanvasItem *connection; // can't use
//GstEditorConnection
};
struct _GstEditorPadClass {
GtkObjectClass parent_class;
void (*realize) (GstEditorPad *pad);
};
GtkType gst_editor_pad_get_type();
GstEditorPad *gst_editor_pad_new(GstEditorElement *parent,GstPad *pad,
const gchar *first_arg_name, ...);
@ -329,7 +329,7 @@ void gst_editor_pad_repack(GstEditorPad *pad);
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EDITOR_PADTEMPLATE))
struct _GstEditorPadTemplate {
GtkObject object;
GtkObject object;
/* parent element */
GstEditorElement *parent;
@ -361,7 +361,7 @@ struct _GstEditorPadTemplate {
gdouble width,height; // actual size
gdouble boxwidth,boxheight; // size of padtemplate box
gboolean resize; // does it need resizing?
/* interaction state */
gboolean dragging,resizing,moved;
gdouble dragx,dragy;
@ -370,13 +370,13 @@ struct _GstEditorPadTemplate {
// GnomeCanvasItem *connection; // can't use
//GstEditorConnection
};
struct _GstEditorPadTemplateClass {
GtkObjectClass parent_class;
void (*realize) (GstEditorPadTemplate *padtemplate);
};
GtkType gst_editor_padtemplate_get_type();
GstEditorPadTemplate *gst_editor_padtemplate_new(GstEditorElement *parent,GstPadTemplate *padtemplate,
const gchar *first_arg_name, ...);

View file

@ -31,8 +31,6 @@ int main(int argc,char *argv[])
exit(-1);
}
/* create a new bin to hold the elements */
pipeline = gst_pipeline_new("pipeline");
g_assert(pipeline != NULL);
@ -59,6 +57,7 @@ int main(int argc,char *argv[])
gtk_widget_show_all(appwindow);
/* add objects to the main pipeline */
/*
gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc);
gst_pipeline_add_sink(GST_PIPELINE(pipeline), videosink);
gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink);
@ -67,6 +66,7 @@ int main(int argc,char *argv[])
g_print("unable to handle stream\n");
exit(-1);
}
*/
xmlSaveFile("xmlTest.gst", gst_xml_write(GST_ELEMENT(pipeline)));

View file

@ -41,6 +41,7 @@ int main(int argc,char *argv[])
g_assert(audiosink != NULL);
/* add objects to the main pipeline */
/*
gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc);
gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink);
@ -48,6 +49,7 @@ int main(int argc,char *argv[])
g_print("unable to handle stream\n");
exit(-1);
}
*/
// hmmmm hack? FIXME
GST_FLAG_UNSET (pipeline, GST_BIN_FLAG_MANAGER);

View file

@ -46,11 +46,12 @@ int main(int argc,char *argv[])
g_assert(audiosink != NULL);
/* add objects to the main pipeline */
/*
gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc);
gst_pipeline_add_sink(GST_PIPELINE(pipeline), queue);
gst_bin_add(GST_BIN(thread), audiosink);
gst_pad_connect(gst_element_get_pad(queue,"src"),
gst_element_get_pad(audiosink,"sink"));
@ -58,6 +59,7 @@ int main(int argc,char *argv[])
g_print("cannot autoplug pipeline\n");
exit(-1);
}
*/
gst_bin_add(GST_BIN(pipeline), thread);

View file

@ -45,6 +45,7 @@ int main(int argc,char *argv[])
g_assert(audiosink != NULL);
/* add objects to the main pipeline */
/*
gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc);
gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink);
@ -52,6 +53,7 @@ int main(int argc,char *argv[])
g_print("unable to handle stream\n");
exit(-1);
}
*/
//gst_bin_remove(GST_BIN(pipeline), disksrc);

View file

@ -1,5 +1,5 @@
# cheap trick to build . first...
SUBDIRS = . types meta elements
SUBDIRS = . types meta elements autoplug
lib_LTLIBRARIES = libgst.la

12
gst/autoplug/Makefile.am Normal file
View file

@ -0,0 +1,12 @@
filterdir = $(libdir)/gst
filter_LTLIBRARIES = libgststaticautoplug.la libgststaticautoplugrender.la
libgststaticautoplug_la_SOURCES = \
gststaticautoplug.c
libgststaticautoplugrender_la_SOURCES = \
gststaticautoplugrender.c
libgststaticautoplug_la_LDFLAGS = -version-info $(GSTREAMER_LIBVERSION)
libgststaticautoplugrender_la_LDFLAGS = -version-info $(GSTREAMER_LIBVERSION)

View file

@ -0,0 +1,619 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gststaticautoplug.c: A static Autoplugger of pipelines
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gststaticautoplug.h"
#include <gst/gst.h>
#define GST_AUTOPLUG_MAX_COST 999999
typedef guint (*GstAutoplugCostFunction) (gpointer src, gpointer dest, gpointer data);
typedef GList* (*GstAutoplugListFunction) (gpointer data);
static void gst_static_autoplug_class_init (GstStaticAutoplugClass *klass);
static void gst_static_autoplug_init (GstStaticAutoplug *autoplug);
static GList* gst_autoplug_func (gpointer src, gpointer sink,
GstAutoplugListFunction list_function,
GstAutoplugCostFunction cost_function,
gpointer data);
static GstElement* gst_static_autoplug_to_caps (GstAutoplug *autoplug,
GList *srccaps, GList *sinkcaps, va_list args);
static GstAutoplugClass *parent_class = NULL;
GtkType gst_static_autoplug_get_type(void)
{
static GtkType static_autoplug_type = 0;
if (!static_autoplug_type) {
static const GtkTypeInfo static_autoplug_info = {
"GstStaticAutoplug",
sizeof(GstElement),
sizeof(GstElementClass),
(GtkClassInitFunc)gst_static_autoplug_class_init,
(GtkObjectInitFunc)gst_static_autoplug_init,
(GtkArgSetFunc)NULL,
(GtkArgGetFunc)NULL,
(GtkClassInitFunc)NULL,
};
static_autoplug_type = gtk_type_unique (GST_TYPE_AUTOPLUG, &static_autoplug_info);
}
return static_autoplug_type;
}
static void
gst_static_autoplug_class_init(GstStaticAutoplugClass *klass)
{
GstAutoplugClass *gstautoplug_class;
gstautoplug_class = (GstAutoplugClass*) klass;
parent_class = gtk_type_class(GST_TYPE_AUTOPLUG);
gstautoplug_class->autoplug_to_caps = gst_static_autoplug_to_caps;
}
static void gst_static_autoplug_init(GstStaticAutoplug *autoplug) {
}
GstPlugin*
plugin_init (GModule *module)
{
GstPlugin *plugin;
GstAutoplugFactory *factory;
plugin = gst_plugin_new("gststaticautoplug");
g_return_val_if_fail(plugin != NULL,NULL);
gst_plugin_set_longname (plugin, "A static autoplugger");
factory = gst_autoplugfactory_new ("static",
"A static autoplugger, it constructs the complete element before running it",
gst_static_autoplug_get_type ());
if (factory != NULL) {
gst_plugin_add_autoplugger (plugin, factory);
}
return plugin;
}
static gboolean
gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest)
{
GList *srctemps, *desttemps;
srctemps = src->padtemplates;
while (srctemps) {
GstPadTemplate *srctemp = (GstPadTemplate *)srctemps->data;
desttemps = dest->padtemplates;
while (desttemps) {
GstPadTemplate *desttemp = (GstPadTemplate *)desttemps->data;
if (srctemp->direction == GST_PAD_SRC &&
desttemp->direction == GST_PAD_SINK) {
if (gst_caps_list_check_compatibility (srctemp->caps, desttemp->caps)) {
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,
"factory \"%s\" can connect with factory \"%s\"", src->name, dest->name);
return TRUE;
}
}
desttemps = g_list_next (desttemps);
}
srctemps = g_list_next (srctemps);
}
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,
"factory \"%s\" cannot connect with factory \"%s\"", src->name, dest->name);
return FALSE;
}
static gboolean
gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink)
{
GList *sinkpads;
gboolean connected = FALSE;
GST_DEBUG (0,"gstpipeline: autoplug pad connect function for \"%s\" to \"%s\"\n",
GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink));
sinkpads = gst_element_get_pad_list(sink);
while (sinkpads) {
GstPad *sinkpad = (GstPad *)sinkpads->data;
// if we have a match, connect the pads
if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
!GST_PAD_CONNECTED(sinkpad))
{
if (gst_caps_list_check_compatibility (gst_pad_get_caps_list(pad), gst_pad_get_caps_list(sinkpad))) {
gst_pad_connect(pad, sinkpad);
GST_DEBUG (0,"gstpipeline: autoconnect pad \"%s\" in element %s <-> ", GST_PAD_NAME (pad),
GST_ELEMENT_NAME(src));
GST_DEBUG (0,"pad \"%s\" in element %s\n", GST_PAD_NAME (sinkpad),
GST_ELEMENT_NAME(sink));
connected = TRUE;
break;
}
else {
GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad));
}
}
sinkpads = g_list_next(sinkpads);
}
if (!connected) {
GST_DEBUG (0,"gstpipeline: no path to sinks for type\n");
}
return connected;
}
typedef struct {
GstElement *result;
GList *endcap;
gint i;
} dynamic_pad_struct;
static void
autoplug_dynamic_pad (GstElement *element, GstPad *pad, gpointer data)
{
dynamic_pad_struct *info = (dynamic_pad_struct *)data;
GList *pads = gst_element_get_pad_list (element);
GST_DEBUG (0,"attempting to dynamically create a ghostpad for %s=%s\n", GST_ELEMENT_NAME (element),
GST_PAD_NAME (pad));
while (pads) {
GstPad *pad = GST_PAD (pads->data);
pads = g_list_next (pads);
if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), info->endcap)) {
gst_element_add_ghost_pad (info->result, pad, g_strdup_printf("src_%02d", info->i));
GST_DEBUG (0,"gstpipeline: new dynamic pad %s\n", GST_PAD_NAME (pad));
break;
}
}
}
static void
gst_autoplug_pads_autoplug (GstElement *src, GstElement *sink)
{
GList *srcpads;
gboolean connected = FALSE;
srcpads = gst_element_get_pad_list(src);
while (srcpads && !connected) {
GstPad *srcpad = (GstPad *)srcpads->data;
if (gst_pad_get_direction(srcpad) == GST_PAD_SRC)
connected = gst_autoplug_pads_autoplug_func (src, srcpad, sink);
srcpads = g_list_next(srcpads);
}
if (!connected) {
GST_DEBUG (0,"gstpipeline: delaying pad connections for \"%s\" to \"%s\"\n",
GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink));
gtk_signal_connect(GTK_OBJECT(src),"new_pad",
GTK_SIGNAL_FUNC(gst_autoplug_pads_autoplug_func), sink);
}
}
static GList*
gst_autoplug_elementfactory_get_list (gpointer data)
{
return gst_elementfactory_get_list ();
}
typedef struct {
GList *src;
GList *sink;
} caps_struct;
#define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink)
static guint
gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data)
{
caps_struct *caps = (caps_struct *)data;
gboolean res;
if (IS_CAPS (src) && IS_CAPS (dest)) {
res = gst_caps_list_check_compatibility ((GList *)src, (GList *)dest);
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"caps %d to caps %d %d", ((GstCaps *)src)->id, ((GstCaps *)dest)->id, res);
}
else if (IS_CAPS (src)) {
res = gst_elementfactory_can_sink_caps_list ((GstElementFactory *)dest, (GList *)src);
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to src caps %d %d", ((GstElementFactory *)dest)->name, ((GstCaps *)src)->id, res);
}
else if (IS_CAPS (dest)) {
res = gst_elementfactory_can_src_caps_list ((GstElementFactory *)src, (GList *)dest);
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to sink caps %d %d", ((GstElementFactory *)src)->name, ((GstCaps *)dest)->id, res);
}
else {
res = gst_autoplug_can_match ((GstElementFactory *)src, (GstElementFactory *)dest);
}
if (res)
return 1;
else
return GST_AUTOPLUG_MAX_COST;
}
static GstElement*
gst_static_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, va_list args)
{
caps_struct caps;
GList *capslist;
GstElement *result = NULL, *srcelement = NULL;
GList **factories;
GList *chains = NULL;
GList *endcaps = NULL;
guint numsinks = 0, i;
gboolean have_common = FALSE;
capslist = sinkcaps;
/*
* We first create a list of elements that are needed
* to convert the srcpad caps to the different sinkpad caps.
* and add the list of elementfactories to a list (chains).
*/
caps.src = srccaps;
while (capslist) {
GList *elements;
caps.sink = capslist;
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures");
elements = gst_autoplug_func (caps.src, caps.sink,
gst_autoplug_elementfactory_get_list,
gst_autoplug_caps_find_cost,
&caps);
if (elements) {
chains = g_list_append (chains, elements);
endcaps = g_list_append (endcaps, capslist);
numsinks++;
}
else {
}
capslist = va_arg (args, GList *);
}
/*
* If no list could be found the pipeline cannot be autoplugged and
* we return a NULL element
*/
if (numsinks == 0)
return NULL;
/*
* We now have a list of lists. We will turn this into an array
* of lists, this will make it much more easy to manipulate it
* in the next steps.
*/
factories = g_new0 (GList *, numsinks);
for (i = 0; chains; i++) {
GList *elements = (GList *) chains->data;
factories[i] = elements;
chains = g_list_next (chains);
}
//FIXME, free the list
result = gst_bin_new ("autoplug_bin");
/*
* We now hav a list of lists that is probably like:
*
* !
* A -> B -> C
* !
* A -> D -> E
*
* we now try to find the common elements (A) and add them to
* the bin. We remove them from both lists too.
*/
while (factories[0]) {
GstElementFactory *factory;
GstElement *element;
// fase 3: add common elements
factory = (GstElementFactory *) (factories[0]->data);
// check to other paths for matching elements (factories)
for (i=1; i<numsinks; i++) {
if (factory != (GstElementFactory *) (factories[i]->data)) {
goto differ;
}
}
GST_DEBUG (0,"common factory \"%s\"\n", factory->name);
element = gst_elementfactory_create (factory, factory->name);
gst_bin_add (GST_BIN(result), element);
if (srcelement != NULL) {
gst_autoplug_pads_autoplug (srcelement, element);
}
// this is the first element, find a good ghostpad
else {
GList *pads;
pads = gst_element_get_pad_list (element);
while (pads) {
GstPad *pad = GST_PAD (pads->data);
if (gst_caps_list_check_compatibility (srccaps, gst_pad_get_caps_list (pad))) {
gst_element_add_ghost_pad (result, pad, "sink");
break;
}
pads = g_list_next (pads);
}
}
gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (element));
srcelement = element;
// advance the pointer in all lists
for (i=0; i<numsinks; i++) {
factories[i] = g_list_next (factories[i]);
}
have_common = TRUE;
}
differ:
// loop over all the sink elements
for (i = 0; i < numsinks; i++) {
GstElement *thesrcelement = srcelement;
GstElement *thebin = GST_ELEMENT(result);
while (factories[i]) {
// fase 4: add other elements...
GstElementFactory *factory;
GstElement *element;
factory = (GstElementFactory *)(factories[i]->data);
GST_DEBUG (0,"factory \"%s\"\n", factory->name);
element = gst_elementfactory_create(factory, factory->name);
GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element));
gst_bin_add(GST_BIN(thebin), element);
gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (element));
gst_autoplug_pads_autoplug(thesrcelement, element);
// this element is now the new source element
thesrcelement = element;
factories[i] = g_list_next(factories[i]);
}
/*
* we're at the last element in the chain,
* find a suitable pad to turn into a ghostpad
*/
{
GList *endcap = (GList *)(endcaps->data);
GList *pads = gst_element_get_pad_list (thesrcelement);
gboolean have_pad = FALSE;
endcaps = g_list_next (endcaps);
GST_DEBUG (0,"attempting to create a ghostpad for %s\n", GST_ELEMENT_NAME (thesrcelement));
while (pads) {
GstPad *pad = GST_PAD (pads->data);
pads = g_list_next (pads);
if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), endcap)) {
gst_element_add_ghost_pad (result, pad, g_strdup_printf("src_%02d", i));
have_pad = TRUE;
break;
}
}
if (!have_pad) {
dynamic_pad_struct *data = g_new0(dynamic_pad_struct, 1);
data->result = result;
data->endcap = endcap;
data->i = i;
GST_DEBUG (0,"delaying the creation of a ghostpad for %s\n", GST_ELEMENT_NAME (thesrcelement));
gtk_signal_connect (GTK_OBJECT (thesrcelement), "new_pad",
autoplug_dynamic_pad, data);
gtk_signal_connect (GTK_OBJECT (thesrcelement), "new_ghost_pad",
autoplug_dynamic_pad, data);
}
}
}
return result;
}
/*
* shortest path algorithm
*
*/
struct _gst_autoplug_node
{
gpointer iNode;
gpointer iPrev;
gint iDist;
};
typedef struct _gst_autoplug_node gst_autoplug_node;
static gint
find_factory (gst_autoplug_node *rgnNodes, gpointer factory)
{
gint i=0;
while (rgnNodes[i].iNode) {
if (rgnNodes[i].iNode == factory) return i;
i++;
}
return 0;
}
static GList*
construct_path (gst_autoplug_node *rgnNodes, gpointer factory)
{
GstElementFactory *current;
GList *factories = NULL;
current = rgnNodes[find_factory(rgnNodes, factory)].iPrev;
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factories found in autoplugging (reversed order)");
while (current != NULL)
{
gpointer next = NULL;
next = rgnNodes[find_factory(rgnNodes, current)].iPrev;
if (next) {
factories = g_list_prepend (factories, current);
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory: \"%s\"", current->name);
}
current = next;
}
return factories;
}
static GList*
gst_autoplug_enqueue (GList *queue, gpointer iNode, gint iDist, gpointer iPrev)
{
gst_autoplug_node *node = g_malloc (sizeof (gst_autoplug_node));
node->iNode = iNode;
node->iDist = iDist;
node->iPrev = iPrev;
queue = g_list_append (queue, node);
return queue;
}
static GList*
gst_autoplug_dequeue (GList *queue, gpointer *iNode, gint *iDist, gpointer *iPrev)
{
GList *head;
gst_autoplug_node *node;
head = g_list_first (queue);
if (head) {
node = (gst_autoplug_node *)head->data;
*iNode = node->iNode;
*iPrev = node->iPrev;
*iDist = node->iDist;
head = g_list_remove (queue, node);
}
return head;
}
static GList*
gst_autoplug_func (gpointer src, gpointer sink,
GstAutoplugListFunction list_function,
GstAutoplugCostFunction cost_function,
gpointer data)
{
gst_autoplug_node *rgnNodes;
GList *queue = NULL;
gpointer iNode, iPrev;
gint iDist, i, iCost;
GList *elements = g_list_copy (list_function(data));
GList *factories;
guint num_factories;
elements = g_list_append (elements, sink);
elements = g_list_append (elements, src);
factories = elements;
num_factories = g_list_length (factories);
rgnNodes = g_new0 (gst_autoplug_node, num_factories+1);
for (i=0; i< num_factories; i++) {
gpointer fact = factories->data;
rgnNodes[i].iNode = fact;
rgnNodes[i].iPrev = NULL;
if (fact == src) {
rgnNodes[i].iDist = 0;
}
else {
rgnNodes[i].iDist = GST_AUTOPLUG_MAX_COST;
}
factories = g_list_next (factories);
}
rgnNodes[num_factories].iNode = NULL;
queue = gst_autoplug_enqueue (queue, src, 0, NULL);
while (g_list_length (queue) > 0) {
GList *factories2 = elements;
queue = gst_autoplug_dequeue (queue, &iNode, &iDist, &iPrev);
for (i=0; i< num_factories; i++) {
gpointer current = factories2->data;
iCost = cost_function (iNode, current, data);
if (iCost != GST_AUTOPLUG_MAX_COST) {
if ((GST_AUTOPLUG_MAX_COST == rgnNodes[i].iDist) ||
(rgnNodes[i].iDist > (iCost + iDist))) {
rgnNodes[i].iDist = iDist + iCost;
rgnNodes[i].iPrev = iNode;
queue = gst_autoplug_enqueue (queue, current, iDist + iCost, iNode);
}
}
factories2 = g_list_next (factories2);
}
}
return construct_path (rgnNodes, sink);
}

View file

@ -0,0 +1,64 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstautoplug.h: Header for autoplugging functionality
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_STATIC_AUTOPLUG_H__
#define __GST_STATIC_AUTOPLUG_H__
#include <gst/gstautoplug.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_STATIC_AUTOPLUG \
(gst_static_autoplug_get_type())
#define GST_STATIC_AUTOPLUG(obj) \
(GTK_CHECK_CAST((obj),GST_TYPE_STATIC_AUTOPLUG,GstStaticAutoplug))
#define GST_STATIC_AUTOPLUG_CLASS(klass) \
(GTK_CHECK_CLASS_CAST((klass),GST_TYPE_STATIC_AUTOPLUG,GstStaticAutoplugClass))
#define GST_IS_STATIC_AUTOPLUG(obj) \
(GTK_CHECK_TYPE((obj),GST_TYPE_STATIC_AUTOPLUG))
#define GST_IS_STATIC_AUTOPLUG_CLASS(obj) \
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_STATIC_AUTOPLUG))
typedef struct _GstStaticAutoplug GstStaticAutoplug;
typedef struct _GstStaticAutoplugClass GstStaticAutoplugClass;
struct _GstStaticAutoplug {
GstAutoplug object;
};
struct _GstStaticAutoplugClass {
GstAutoplugClass parent_class;
};
GtkType gst_static_autoplug_get_type (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_STATIC_AUTOPLUG_H__ */

View file

@ -0,0 +1,650 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gststaticautoplug.c: A static Autoplugger of pipelines
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gststaticautoplugrender.h"
#include <gst/gst.h>
#define GST_AUTOPLUG_MAX_COST 999999
typedef guint (*GstAutoplugCostFunction) (gpointer src, gpointer dest, gpointer data);
typedef GList* (*GstAutoplugListFunction) (gpointer data);
static void gst_static_autoplug_render_class_init (GstStaticAutoplugRenderClass *klass);
static void gst_static_autoplug_render_init (GstStaticAutoplugRender *autoplug);
static GList* gst_autoplug_func (gpointer src, gpointer sink,
GstAutoplugListFunction list_function,
GstAutoplugCostFunction cost_function,
gpointer data);
static GstElement* gst_static_autoplug_to_render (GstAutoplug *autoplug,
GList *srccaps, GstElement *target, va_list args);
static GstAutoplugClass *parent_class = NULL;
GtkType gst_static_autoplug_render_get_type(void)
{
static GtkType static_autoplug_type = 0;
if (!static_autoplug_type) {
static const GtkTypeInfo static_autoplug_info = {
"GstStaticAutoplugRender",
sizeof(GstElement),
sizeof(GstElementClass),
(GtkClassInitFunc)gst_static_autoplug_render_class_init,
(GtkObjectInitFunc)gst_static_autoplug_render_init,
(GtkArgSetFunc)NULL,
(GtkArgGetFunc)NULL,
(GtkClassInitFunc)NULL,
};
static_autoplug_type = gtk_type_unique (GST_TYPE_AUTOPLUG, &static_autoplug_info);
}
return static_autoplug_type;
}
static void
gst_static_autoplug_render_class_init(GstStaticAutoplugRenderClass *klass)
{
GstAutoplugClass *gstautoplug_class;
gstautoplug_class = (GstAutoplugClass*) klass;
parent_class = gtk_type_class(GST_TYPE_AUTOPLUG);
gstautoplug_class->autoplug_to_renderers = gst_static_autoplug_to_render;
}
static void gst_static_autoplug_render_init(GstStaticAutoplugRender *autoplug) {
}
GstPlugin*
plugin_init (GModule *module)
{
GstPlugin *plugin;
GstAutoplugFactory *factory;
plugin = gst_plugin_new("gststaticautoplugrender");
g_return_val_if_fail(plugin != NULL,NULL);
gst_plugin_set_longname (plugin, "A static autoplugger");
factory = gst_autoplugfactory_new ("staticrender",
"A static autoplugger, it constructs the complete element before running it",
gst_static_autoplug_render_get_type ());
if (factory != NULL) {
gst_plugin_add_autoplugger (plugin, factory);
}
return plugin;
}
static gboolean
gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest)
{
GList *srctemps, *desttemps;
srctemps = src->padtemplates;
while (srctemps) {
GstPadTemplate *srctemp = (GstPadTemplate *)srctemps->data;
desttemps = dest->padtemplates;
while (desttemps) {
GstPadTemplate *desttemp = (GstPadTemplate *)desttemps->data;
if (srctemp->direction == GST_PAD_SRC &&
desttemp->direction == GST_PAD_SINK) {
if (gst_caps_list_check_compatibility (srctemp->caps, desttemp->caps)) {
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,
"factory \"%s\" can connect with factory \"%s\"", src->name, dest->name);
return TRUE;
}
}
desttemps = g_list_next (desttemps);
}
srctemps = g_list_next (srctemps);
}
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,
"factory \"%s\" cannot connect with factory \"%s\"", src->name, dest->name);
return FALSE;
}
static gboolean
gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink)
{
GList *sinkpads;
gboolean connected = FALSE;
GST_DEBUG (0,"gstpipeline: autoplug pad connect function for \"%s\" to \"%s\"\n",
GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink));
sinkpads = gst_element_get_pad_list(sink);
while (sinkpads) {
GstPad *sinkpad = (GstPad *)sinkpads->data;
// if we have a match, connect the pads
if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
!GST_PAD_CONNECTED(sinkpad))
{
if (gst_caps_list_check_compatibility (gst_pad_get_caps_list(pad), gst_pad_get_caps_list(sinkpad))) {
gst_pad_connect(pad, sinkpad);
GST_DEBUG (0,"gstpipeline: autoconnect pad \"%s\" in element %s <-> ", GST_PAD_NAME (pad),
GST_ELEMENT_NAME(src));
GST_DEBUG (0,"pad \"%s\" in element %s\n", GST_PAD_NAME (sinkpad),
GST_ELEMENT_NAME(sink));
connected = TRUE;
break;
}
else {
GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad));
}
}
sinkpads = g_list_next(sinkpads);
}
if (!connected) {
GST_DEBUG (0,"gstpipeline: no path to sinks for type\n");
}
return connected;
}
typedef struct {
GstElement *result;
GList *endcap;
gint i;
} dynamic_pad_struct;
static void
autoplug_dynamic_pad (GstElement *element, GstPad *pad, gpointer data)
{
dynamic_pad_struct *info = (dynamic_pad_struct *)data;
GList *pads = gst_element_get_pad_list (element);
GST_DEBUG (0,"attempting to dynamically create a ghostpad for %s=%s\n", GST_ELEMENT_NAME (element),
GST_PAD_NAME (pad));
while (pads) {
GstPad *pad = GST_PAD (pads->data);
pads = g_list_next (pads);
if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), info->endcap)) {
gst_element_add_ghost_pad (info->result, pad, g_strdup_printf("src_%02d", info->i));
GST_DEBUG (0,"gstpipeline: new dynamic pad %s\n", GST_PAD_NAME (pad));
break;
}
}
}
static void
gst_autoplug_pads_autoplug (GstElement *src, GstElement *sink)
{
GList *srcpads;
gboolean connected = FALSE;
srcpads = gst_element_get_pad_list(src);
while (srcpads && !connected) {
GstPad *srcpad = (GstPad *)srcpads->data;
if (gst_pad_get_direction(srcpad) == GST_PAD_SRC)
connected = gst_autoplug_pads_autoplug_func (src, srcpad, sink);
srcpads = g_list_next(srcpads);
}
if (!connected) {
GST_DEBUG (0,"gstpipeline: delaying pad connections for \"%s\" to \"%s\"\n",
GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink));
gtk_signal_connect(GTK_OBJECT(src),"new_pad",
GTK_SIGNAL_FUNC(gst_autoplug_pads_autoplug_func), sink);
gtk_signal_connect(GTK_OBJECT(src),"new_ghost_pad",
GTK_SIGNAL_FUNC(gst_autoplug_pads_autoplug_func), sink);
}
}
static GList*
gst_autoplug_elementfactory_get_list (gpointer data)
{
return gst_elementfactory_get_list ();
}
typedef struct {
GList *src;
GList *sink;
} caps_struct;
#define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink)
static guint
gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data)
{
caps_struct *caps = (caps_struct *)data;
gboolean res;
if (IS_CAPS (src) && IS_CAPS (dest)) {
res = gst_caps_list_check_compatibility ((GList *)src, (GList *)dest);
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"caps %d to caps %d %d", ((GstCaps *)src)->id, ((GstCaps *)dest)->id, res);
}
else if (IS_CAPS (src)) {
res = gst_elementfactory_can_sink_caps_list ((GstElementFactory *)dest, (GList *)src);
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to src caps %d %d", ((GstElementFactory *)dest)->name, ((GstCaps *)src)->id, res);
}
else if (IS_CAPS (dest)) {
res = gst_elementfactory_can_src_caps_list ((GstElementFactory *)src, (GList *)dest);
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to sink caps %d %d", ((GstElementFactory *)src)->name, ((GstCaps *)dest)->id, res);
}
else {
res = gst_autoplug_can_match ((GstElementFactory *)src, (GstElementFactory *)dest);
}
if (res)
return 1;
else
return GST_AUTOPLUG_MAX_COST;
}
static GstElement*
gst_static_autoplug_to_render (GstAutoplug *autoplug, GList *srccaps, GstElement *target, va_list args)
{
caps_struct caps;
GstElement *targetelement;
GstElement *result = NULL, *srcelement = NULL;
GList **factories;
GList *chains = NULL;
GList *endelements = NULL;
guint numsinks = 0, i;
gboolean have_common = FALSE;
targetelement = target;
/*
* We first create a list of elements that are needed
* to convert the srcpad caps to the different sinkpad caps.
* and add the list of elementfactories to a list (chains).
*/
caps.src = srccaps;
while (targetelement) {
GList *elements;
GstPad *pad;
pad = GST_PAD (gst_element_get_pad_list (targetelement)->data);
caps.sink = gst_pad_get_caps_list (pad);
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures");
elements = gst_autoplug_func (caps.src, caps.sink,
gst_autoplug_elementfactory_get_list,
gst_autoplug_caps_find_cost,
&caps);
if (elements) {
chains = g_list_append (chains, elements);
endelements = g_list_append (endelements, targetelement);
numsinks++;
}
else {
}
targetelement = va_arg (args, GstElement *);
}
/*
* If no list could be found the pipeline cannot be autoplugged and
* we return a NULL element
*/
if (numsinks == 0)
return NULL;
/*
* We now have a list of lists. We will turn this into an array
* of lists, this will make it much more easy to manipulate it
* in the next steps.
*/
factories = g_new0 (GList *, numsinks);
for (i = 0; chains; i++) {
GList *elements = (GList *) chains->data;
factories[i] = elements;
chains = g_list_next (chains);
}
//FIXME, free the list
result = gst_bin_new ("autoplug_bin");
/*
* We now hav a list of lists that is probably like:
*
* !
* A -> B -> C
* !
* A -> D -> E
*
* we now try to find the common elements (A) and add them to
* the bin. We remove them from both lists too.
*/
while (factories[0]) {
GstElementFactory *factory;
GstElement *element;
// fase 3: add common elements
factory = (GstElementFactory *) (factories[0]->data);
// check to other paths for matching elements (factories)
for (i=1; i<numsinks; i++) {
if (factory != (GstElementFactory *) (factories[i]->data)) {
goto differ;
}
}
GST_DEBUG (0,"common factory \"%s\"\n", factory->name);
element = gst_elementfactory_create (factory, factory->name);
gst_bin_add (GST_BIN(result), element);
if (srcelement != NULL) {
gst_autoplug_pads_autoplug (srcelement, element);
}
// this is the first element, find a good ghostpad
else {
GList *pads;
pads = gst_element_get_pad_list (element);
while (pads) {
GstPad *pad = GST_PAD (pads->data);
if (gst_caps_list_check_compatibility (srccaps, gst_pad_get_caps_list (pad))) {
gst_element_add_ghost_pad (result, pad, "sink");
break;
}
pads = g_list_next (pads);
}
}
gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (element));
srcelement = element;
// advance the pointer in all lists
for (i=0; i<numsinks; i++) {
factories[i] = g_list_next (factories[i]);
}
have_common = TRUE;
}
differ:
// loop over all the sink elements
for (i = 0; i < numsinks; i++) {
GstElement *thesrcelement = srcelement;
GstElement *thebin = GST_ELEMENT(result);
GstElement *sinkelement;
gboolean use_thread;
sinkelement = GST_ELEMENT (endelements->data);
endelements = g_list_next (endelements);
use_thread = have_common;
while (factories[i] || sinkelement) {
// fase 4: add other elements...
GstElementFactory *factory;
GstElement *element;
if (factories[i]) {
factory = (GstElementFactory *)(factories[i]->data);
GST_DEBUG (0,"factory \"%s\"\n", factory->name);
element = gst_elementfactory_create(factory, factory->name);
}
else {
element = sinkelement;
sinkelement = NULL;
}
// this element suggests the use of a thread, so we set one up...
if (GST_ELEMENT_IS_THREAD_SUGGESTED(element) || use_thread) {
GstElement *queue;
GList *sinkpads;
GstPad *srcpad, *sinkpad;
use_thread = FALSE;
GST_DEBUG (0,"sugest new thread for \"%s\" %08x\n", GST_ELEMENT_NAME (element), GST_FLAGS(element));
// create a new queue and add to the previous bin
queue = gst_elementfactory_make("queue", g_strconcat("queue_", GST_ELEMENT_NAME(element), NULL));
GST_DEBUG (0,"adding element \"%s\"\n", GST_ELEMENT_NAME (element));
gst_bin_add(GST_BIN(thebin), queue);
gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (queue));
// this will be the new bin for all following elements
thebin = gst_elementfactory_make("thread", g_strconcat("thread_", GST_ELEMENT_NAME(element), NULL));
srcpad = gst_element_get_pad(queue, "src");
sinkpads = gst_element_get_pad_list(element);
while (sinkpads) {
sinkpad = (GstPad *)sinkpads->data;
// FIXME connect matching pads, not just the first one...
if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
!GST_PAD_CONNECTED(sinkpad)) {
GList *caps = gst_pad_get_caps_list (sinkpad);
// the queue has the type of the elements it connects
gst_pad_set_caps_list (srcpad, caps);
gst_pad_set_caps_list (gst_element_get_pad(queue, "sink"), caps);
break;
}
sinkpads = g_list_next(sinkpads);
}
gst_autoplug_pads_autoplug(thesrcelement, queue);
GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element));
gst_bin_add(GST_BIN(thebin), element);
gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (element));
GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (thebin));
gst_bin_add(GST_BIN(result), thebin);
gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (thebin));
thesrcelement = queue;
}
// no thread needed, easy case
else {
GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element));
gst_bin_add(GST_BIN(thebin), element);
gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (element));
}
gst_autoplug_pads_autoplug(thesrcelement, element);
// this element is now the new source element
thesrcelement = element;
factories[i] = g_list_next(factories[i]);
}
}
return result;
}
/*
* shortest path algorithm
*
*/
struct _gst_autoplug_node
{
gpointer iNode;
gpointer iPrev;
gint iDist;
};
typedef struct _gst_autoplug_node gst_autoplug_node;
static gint
find_factory (gst_autoplug_node *rgnNodes, gpointer factory)
{
gint i=0;
while (rgnNodes[i].iNode) {
if (rgnNodes[i].iNode == factory) return i;
i++;
}
return 0;
}
static GList*
construct_path (gst_autoplug_node *rgnNodes, gpointer factory)
{
GstElementFactory *current;
GList *factories = NULL;
current = rgnNodes[find_factory(rgnNodes, factory)].iPrev;
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factories found in autoplugging (reversed order)");
while (current != NULL)
{
gpointer next = NULL;
next = rgnNodes[find_factory(rgnNodes, current)].iPrev;
if (next) {
factories = g_list_prepend (factories, current);
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory: \"%s\"", current->name);
}
current = next;
}
return factories;
}
static GList*
gst_autoplug_enqueue (GList *queue, gpointer iNode, gint iDist, gpointer iPrev)
{
gst_autoplug_node *node = g_malloc (sizeof (gst_autoplug_node));
node->iNode = iNode;
node->iDist = iDist;
node->iPrev = iPrev;
queue = g_list_append (queue, node);
return queue;
}
static GList*
gst_autoplug_dequeue (GList *queue, gpointer *iNode, gint *iDist, gpointer *iPrev)
{
GList *head;
gst_autoplug_node *node;
head = g_list_first (queue);
if (head) {
node = (gst_autoplug_node *)head->data;
*iNode = node->iNode;
*iPrev = node->iPrev;
*iDist = node->iDist;
head = g_list_remove (queue, node);
}
return head;
}
static GList*
gst_autoplug_func (gpointer src, gpointer sink,
GstAutoplugListFunction list_function,
GstAutoplugCostFunction cost_function,
gpointer data)
{
gst_autoplug_node *rgnNodes;
GList *queue = NULL;
gpointer iNode, iPrev;
gint iDist, i, iCost;
GList *elements = g_list_copy (list_function(data));
GList *factories;
guint num_factories;
elements = g_list_append (elements, sink);
elements = g_list_append (elements, src);
factories = elements;
num_factories = g_list_length (factories);
rgnNodes = g_new0 (gst_autoplug_node, num_factories+1);
for (i=0; i< num_factories; i++) {
gpointer fact = factories->data;
rgnNodes[i].iNode = fact;
rgnNodes[i].iPrev = NULL;
if (fact == src) {
rgnNodes[i].iDist = 0;
}
else {
rgnNodes[i].iDist = GST_AUTOPLUG_MAX_COST;
}
factories = g_list_next (factories);
}
rgnNodes[num_factories].iNode = NULL;
queue = gst_autoplug_enqueue (queue, src, 0, NULL);
while (g_list_length (queue) > 0) {
GList *factories2 = elements;
queue = gst_autoplug_dequeue (queue, &iNode, &iDist, &iPrev);
for (i=0; i< num_factories; i++) {
gpointer current = factories2->data;
iCost = cost_function (iNode, current, data);
if (iCost != GST_AUTOPLUG_MAX_COST) {
if ((GST_AUTOPLUG_MAX_COST == rgnNodes[i].iDist) ||
(rgnNodes[i].iDist > (iCost + iDist))) {
rgnNodes[i].iDist = iDist + iCost;
rgnNodes[i].iPrev = iNode;
queue = gst_autoplug_enqueue (queue, current, iDist + iCost, iNode);
}
}
factories2 = g_list_next (factories2);
}
}
return construct_path (rgnNodes, sink);
}

View file

@ -0,0 +1,64 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstautoplug.h: Header for autoplugging functionality
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_STATIC_AUTOPLUG_RENDER_H__
#define __GST_STATIC_AUTOPLUG_RENDER_H__
#include <gst/gstautoplug.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_STATIC_AUTOPLUG_RENDER \
(gst_static_autoplug_render_get_type())
#define GST_STATIC_AUTOPLUG_RENDER(obj) \
(GTK_CHECK_CAST((obj),GST_TYPE_STATIC_AUTOPLUG_RENDER,GstStaticAutoplugRender))
#define GST_STATIC_AUTOPLUG_RENDER_CLASS(klass) \
(GTK_CHECK_CLASS_CAST((klass),GST_TYPE_STATIC_AUTOPLUG_RENDER,GstStaticAutoplugRenderClass))
#define GST_IS_STATIC_AUTOPLUG_RENDER(obj) \
(GTK_CHECK_TYPE((obj),GST_TYPE_STATIC_AUTOPLUG_RENDER))
#define GST_IS_STATIC_AUTOPLUG_RENDER_CLASS(obj) \
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_STATIC_AUTOPLUG_RENDER))
typedef struct _GstStaticAutoplugRender GstStaticAutoplugRender;
typedef struct _GstStaticAutoplugRenderClass GstStaticAutoplugRenderClass;
struct _GstStaticAutoplugRender {
GstAutoplug object;
};
struct _GstStaticAutoplugRenderClass {
GstAutoplugClass parent_class;
};
GtkType gst_static_autoplug_render_get_type (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_STATIC_AUTOPLUG_H__ */

View file

@ -2,7 +2,7 @@
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstdisksrc.c:
* gstdisksrc.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -56,23 +56,23 @@ enum {
};
static void gst_disksrc_class_init (GstDiskSrcClass *klass);
static void gst_disksrc_init (GstDiskSrc *disksrc);
static void gst_disksrc_class_init (GstDiskSrcClass *klass);
static void gst_disksrc_init (GstDiskSrc *disksrc);
static void gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id);
static void gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id);
static void gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id);
static void gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id);
static GstBuffer * gst_disksrc_get (GstPad *pad);
static GstBuffer * gst_disksrc_get_region (GstPad *pad,GstRegionType type,guint64 offset,guint64 len);
static GstElementStateReturn gst_disksrc_change_state (GstElement *element);
static GstElementStateReturn gst_disksrc_change_state (GstElement *element);
static GstElementClass *parent_class = NULL;
//static guint gst_disksrc_signals[LAST_SIGNAL] = { 0 };
GtkType
gst_disksrc_get_type(void)
gst_disksrc_get_type(void)
{
static GtkType disksrc_type = 0;
@ -93,7 +93,7 @@ gst_disksrc_get_type(void)
}
static void
gst_disksrc_class_init (GstDiskSrcClass *klass)
gst_disksrc_class_init (GstDiskSrcClass *klass)
{
GtkObjectClass *gtkobject_class;
GstElementClass *gstelement_class;
@ -118,8 +118,8 @@ gst_disksrc_class_init (GstDiskSrcClass *klass)
gstelement_class->change_state = gst_disksrc_change_state;
}
static void
gst_disksrc_init (GstDiskSrc *disksrc)
static void
gst_disksrc_init (GstDiskSrc *disksrc)
{
// GST_FLAG_SET (disksrc, GST_SRC_);
@ -139,14 +139,14 @@ gst_disksrc_init (GstDiskSrc *disksrc)
}
static void
gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id)
static void
gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id)
{
GstDiskSrc *src;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_DISKSRC (object));
src = GST_DISKSRC (object);
switch(id) {
@ -176,14 +176,14 @@ gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id)
}
}
static void
gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id)
static void
gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id)
{
GstDiskSrc *src;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_DISKSRC (object));
src = GST_DISKSRC (object);
switch (id) {
@ -212,7 +212,7 @@ gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id)
* Push a new buffer from the disksrc at the current offset.
*/
static GstBuffer *
gst_disksrc_get (GstPad *pad)
gst_disksrc_get (GstPad *pad)
{
GstDiskSrc *src;
GstBuffer *buf;
@ -223,7 +223,7 @@ gst_disksrc_get (GstPad *pad)
/* deal with EOF state */
if (src->curoffset >= src->size) {
gst_element_signal_eos (GST_ELEMENT (src));
gst_pad_set_eos (pad);
return NULL;
}
@ -269,7 +269,7 @@ gst_disksrc_get (GstPad *pad)
* Push a new buffer from the disksrc of given size at given offset.
*/
static GstBuffer *
gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len)
gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len)
{
GstDiskSrc *src;
GstBuffer *buf;
@ -281,10 +281,10 @@ gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 l
g_return_val_if_fail (GST_IS_DISKSRC (src), NULL);
g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN), NULL);
/* deal with EOF state */
if (offset >= src->size) {
gst_element_signal_eos (GST_ELEMENT (src));
gst_pad_set_eos (pad);
return NULL;
}
@ -312,8 +312,8 @@ gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 l
/* open the file and mmap it, necessary to go to READY state */
static
gboolean gst_disksrc_open_file (GstDiskSrc *src)
static
gboolean gst_disksrc_open_file (GstDiskSrc *src)
{
g_return_val_if_fail (!GST_FLAG_IS_SET (src ,GST_DISKSRC_OPEN), FALSE);
@ -343,8 +343,8 @@ gboolean gst_disksrc_open_file (GstDiskSrc *src)
}
/* unmap and close the file */
static void
gst_disksrc_close_file (GstDiskSrc *src)
static void
gst_disksrc_close_file (GstDiskSrc *src)
{
g_return_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN));
@ -365,8 +365,8 @@ gst_disksrc_close_file (GstDiskSrc *src)
}
static GstElementStateReturn
gst_disksrc_change_state (GstElement *element)
static GstElementStateReturn
gst_disksrc_change_state (GstElement *element)
{
g_return_val_if_fail (GST_IS_DISKSRC (element), GST_STATE_FAILURE);
@ -375,7 +375,7 @@ gst_disksrc_change_state (GstElement *element)
gst_disksrc_close_file (GST_DISKSRC (element));
} else {
if (!GST_FLAG_IS_SET (element, GST_DISKSRC_OPEN)) {
if (!gst_disksrc_open_file (GST_DISKSRC (element)))
if (!gst_disksrc_open_file (GST_DISKSRC (element)))
return GST_STATE_FAILURE;
}
}

View file

@ -2,7 +2,7 @@
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstelements.c:
* gstelements.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -61,13 +61,13 @@ static struct _elements_entry _elements[] = {
{ "tee", gst_tee_get_type, &gst_tee_details, gst_tee_factory_init },
#if HAVE_LIBGHTTP
{ "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details, NULL },
{ "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details, NULL },
#endif /* HAVE_LIBGHTTP */
{ NULL, 0 },
};
GstPlugin *plugin_init (GModule *module)
GstPlugin *plugin_init (GModule *module)
{
GstPlugin *plugin;
GstElementFactory *factory;

View file

@ -24,337 +24,268 @@
#include "gst_private.h"
#include "gstautoplug.h"
#include "gstplugin.h"
GList* _gst_autoplugfactories;
enum {
NEW_OBJECT,
LAST_SIGNAL
};
enum {
ARG_0,
/* FILL ME */
};
static void gst_autoplug_class_init (GstAutoplugClass *klass);
static void gst_autoplug_init (GstAutoplug *autoplug);
static GList* gst_autoplug_func (gpointer src, gpointer sink,
GstAutoplugListFunction list_function,
GstAutoplugCostFunction cost_function,
gpointer data);
struct _gst_autoplug_node
{
gpointer iNode;
gpointer iPrev;
gint iDist;
};
typedef struct _gst_autoplug_node gst_autoplug_node;
static GstObjectClass *parent_class = NULL;
static guint gst_autoplug_signals[LAST_SIGNAL] = { 0 };
GtkType gst_autoplug_get_type(void) {
GtkType gst_autoplug_get_type(void)
{
static GtkType autoplug_type = 0;
if (!autoplug_type) {
static const GtkTypeInfo autoplug_info = {
"GstAutoplug",
sizeof(GstElement),
sizeof(GstElementClass),
sizeof(GstAutoplug),
sizeof(GstAutoplugClass),
(GtkClassInitFunc)gst_autoplug_class_init,
(GtkObjectInitFunc)gst_autoplug_init,
(GtkArgSetFunc)NULL,
(GtkArgGetFunc)NULL,
(GtkClassInitFunc)NULL,
};
autoplug_type = gtk_type_unique(GST_TYPE_AUTOPLUG,&autoplug_info);
autoplug_type = gtk_type_unique (GST_TYPE_OBJECT, &autoplug_info);
}
return autoplug_type;
}
static void
gst_autoplug_class_init(GstAutoplugClass *klass) {
gst_autoplug_class_init(GstAutoplugClass *klass)
{
GtkObjectClass *gtkobject_class;
GstObjectClass *gstobject_class;
gtkobject_class = (GtkObjectClass*) klass;
gstobject_class = (GstObjectClass*) klass;
parent_class = gtk_type_class(GST_TYPE_OBJECT);
gst_autoplug_signals[NEW_OBJECT] =
gtk_signal_new ("new_object", GTK_RUN_LAST, gtkobject_class->type,
GTK_SIGNAL_OFFSET (GstAutoplugClass, new_object),
gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1,
GST_TYPE_OBJECT);
gtk_object_class_add_signals (gtkobject_class, gst_autoplug_signals, LAST_SIGNAL);
}
static void gst_autoplug_init(GstAutoplug *autoplug) {
}
static gboolean
gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest)
static void gst_autoplug_init(GstAutoplug *autoplug)
{
GList *srctemps, *desttemps;
srctemps = src->padtemplates;
while (srctemps) {
GstPadTemplate *srctemp = (GstPadTemplate *)srctemps->data;
desttemps = dest->padtemplates;
while (desttemps) {
GstPadTemplate *desttemp = (GstPadTemplate *)desttemps->data;
if (srctemp->direction == GST_PAD_SRC &&
desttemp->direction == GST_PAD_SINK) {
if (gst_caps_list_check_compatibility (srctemp->caps, desttemp->caps)) {
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory \"%s\" can connect with factory \"%s\"", src->name, dest->name);
return TRUE;
}
}
desttemps = g_list_next (desttemps);
}
srctemps = g_list_next (srctemps);
}
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory \"%s\" cannot connect with factory \"%s\"", src->name, dest->name);
return FALSE;
}
static GList*
gst_autoplug_elementfactory_get_list (gpointer data)
void
_gst_autoplug_initialize (void)
{
return gst_elementfactory_get_list ();
_gst_autoplugfactories = NULL;
}
typedef struct {
GList *src;
GList *sink;
} caps_struct;
#define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink)
static guint
gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data)
void
gst_autoplug_signal_new_object (GstAutoplug *autoplug, GstObject *object)
{
caps_struct *caps = (caps_struct *)data;
gboolean res;
gtk_signal_emit (GTK_OBJECT (autoplug), gst_autoplug_signals[NEW_OBJECT], object);
}
if (IS_CAPS (src) && IS_CAPS (dest)) {
res = gst_caps_list_check_compatibility ((GList *)src, (GList *)dest);
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"caps %d to caps %d %d", ((GstCaps *)src)->id, ((GstCaps *)dest)->id, res);
}
else if (IS_CAPS (src)) {
res = gst_elementfactory_can_sink_caps_list ((GstElementFactory *)dest, (GList *)src);
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to src caps %d %d", ((GstElementFactory *)dest)->name, ((GstCaps *)src)->id, res);
}
else if (IS_CAPS (dest)) {
res = gst_elementfactory_can_src_caps_list ((GstElementFactory *)src, (GList *)dest);
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to sink caps %d %d", ((GstElementFactory *)src)->name, ((GstCaps *)dest)->id, res);
}
else {
res = gst_autoplug_can_match ((GstElementFactory *)src, (GstElementFactory *)dest);
}
if (res)
return 1;
else
return GST_AUTOPLUG_MAX_COST;
GstElement*
gst_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, ...)
{
GstAutoplugClass *oclass;
GstElement *element = NULL;
va_list args;
va_start (args, sinkcaps);
oclass = GST_AUTOPLUG_CLASS (GTK_OBJECT (autoplug)->klass);
if (oclass->autoplug_to_caps)
element = (oclass->autoplug_to_caps) (autoplug, srccaps, sinkcaps, args);
va_end (args);
return element;
}
GstElement*
gst_autoplug_to_renderers (GstAutoplug *autoplug, GList *srccaps, GstElement *target, ...)
{
GstAutoplugClass *oclass;
GstElement *element = NULL;
va_list args;
va_start (args, target);
oclass = GST_AUTOPLUG_CLASS (GTK_OBJECT (autoplug)->klass);
if (oclass->autoplug_to_renderers)
element = (oclass->autoplug_to_renderers) (autoplug, srccaps, target, args);
va_end (args);
return element;
}
/**
* gst_autoplugfactory_new:
* @name: name of autoplugfactory to create
* @longdesc: long description of autoplugfactory to create
* @type: the gtk type of the GstAutoplug element of this factory
*
* Create a new autoplugfactory with the given parameters
*
* Returns: a new #GstAutoplugFactory.
*/
GstAutoplugFactory*
gst_autoplugfactory_new (const gchar *name, const gchar *longdesc, GtkType type)
{
GstAutoplugFactory *factory;
g_return_val_if_fail(name != NULL, NULL);
factory = g_new0(GstAutoplugFactory, 1);
factory->name = g_strdup(name);
factory->longdesc = g_strdup (longdesc);
factory->type = type;
_gst_autoplugfactories = g_list_prepend (_gst_autoplugfactories, factory);
return factory;
}
/**
* gst_autoplug_caps:
* @srccaps: the source caps
* @sinkcaps: the sink caps
* gst_autoplugfactory_destroy:
* @autoplug: factory to destroy
*
* Perform autoplugging between the two given caps.
*
* Returns: a list of elementfactories that can connect
* the two caps
* Removes the autoplug from the global list.
*/
GList*
gst_autoplug_caps (GstCaps *srccaps, GstCaps *sinkcaps)
void
gst_autoplugfactory_destroy (GstAutoplugFactory *autoplug)
{
caps_struct caps;
g_return_if_fail (autoplug != NULL);
caps.src = g_list_prepend (NULL,srccaps);
caps.sink = g_list_prepend (NULL,sinkcaps);
_gst_autoplugfactories = g_list_remove (_gst_autoplugfactories, autoplug);
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures");
return gst_autoplug_func (caps.src, caps.sink,
gst_autoplug_elementfactory_get_list,
gst_autoplug_caps_find_cost,
&caps);
// we don't free the struct bacause someone might have a handle to it..
}
/**
* gst_autoplug_caps_list:
* @srccaps: the source caps list
* @sinkcaps: the sink caps list
* gst_autoplug_find:
* @name: name of autoplugger to find
*
* Perform autoplugging between the two given caps lists.
* Search for an autoplugger of the given name.
*
* Returns: a list of elementfactories that can connect
* the two caps lists
* Returns: #GstAutoplug if found, NULL otherwise
*/
GList*
gst_autoplug_caps_list (GList *srccaps, GList *sinkcaps)
GstAutoplugFactory*
gst_autoplugfactory_find (const gchar *name)
{
caps_struct caps;
GList *walk;
GstAutoplugFactory *factory;
caps.src = srccaps;
caps.sink = sinkcaps;
g_return_val_if_fail(name != NULL, NULL);
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps list structures");
GST_DEBUG (0,"gstautoplug: find \"%s\"\n", name);
return gst_autoplug_func (caps.src, caps.sink,
gst_autoplug_elementfactory_get_list,
gst_autoplug_caps_find_cost,
&caps);
walk = _gst_autoplugfactories;
while (walk) {
factory = (GstAutoplugFactory *)(walk->data);
if (!strcmp (name, factory->name))
return factory;
walk = g_list_next (walk);
}
return NULL;
}
/**
* gst_autoplug_pads:
* @srcpad: the source pad
* @sinkpad: the sink pad
* gst_autoplugfactory_get_list:
*
* Perform autoplugging between the two given pads.
* Get the global list of elementfactories.
*
* Returns: a list of elementfactories that can connect
* the two pads
* Returns: GList of type #GstElementFactory
*/
GList*
gst_autoplug_pads (GstPad *srcpad, GstPad *sinkpad)
gst_autoplugfactory_get_list (void)
{
caps_struct caps;
caps.src = gst_pad_get_caps_list(srcpad);
caps.sink = gst_pad_get_caps_list(sinkpad);
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures");
return gst_autoplug_func (caps.src, caps.sink,
gst_autoplug_elementfactory_get_list,
gst_autoplug_caps_find_cost,
&caps);
return _gst_autoplugfactories;
}
static gint
find_factory (gst_autoplug_node *rgnNodes, gpointer factory)
{
gint i=0;
while (rgnNodes[i].iNode) {
if (rgnNodes[i].iNode == factory) return i;
i++;
GstAutoplug*
gst_autoplugfactory_create (GstAutoplugFactory *factory)
{
GstAutoplug *new = NULL;
g_return_val_if_fail (factory != NULL, NULL);
if (factory->type == 0){
factory = gst_plugin_load_autoplugfactory (factory->name);
}
return 0;
g_return_val_if_fail (factory != NULL, NULL);
g_return_val_if_fail (factory->type != 0, NULL);
new = GST_AUTOPLUG (gtk_type_new (factory->type));
return new;
}
static GList*
construct_path (gst_autoplug_node *rgnNodes, gpointer factory)
GstAutoplug*
gst_autoplugfactory_make (const gchar *name)
{
GstElementFactory *current;
GList *factories = NULL;
GstAutoplugFactory *factory;
current = rgnNodes[find_factory(rgnNodes, factory)].iPrev;
g_return_val_if_fail (name != NULL, NULL);
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factories found in autoplugging (reversed order)");
factory = gst_autoplugfactory_find (name);
while (current != NULL)
{
gpointer next = NULL;
if (factory == NULL)
return NULL;
next = rgnNodes[find_factory(rgnNodes, current)].iPrev;
if (next) {
factories = g_list_prepend (factories, current);
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory: \"%s\"", current->name);
return gst_autoplugfactory_create (factory);;
}
xmlNodePtr
gst_autoplugfactory_save_thyself (GstAutoplugFactory *factory, xmlNodePtr parent)
{
g_return_val_if_fail(factory != NULL, NULL);
xmlNewChild(parent,NULL,"name",factory->name);
xmlNewChild(parent,NULL,"longdesc", factory->longdesc);
return parent;
}
GstAutoplugFactory*
gst_autoplugfactory_load_thyself (xmlNodePtr parent)
{
GstAutoplugFactory *factory = g_new0(GstAutoplugFactory, 1);
xmlNodePtr children = parent->xmlChildrenNode;
while (children) {
if (!strcmp(children->name, "name")) {
factory->name = xmlNodeGetContent(children);
}
current = next;
}
return factories;
}
static GList*
gst_autoplug_enqueue (GList *queue, gpointer iNode, gint iDist, gpointer iPrev)
{
gst_autoplug_node *node = g_malloc (sizeof (gst_autoplug_node));
node->iNode = iNode;
node->iDist = iDist;
node->iPrev = iPrev;
queue = g_list_append (queue, node);
return queue;
}
static GList*
gst_autoplug_dequeue (GList *queue, gpointer *iNode, gint *iDist, gpointer *iPrev)
{
GList *head;
gst_autoplug_node *node;
head = g_list_first (queue);
if (head) {
node = (gst_autoplug_node *)head->data;
*iNode = node->iNode;
*iPrev = node->iPrev;
*iDist = node->iDist;
head = g_list_remove (queue, node);
}
return head;
}
static GList*
gst_autoplug_func (gpointer src, gpointer sink,
GstAutoplugListFunction list_function,
GstAutoplugCostFunction cost_function,
gpointer data)
{
gst_autoplug_node *rgnNodes;
GList *queue = NULL;
gpointer iNode, iPrev;
gint iDist, i, iCost;
GList *elements = g_list_copy (list_function(data));
GList *factories;
guint num_factories;
elements = g_list_append (elements, sink);
elements = g_list_append (elements, src);
factories = elements;
num_factories = g_list_length (factories);
rgnNodes = g_new0 (gst_autoplug_node, num_factories+1);
for (i=0; i< num_factories; i++) {
gpointer fact = factories->data;
rgnNodes[i].iNode = fact;
rgnNodes[i].iPrev = NULL;
if (fact == src) {
rgnNodes[i].iDist = 0;
}
else {
rgnNodes[i].iDist = GST_AUTOPLUG_MAX_COST;
}
factories = g_list_next (factories);
}
rgnNodes[num_factories].iNode = NULL;
queue = gst_autoplug_enqueue (queue, src, 0, NULL);
while (g_list_length (queue) > 0) {
GList *factories2 = elements;
queue = gst_autoplug_dequeue (queue, &iNode, &iDist, &iPrev);
for (i=0; i< num_factories; i++) {
gpointer current = factories2->data;
iCost = cost_function (iNode, current, data);
if (iCost != GST_AUTOPLUG_MAX_COST) {
if((GST_AUTOPLUG_MAX_COST == rgnNodes[i].iDist) ||
(rgnNodes[i].iDist > (iCost + iDist))) {
rgnNodes[i].iDist = iDist + iCost;
rgnNodes[i].iPrev = iNode;
queue = gst_autoplug_enqueue (queue, current, iDist + iCost, iNode);
}
}
factories2 = g_list_next (factories2);
if (!strcmp(children->name, "longdesc")) {
factory->longdesc = xmlNodeGetContent(children);
}
children = children->next;
}
return construct_path (rgnNodes, sink);
_gst_autoplugfactories = g_list_prepend (_gst_autoplugfactories, factory);
return factory;
}

View file

@ -31,7 +31,7 @@ extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_AUTOPLUG \
(gst_object_get_type())
(gst_autoplug_get_type())
#define GST_AUTOPLUG(obj) \
(GTK_CHECK_CAST((obj),GST_TYPE_AUTOPLUG,GstAutoplug))
#define GST_AUTOPLUG_CLASS(klass) \
@ -44,30 +44,66 @@ extern "C" {
typedef struct _GstAutoplug GstAutoplug;
typedef struct _GstAutoplugClass GstAutoplugClass;
#define GST_AUTOPLUG_MAX_COST 999999
typedef enum {
GST_AUTOPLUG_TO_CAPS = GST_OBJECT_FLAG_LAST,
GST_AUTOPLUG_TO_RENDERER,
typedef guint (*GstAutoplugCostFunction) (gpointer src, gpointer dest, gpointer data);
typedef GList* (*GstAutoplugListFunction) (gpointer data);
GST_AUTOPLUG_FLAG_LAST = GST_OBJECT_FLAG_LAST + 8,
} GstAutoplugFlags;
struct _GstAutoplug {
GtkObject object;
GstObject object;
};
struct _GstAutoplugClass {
GtkObjectClass parent_class;
GstObjectClass parent_class;
/* signal callbacks */
void (*new_object) (GstAutoplug *autoplug, GstObject *object);
/* perform the autoplugging */
GstElement* (*autoplug_to_caps) (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, va_list args);
GstElement* (*autoplug_to_renderers) (GstAutoplug *autoplug, GList *srccaps, GstElement *target, va_list args);
};
GtkType gst_autoplug_get_type (void);
typedef struct _GstAutoplugFactory GstAutoplugFactory;
GList* gst_autoplug_caps (GstCaps *srccaps, GstCaps *sinkcaps);
GList* gst_autoplug_caps_list (GList *srccaps, GList *sinkcaps);
GList* gst_autoplug_pads (GstPad *srcpad, GstPad *sinkpad);
struct _GstAutoplugFactory {
gchar *name; /* name of autoplugger */
gchar *longdesc; /* long description of the autoplugger (well, don't overdo it..) */
GtkType type; /* unique GtkType of the autoplugger */
};
GtkType gst_autoplug_get_type (void);
void gst_autoplug_signal_new_object (GstAutoplug *autoplug, GstObject *object);
GstElement* gst_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, ...);
GstElement* gst_autoplug_to_renderers (GstAutoplug *autoplug, GList *srccaps,
GstElement *target, ...);
/*
* creating autopluggers
*
*/
GstAutoplugFactory* gst_autoplugfactory_new (const gchar *name, const gchar *longdesc, GtkType type);
void gst_autoplugfactory_destroy (GstAutoplugFactory *factory);
GstAutoplugFactory* gst_autoplugfactory_find (const gchar *name);
GList* gst_autoplugfactory_get_list (void);
GstAutoplug* gst_autoplugfactory_create (GstAutoplugFactory *factory);
GstAutoplug* gst_autoplugfactory_make (const gchar *name);
xmlNodePtr gst_autoplugfactory_save_thyself (GstAutoplugFactory *factory, xmlNodePtr parent);
GstAutoplugFactory* gst_autoplugfactory_load_thyself (xmlNodePtr parent);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_AUTOPLUG_H__ */
#endif /* __GST_AUTOPLUG_H__ */

View file

@ -234,6 +234,7 @@ gst_bin_change_state (GstElement *element)
GstBin *bin;
GList *children;
GstElement *child;
GstElementStateReturn ret;
GST_DEBUG_ENTER("(\"%s\")",GST_ELEMENT_NAME (element));
@ -265,6 +266,8 @@ gst_bin_change_state (GstElement *element)
break;
}
case GST_STATE_READY_TO_NULL:
GST_FLAG_UNSET (bin, GST_BIN_FLAG_MANAGER);
default:
break;
}
@ -289,9 +292,9 @@ gst_bin_change_state (GstElement *element)
children = g_list_next (children);
}
// g_print("<-- \"%s\"\n",gst_object_get_name(GST_OBJECT(bin)));
ret = gst_bin_change_state_norecurse (bin);
return gst_bin_change_state_norecurse (bin);
return ret;
}
@ -587,7 +590,7 @@ gst_bin_create_plan (GstBin *bin)
static void
gst_bin_received_eos (GstElement *element, GstBin *bin)
{
GST_INFO_ELEMENT (GST_CAT_PLANNING, bin, "child %s fired eos, pending %d\n", GST_ELEMENT_NAME (element),
GST_INFO_ELEMENT (GST_CAT_PLANNING, bin, "child %s fired eos, pending %d", GST_ELEMENT_NAME (element),
bin->num_eos_providers);
GST_LOCK (bin);
@ -756,7 +759,9 @@ gst_bin_create_plan_func (GstBin *bin)
}
// else it's not ours and we need to wait for EOS notifications
else {
gtk_signal_connect (GTK_OBJECT (element), "eos", gst_bin_received_eos, bin);
GST_DEBUG (0,"setting up EOS signal from \"%s\" to \"%s\"\n", elementname,
gst_element_get_name (GST_ELEMENT(bin)->manager));
gtk_signal_connect (GTK_OBJECT (element), "eos", gst_bin_received_eos, GST_ELEMENT(bin)->manager);
bin->eos_providers = g_list_prepend (bin->eos_providers, element);
bin->num_eos_providers++;
}
@ -869,7 +874,7 @@ gst_bin_iterate_func (GstBin *bin)
if (bin->num_eos_providers) {
GST_LOCK (bin);
GST_DEBUG (0,"waiting for eos providers\n");
g_cond_wait (bin->eoscond, GST_OBJECT(bin)->lock);
g_cond_wait (bin->eoscond, GST_GET_LOCK(bin));
GST_DEBUG (0,"num eos providers %d\n", bin->num_eos_providers);
GST_UNLOCK (bin);
}

View file

@ -29,8 +29,8 @@
#include "gstpropsprivate.h"
void
_gst_caps_initialize (void)
void
_gst_caps_initialize (void)
{
}
@ -67,12 +67,12 @@ gst_caps_new (const gchar *name, const gchar *mime)
GstCaps *caps;
g_return_val_if_fail (mime != NULL, NULL);
caps = g_new0 (GstCaps, 1);
caps->name = g_strdup (name);
caps->id = get_type_for_mime (mime);
caps->properties = NULL;
return caps;
}
@ -90,7 +90,7 @@ GstCaps*
gst_caps_new_with_props (const gchar *name, const gchar *mime, GstProps *props)
{
GstCaps *caps;
caps = gst_caps_new (name, mime);
caps->properties = props;
@ -101,7 +101,7 @@ gst_caps_new_with_props (const gchar *name, const gchar *mime, GstProps *props)
* gst_caps_register:
* @factory: the factory to register
*
* Register the factory.
* Register the factory.
*
* Returns: the registered capability
*/
@ -140,7 +140,7 @@ gst_caps_register_count (GstCapsFactory *factory, guint *counter)
tag = (*factory)[i++];
g_return_val_if_fail (tag != NULL, NULL);
typeid = get_type_for_mime ((gchar *)tag);
caps = g_new0 (GstCaps, 1);
@ -163,7 +163,7 @@ gst_caps_register_count (GstCapsFactory *factory, guint *counter)
*
* Returns: the name of the caps
*/
const gchar*
const gchar*
gst_caps_get_name (GstCaps *caps)
{
g_return_val_if_fail (caps != NULL, NULL);
@ -173,7 +173,7 @@ gst_caps_get_name (GstCaps *caps)
/**
* gst_caps_set_name:
* @caps: the caps to set the name to
* @caps: the caps to set the name to
* @name: the name to set
*
* Set the name of a caps.
@ -182,7 +182,7 @@ void
gst_caps_set_name (GstCaps *caps, const gchar *name)
{
g_return_if_fail (caps != NULL);
if (caps->name)
g_free (caps->name);
@ -197,7 +197,7 @@ gst_caps_set_name (GstCaps *caps, const gchar *name)
*
* Returns: the mime type of the caps
*/
const gchar*
const gchar*
gst_caps_get_mime (GstCaps *caps)
{
GstType *type;
@ -206,9 +206,9 @@ gst_caps_get_mime (GstCaps *caps)
type = gst_type_find_by_id (caps->id);
if (type)
if (type)
return type->mime;
else
else
return "unknown/unknown";
}
@ -236,7 +236,7 @@ gst_caps_set_mime (GstCaps *caps, const gchar *mime)
*
* Returns: the type id of the caps
*/
guint16
guint16
gst_caps_get_type_id (GstCaps *caps)
{
g_return_val_if_fail (caps != NULL, 0);
@ -247,16 +247,16 @@ gst_caps_get_type_id (GstCaps *caps)
/**
* gst_caps_set_type_id:
* @caps: the caps to set the type id to
* @typeid: the type id to set
* @typeid: the type id to set
*
* Set the type id of the caps.
*/
void
gst_caps_set_type_id (GstCaps *caps, guint16 typeid)
gst_caps_set_type_id (GstCaps *caps, guint16 type_id)
{
g_return_if_fail (caps != NULL);
caps->id = typeid;
caps->id = type_id;
}
/**
@ -276,7 +276,7 @@ gst_caps_set_props (GstCaps *caps, GstProps *props)
g_return_val_if_fail (caps->properties == NULL, caps);
caps->properties = props;
return caps;
}
@ -310,7 +310,7 @@ gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
{
g_return_val_if_fail (fromcaps != NULL, FALSE);
g_return_val_if_fail (tocaps != NULL, FALSE);
if (fromcaps->id != tocaps->id) {
GST_DEBUG (0,"gstcaps: mime types differ (%d to %d)\n",
fromcaps->id, tocaps->id);
@ -371,7 +371,7 @@ gst_caps_list_check_compatibility (GList *fromcaps, GList *tocaps)
*
* Returns: a new XML node pointer
*/
xmlNodePtr
xmlNodePtr
gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent)
{
xmlNodePtr subtree;
@ -397,7 +397,7 @@ gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent)
*
* Returns: a new capability
*/
GstCaps*
GstCaps*
gst_caps_load_thyself (xmlNodePtr parent)
{
GstCaps *caps = g_new0 (GstCaps, 1);

View file

@ -52,7 +52,7 @@ struct _GstCaps {
};
/* initialize the subsystem */
void _gst_caps_initialize (void);
void _gst_caps_initialize (void);
GstCaps* gst_caps_new (const gchar *name, const gchar *mime);
GstCaps* gst_caps_new_with_props (const gchar *name, const gchar *mime, GstProps *props);
@ -60,21 +60,21 @@ GstCaps* gst_caps_register (GstCapsFactory *factory);
GstCaps* gst_caps_register_count (GstCapsFactory *factory, guint *counter);
const gchar* gst_caps_get_name (GstCaps *caps);
void gst_caps_set_name (GstCaps *caps, const gchar *name);
void gst_caps_set_name (GstCaps *caps, const gchar *name);
const gchar* gst_caps_get_mime (GstCaps *caps);
void gst_caps_set_mime (GstCaps *caps, const gchar *mime);
void gst_caps_set_mime (GstCaps *caps, const gchar *mime);
guint16 gst_caps_get_type_id (GstCaps *caps);
void gst_caps_set_type_id (GstCaps *caps, guint16 /*typeid*/);
guint16 gst_caps_get_type_id (GstCaps *caps);
void gst_caps_set_type_id (GstCaps *caps, guint16 type_id);
GstCaps* gst_caps_set_props (GstCaps *caps, GstProps *props);
GstProps* gst_caps_get_props (GstCaps *caps);
gboolean gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps);
gboolean gst_caps_list_check_compatibility (GList *fromcaps, GList *tocaps);
gboolean gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps);
gboolean gst_caps_list_check_compatibility (GList *fromcaps, GList *tocaps);
xmlNodePtr gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent);
GstCaps* gst_caps_load_thyself (xmlNodePtr parent);
xmlNodePtr gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent);
GstCaps* gst_caps_load_thyself (xmlNodePtr parent);
#endif /* __GST_CAPS_H__ */

View file

@ -519,7 +519,7 @@ gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ)
g_return_val_if_fail (templ != NULL, NULL);
templ_new = gst_element_get_padtemplate_by_compatible (element, templ);
if (templ_new != NULL)
if (templ_new != NULL)
pad = gst_element_request_pad (element, templ_new);
return pad;
@ -902,13 +902,15 @@ gst_element_save_thyself (GstObject *object,
type = gtk_type_parent (type);
}
pads = element->pads;
pads = GST_ELEMENT_PADS (element);
while (pads) {
GstPad *pad = GST_PAD (pads->data);
xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL);
// figure out if it's a direct pad or a ghostpad
if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element)
if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL);
gst_object_save_thyself (GST_OBJECT (pad), padtag);
}
pads = g_list_next (pads);
}
@ -973,7 +975,6 @@ gst_element_load_thyself (xmlNodePtr self, GstObject *parent)
}
child = child->next;
}
gst_util_set_object_arg (GTK_OBJECT (element), name, value);
}
children = children->next;

View file

@ -122,6 +122,7 @@ typedef enum {
#define GST_ELEMENT_NAME(obj) (GST_OBJECT_NAME(obj))
#define GST_ELEMENT_PARENT(obj) (GST_OBJECT_PARENT(obj))
#define GST_ELEMENT_PADS(obj) ((obj)->pads)
typedef struct _GstElement GstElement;
typedef struct _GstElementClass GstElementClass;

View file

@ -30,8 +30,8 @@
/* global list of registered elementfactories */
GList* _gst_elementfactories;
void
_gst_elementfactory_initialize (void)
void
_gst_elementfactory_initialize (void)
{
_gst_elementfactories = NULL;
}
@ -42,8 +42,8 @@ _gst_elementfactory_initialize (void)
*
* Removes the elementfactory from the global list.
*/
void
gst_elementfactory_destroy (GstElementFactory *elementfactory)
void
gst_elementfactory_destroy (GstElementFactory *elementfactory)
{
g_return_if_fail (elementfactory != NULL);
@ -61,7 +61,7 @@ gst_elementfactory_destroy (GstElementFactory *elementfactory)
* Returns: #GstElementFactory if found, NULL otherwise
*/
GstElementFactory*
gst_elementfactory_find (const gchar *name)
gst_elementfactory_find (const gchar *name)
{
GList *walk;
GstElementFactory *factory;
@ -89,7 +89,7 @@ gst_elementfactory_find (const gchar *name)
* Returns: GList of type #GstElementFactory
*/
GList*
gst_elementfactory_get_list (void)
gst_elementfactory_get_list (void)
{
return _gst_elementfactories;
}
@ -108,12 +108,14 @@ gst_elementfactory_get_list (void)
*/
GstElementFactory*
gst_elementfactory_new (const gchar *name, GtkType type,
GstElementDetails *details)
GstElementDetails *details)
{
GstElementFactory *factory = g_new0(GstElementFactory, 1);
GstElementFactory *factory;
g_return_val_if_fail(name != NULL, NULL);
factory = g_new0(GstElementFactory, 1);
factory->name = g_strdup(name);
factory->type = type;
factory->details = details;
@ -138,7 +140,7 @@ gst_elementfactory_new (const gchar *name, GtkType type,
*/
GstElement *
gst_elementfactory_create (GstElementFactory *factory,
const gchar *name)
const gchar *name)
{
GstElement *element;
GstElementClass *oclass;
@ -184,7 +186,7 @@ gst_elementfactory_create (GstElementFactory *factory,
* Returns: new #GstElement
*/
GstElement*
gst_elementfactory_make (const gchar *factoryname, const gchar *name)
gst_elementfactory_make (const gchar *factoryname, const gchar *name)
{
GstElementFactory *factory;
GstElement *element;
@ -338,15 +340,15 @@ gst_elementfactory_can_sink_caps (GstElementFactory *factory,
/**
* gst_elementfactory_save_thyself:
* @factory: factory to save
* @parent: the parent xmlNodePtr
* @parent: the parent xmlNodePtr
*
* Saves the factory into an XML tree.
*
*
* Returns: the new xmlNodePtr
*/
xmlNodePtr
gst_elementfactory_save_thyself (GstElementFactory *factory,
xmlNodePtr parent)
xmlNodePtr
gst_elementfactory_save_thyself (GstElementFactory *factory,
xmlNodePtr parent)
{
GList *pads;
@ -377,14 +379,14 @@ gst_elementfactory_save_thyself (GstElementFactory *factory,
/**
* gst_elementfactory_load_thyself:
* @parent: the parent xmlNodePtr
* @parent: the parent xmlNodePtr
*
* Creates a new factory from an xmlNodePtr.
*
*
* Returns: the new factory
*/
GstElementFactory *
gst_elementfactory_load_thyself (xmlNodePtr parent)
gst_elementfactory_load_thyself (xmlNodePtr parent)
{
GstElementFactory *factory = g_new0(GstElementFactory, 1);
xmlNodePtr children = parent->xmlChildrenNode;
@ -415,7 +417,7 @@ gst_elementfactory_load_thyself (xmlNodePtr parent)
}
if (!strcmp(children->name, "padtemplate")) {
GstPadTemplate *template;
template = gst_padtemplate_load_thyself (children);
gst_elementfactory_add_padtemplate (factory, template);

View file

@ -370,13 +370,15 @@ gst_object_get_path_string (GstObject *object)
GSList *parentage = NULL;
GSList *parents;
void *parent;
gchar *prevpath, *path = "";
gchar *prevpath, *path;
const char *component;
gchar *separator = "";
gboolean free_component;
parentage = g_slist_prepend (NULL, object);
path = g_strdup ("");
// first walk the object hierarchy to build a list of the parents
do {
if (GST_IS_OBJECT (object)) {
@ -397,9 +399,9 @@ gst_object_get_path_string (GstObject *object)
parents = parentage;
while (parents) {
if (GST_IS_OBJECT (parents->data)) {
GstObjectClass *oclass = GST_OBJECT_CLASS (GTK_OBJECT (parents->data));
GstObjectClass *oclass = GST_OBJECT_CLASS (GTK_OBJECT (parents->data)->klass);
component = GST_OBJECT_NAME (parents->data);
component = gst_object_get_name (parents->data);
separator = oclass->path_string_separator;
free_component = FALSE;
} else {

View file

@ -35,7 +35,6 @@ static void gst_pad_init (GstPad *pad);
static xmlNodePtr gst_pad_save_thyself (GstObject *object, xmlNodePtr parent);
static GstObject *pad_parent_class = NULL;
GtkType
@ -593,6 +592,25 @@ gst_pad_get_parent (GstPad *pad)
return GST_OBJECT_PARENT (pad);
}
/**
* gst_pad_get_real_parent:
* @pad: the pad to get the parent from
*
* Get the real parent object of this pad. If the pad
* is a ghostpad, the actual owner of the real pad is
* returned, as opposed to the gst_pad_get_parent.
*
* Returns: the parent object
*/
GstObject*
gst_pad_get_real_parent (GstPad *pad)
{
g_return_val_if_fail (pad != NULL, NULL);
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
return GST_PAD_PARENT (GST_PAD (GST_PAD_REALIZE (pad)));
}
/**
* gst_pad_add_ghost_pad:
* @pad: the pad to set the ghost parent
@ -948,7 +966,7 @@ gst_pad_pull (GstPad *pad)
{
GstRealPad *peer = GST_RPAD_PEER(pad);
g_return_if_fail (peer != NULL);
g_return_val_if_fail (peer != NULL, NULL);
GST_DEBUG_ENTER("(%s:%s)",GST_DEBUG_PAD_NAME(pad));
@ -983,7 +1001,7 @@ gst_pad_pullregion (GstPad *pad, GstRegionType type, guint64 offset, guint64 len
{
GstRealPad *peer = GST_RPAD_PEER(pad);
g_return_if_fail (peer != NULL);
g_return_val_if_fail (peer != NULL, NULL);
GST_DEBUG_ENTER("(%s:%s,%d,%lld,%lld)",GST_DEBUG_PAD_NAME(pad),type,offset,len);
@ -1003,6 +1021,65 @@ gst_pad_pullregion (GstPad *pad, GstRegionType type, guint64 offset, guint64 len
* templates
*
*/
static void gst_padtemplate_class_init (GstPadTemplateClass *klass);
static void gst_padtemplate_init (GstPadTemplate *templ);
enum {
TEMPL_PAD_CREATED,
/* FILL ME */
TEMPL_LAST_SIGNAL
};
static GstObject *padtemplate_parent_class = NULL;
static guint gst_padtemplate_signals[TEMPL_LAST_SIGNAL] = { 0 };
GtkType
gst_padtemplate_get_type (void)
{
static GtkType padtemplate_type = 0;
if (!padtemplate_type) {
static const GtkTypeInfo padtemplate_info = {
"GstPadTemplate",
sizeof(GstPadTemplate),
sizeof(GstPadTemplateClass),
(GtkClassInitFunc)gst_padtemplate_class_init,
(GtkObjectInitFunc)gst_padtemplate_init,
(GtkArgSetFunc)NULL,
(GtkArgGetFunc)NULL,
(GtkClassInitFunc)NULL,
};
padtemplate_type = gtk_type_unique(GST_TYPE_OBJECT,&padtemplate_info);
}
return padtemplate_type;
}
static void
gst_padtemplate_class_init (GstPadTemplateClass *klass)
{
GtkObjectClass *gtkobject_class;
GstObjectClass *gstobject_class;
gtkobject_class = (GtkObjectClass*)klass;
gstobject_class = (GstObjectClass*)klass;
padtemplate_parent_class = gtk_type_class(GST_TYPE_OBJECT);
gst_padtemplate_signals[TEMPL_PAD_CREATED] =
gtk_signal_new ("pad_created", GTK_RUN_LAST, gtkobject_class->type,
GTK_SIGNAL_OFFSET (GstPadTemplateClass, pad_created),
gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1,
GST_TYPE_PAD);
gtk_object_class_add_signals (gtkobject_class, gst_padtemplate_signals, TEMPL_LAST_SIGNAL);
gstobject_class->path_string_separator = "*";
}
static void
gst_padtemplate_init (GstPadTemplate *templ)
{
}
/**
* gst_padtemplate_new:
@ -1022,7 +1099,7 @@ gst_padtemplate_new (GstPadFactory *factory)
g_return_val_if_fail (factory != NULL, NULL);
new = g_new0 (GstPadTemplate, 1);
new = gtk_type_new (gst_padtemplate_get_type ());
tag = (*factory)[i++];
g_return_val_if_fail (tag != NULL, new);
@ -1063,7 +1140,9 @@ gst_padtemplate_create (gchar *name_template,
{
GstPadTemplate *new;
new = g_new0 (GstPadTemplate, 1);
g_return_val_if_fail (name_template != NULL, NULL);
new = gtk_type_new (gst_padtemplate_get_type ());
new->name_template = name_template;
new->direction = direction;
@ -1134,21 +1213,24 @@ GstPadTemplate*
gst_padtemplate_load_thyself (xmlNodePtr parent)
{
xmlNodePtr field = parent->xmlChildrenNode;
GstPadTemplate *factory = g_new0 (GstPadTemplate, 1);
GstPadTemplate *factory;
gchar *name_template = NULL;
GstPadDirection direction = GST_PAD_UNKNOWN;
GstPadPresence presence = GST_PAD_ALWAYS;
GList *caps = NULL;
while (field) {
if (!strcmp(field->name, "nametemplate")) {
factory->name_template = xmlNodeGetContent(field);
name_template = xmlNodeGetContent(field);
}
if (!strcmp(field->name, "direction")) {
gchar *value = xmlNodeGetContent(field);
factory->direction = GST_PAD_UNKNOWN;
if (!strcmp(value, "sink")) {
factory->direction = GST_PAD_SINK;
direction = GST_PAD_SINK;
}
else if (!strcmp(value, "src")) {
factory->direction = GST_PAD_SRC;
direction = GST_PAD_SRC;
}
g_free (value);
}
@ -1156,21 +1238,24 @@ gst_padtemplate_load_thyself (xmlNodePtr parent)
gchar *value = xmlNodeGetContent(field);
if (!strcmp(value, "always")) {
factory->presence = GST_PAD_ALWAYS;
presence = GST_PAD_ALWAYS;
}
else if (!strcmp(value, "sometimes")) {
factory->presence = GST_PAD_SOMETIMES;
presence = GST_PAD_SOMETIMES;
}
else if (!strcmp(value, "request")) {
factory->presence = GST_PAD_REQUEST;
presence = GST_PAD_REQUEST;
}
g_free (value);
}
else if (!strcmp(field->name, "caps")) {
factory->caps = g_list_append(factory->caps, gst_caps_load_thyself (field));
caps = g_list_append (caps, gst_caps_load_thyself (field));
}
field = field->next;
}
factory = gst_padtemplate_create (name_template, direction, presence, caps);
return factory;
}
@ -1271,13 +1356,6 @@ gst_pad_get_element_private (GstPad *pad)
}
/***** ghost pads *****/
static void gst_ghost_pad_class_init (GstGhostPadClass *klass);

View file

@ -278,6 +278,7 @@ const gchar* gst_pad_get_name (GstPad *pad);
void gst_pad_set_parent (GstPad *pad, GstObject *parent);
GstObject* gst_pad_get_parent (GstPad *pad);
GstObject* gst_pad_get_real_parent (GstPad *pad);
void gst_pad_add_ghost_pad (GstPad *pad, GstPad *ghostpad);
void gst_pad_remove_ghost_pad (GstPad *pad, GstPad *ghostpad);

View file

@ -24,10 +24,6 @@
#include "gst_private.h"
#include "gstpipeline.h"
#include "gstthread.h"
#include "gstutils.h"
#include "gsttype.h"
#include "gstautoplug.h"
GstElementDetails gst_pipeline_details = {
@ -51,15 +47,13 @@ enum {
};
static void gst_pipeline_class_init (GstPipelineClass *klass);
static void gst_pipeline_init (GstPipeline *pipeline);
static void gst_pipeline_class_init (GstPipelineClass *klass);
static void gst_pipeline_init (GstPipeline *pipeline);
static GstElementStateReturn gst_pipeline_change_state (GstElement *element);
static GstElementStateReturn gst_pipeline_change_state (GstElement *element);
static void gst_pipeline_prepare (GstPipeline *pipeline);
static void gst_pipeline_prepare (GstPipeline *pipeline);
static void gst_pipeline_have_type (GstElement *sink, GstElement *sink2, gpointer data);
static void gst_pipeline_pads_autoplug (GstElement *src, GstElement *sink);
static GstBinClass *parent_class = NULL;
//static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 };
@ -85,7 +79,7 @@ gst_pipeline_get_type (void) {
}
static void
gst_pipeline_class_init (GstPipelineClass *klass)
gst_pipeline_class_init (GstPipelineClass *klass)
{
GstElementClass *gstelement_class;
@ -96,14 +90,11 @@ gst_pipeline_class_init (GstPipelineClass *klass)
gstelement_class->change_state = gst_pipeline_change_state;
}
static void
gst_pipeline_init (GstPipeline *pipeline)
static void
gst_pipeline_init (GstPipeline *pipeline)
{
// we're a manager by default
GST_FLAG_SET (pipeline, GST_BIN_FLAG_MANAGER);
pipeline->src = NULL;
pipeline->sinks = NULL;
}
@ -116,393 +107,25 @@ gst_pipeline_init (GstPipeline *pipeline)
* Returns: newly created GstPipeline
*/
GstElement*
gst_pipeline_new (guchar *name)
gst_pipeline_new (guchar *name)
{
return gst_elementfactory_make ("pipeline", name);
}
static void
gst_pipeline_prepare (GstPipeline *pipeline)
static void
gst_pipeline_prepare (GstPipeline *pipeline)
{
GST_DEBUG (0,"GstPipeline: preparing pipeline \"%s\" for playing\n",
GST_DEBUG (0,"GstPipeline: preparing pipeline \"%s\" for playing\n",
GST_ELEMENT_NAME(GST_ELEMENT(pipeline)));
}
static void
gst_pipeline_have_type (GstElement *sink, GstElement *sink2, gpointer data)
{
GST_DEBUG (0,"GstPipeline: pipeline have type %p\n", (gboolean *)data);
*(gboolean *)data = TRUE;
}
static GstCaps*
gst_pipeline_typefind (GstPipeline *pipeline, GstElement *element)
{
gboolean found = FALSE;
GstElement *typefind;
GstCaps *caps = NULL;
GST_DEBUG (0,"GstPipeline: typefind for element \"%s\" %p\n",
GST_ELEMENT_NAME(element), &found);
typefind = gst_elementfactory_make ("typefind", "typefind");
g_return_val_if_fail (typefind != NULL, FALSE);
gtk_signal_connect (GTK_OBJECT (typefind), "have_type",
GTK_SIGNAL_FUNC (gst_pipeline_have_type), &found);
gst_pad_connect (gst_element_get_pad (element, "src"),
gst_element_get_pad (typefind, "sink"));
gst_bin_add (GST_BIN (pipeline), typefind);
//gst_bin_create_plan (GST_BIN (pipeline));
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
// keep pushing buffers... the have_type signal handler will set the found flag
while (!found) {
gst_bin_iterate (GST_BIN (pipeline));
}
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
if (found) {
caps = gst_util_get_pointer_arg (GTK_OBJECT (typefind), "caps");
gst_pad_set_caps_list (gst_element_get_pad (element, "src"), g_list_prepend (NULL, caps));
}
gst_pad_disconnect (gst_element_get_pad (element, "src"),
gst_element_get_pad (typefind, "sink"));
gst_bin_remove (GST_BIN (pipeline), typefind);
gst_object_unref (GST_OBJECT (typefind));
return caps;
}
static gboolean
gst_pipeline_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink)
{
GList *sinkpads;
gboolean connected = FALSE;
GST_DEBUG (0,"gstpipeline: autoplug pad connect function for \"%s\" to \"%s\"\n",
GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink));
sinkpads = gst_element_get_pad_list(sink);
while (sinkpads) {
GstPad *sinkpad = (GstPad *)sinkpads->data;
// if we have a match, connect the pads
if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
!GST_PAD_CONNECTED(sinkpad))
{
if (gst_caps_list_check_compatibility (gst_pad_get_caps_list(pad), gst_pad_get_caps_list(sinkpad))) {
gst_pad_connect(pad, sinkpad);
GST_DEBUG (0,"gstpipeline: autoconnect pad \"%s\" in element %s <-> ", GST_PAD_NAME (pad),
GST_ELEMENT_NAME(src));
GST_DEBUG (0,"pad \"%s\" in element %s\n", GST_PAD_NAME (sinkpad),
GST_ELEMENT_NAME(sink));
connected = TRUE;
break;
}
else {
GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad));
}
}
sinkpads = g_list_next(sinkpads);
}
if (!connected) {
GST_DEBUG (0,"gstpipeline: no path to sinks for type\n");
}
return connected;
}
static void
gst_pipeline_pads_autoplug (GstElement *src, GstElement *sink)
{
GList *srcpads;
gboolean connected = FALSE;
srcpads = gst_element_get_pad_list(src);
while (srcpads && !connected) {
GstPad *srcpad = (GstPad *)srcpads->data;
if (gst_pad_get_direction(srcpad) == GST_PAD_SRC)
connected = gst_pipeline_pads_autoplug_func (src, srcpad, sink);
srcpads = g_list_next(srcpads);
}
if (!connected) {
GST_DEBUG (0,"gstpipeline: delaying pad connections for \"%s\" to \"%s\"\n",
GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink));
gtk_signal_connect(GTK_OBJECT(src),"new_pad",
GTK_SIGNAL_FUNC(gst_pipeline_pads_autoplug_func), sink);
}
}
/**
* gst_pipeline_add_src:
* @pipeline: the pipeline to add the src to
* @src: the src to add to the pipeline
*
* Adds a src element to the pipeline. This element
* will be used as a src for autoplugging. If you add more
* than one src element, the previously added element will
* be removed.
*/
void
gst_pipeline_add_src (GstPipeline *pipeline, GstElement *src)
{
g_return_if_fail (pipeline != NULL);
g_return_if_fail (GST_IS_PIPELINE (pipeline));
g_return_if_fail (src != NULL);
g_return_if_fail (GST_IS_ELEMENT (src));
if (pipeline->src) {
printf("gstpipeline: *WARNING* removing previously added element \"%s\"\n",
GST_ELEMENT_NAME(pipeline->src));
gst_bin_remove(GST_BIN(pipeline), pipeline->src);
}
pipeline->src = src;
gst_bin_add(GST_BIN(pipeline), src);
}
/**
* gst_pipeline_add_sink:
* @pipeline: the pipeline to add the sink to
* @sink: the sink to add to the pipeline
*
* Adds a sink element to the pipeline. This element
* will be used as a sink for autoplugging.
*/
void
gst_pipeline_add_sink (GstPipeline *pipeline, GstElement *sink)
{
g_return_if_fail (pipeline != NULL);
g_return_if_fail (GST_IS_PIPELINE (pipeline));
g_return_if_fail (sink != NULL);
g_return_if_fail (GST_IS_ELEMENT (sink));
pipeline->sinks = g_list_prepend (pipeline->sinks, sink);
//gst_bin_add(GST_BIN(pipeline), sink);
}
/**
* gst_pipeline_autoplug:
* @pipeline: the pipeline to autoplug
*
* Constructs a complete pipeline by automatically
* detecting the plugins needed.
*
* Returns: a gboolean indicating success or failure.
*/
gboolean
gst_pipeline_autoplug (GstPipeline *pipeline)
{
GList *elements;
GstElement *element, *srcelement = NULL, *sinkelement= NULL;
GList **factories;
GList **base_factories;
GstElementFactory *factory;
GstCaps *src_caps = 0;
guint i, numsinks;
gboolean use_thread = FALSE, have_common = FALSE;
GList *sinkstart;
g_return_val_if_fail(pipeline != NULL, FALSE);
g_return_val_if_fail(GST_IS_PIPELINE(pipeline), FALSE);
GST_DEBUG (0,"GstPipeline: autopluging pipeline \"%s\"\n",
GST_ELEMENT_NAME(GST_ELEMENT(pipeline)));
// fase 1, run typedetect on the source if needed...
if (!pipeline->src) {
GST_DEBUG (0,"GstPipeline: no source detected, can't autoplug pipeline \"%s\"\n",
GST_ELEMENT_NAME(GST_ELEMENT(pipeline)));
return FALSE;
}
GST_DEBUG (0,"GstPipeline: source \"%s\" has no MIME type, running typefind...\n",
GST_ELEMENT_NAME(pipeline->src));
src_caps = gst_pipeline_typefind(pipeline, pipeline->src);
if (src_caps) {
GST_DEBUG (0,"GstPipeline: source \"%s\" type found %d\n", GST_ELEMENT_NAME(pipeline->src),
src_caps->id);
}
else {
GST_DEBUG (0,"GstPipeline: source \"%s\" has no type\n", GST_ELEMENT_NAME(pipeline->src));
return FALSE;
}
srcelement = pipeline->src;
elements = pipeline->sinks;
sinkstart = g_list_copy (elements);
numsinks = g_list_length(elements);
factories = g_new0(GList *, numsinks);
base_factories = g_new0(GList *, numsinks);
i = 0;
// fase 2, loop over all the sinks..
while (elements) {
GstPad *pad;
element = GST_ELEMENT(elements->data);
pad = (GstPad *)gst_element_get_pad_list (element)->data;
base_factories[i] = factories[i] = gst_autoplug_caps_list (g_list_append(NULL,src_caps),
gst_pad_get_caps_list(pad));
// if we have a succesfull connection, proceed
if (factories[i] != NULL) {
i++;
}
else {
sinkstart = g_list_remove (sinkstart, element);
}
elements = g_list_next(elements);
}
while (factories[0]) {
// fase 3: add common elements
factory = (GstElementFactory *)(factories[0]->data);
// check to other paths for mathing elements (factories)
for (i=1; i<numsinks; i++) {
if (!factories[i] || (factory != (GstElementFactory *)(factories[i]->data))) {
goto differ;
}
factories[i] = g_list_next(factories[i]);
}
factory = (GstElementFactory *)(factories[0]->data);
GST_DEBUG (0,"common factory \"%s\"\n", factory->name);
element = gst_elementfactory_create(factory, factory->name);
gst_bin_add(GST_BIN(pipeline), element);
gst_pipeline_pads_autoplug(srcelement, element);
srcelement = element;
factories[0] = g_list_next(factories[0]);
have_common = TRUE;
}
differ:
// loop over all the sink elements
elements = sinkstart;
i = 0;
while (elements) {
GstElement *thesrcelement = srcelement;
GstElement *thebin = GST_ELEMENT(pipeline);
if (g_list_length(base_factories[i]) == 0) goto next;
sinkelement = (GstElement *)elements->data;
use_thread = have_common;
while (factories[i] || sinkelement) {
// fase 4: add other elements...
if (factories[i]) {
factory = (GstElementFactory *)(factories[i]->data);
GST_DEBUG (0,"factory \"%s\"\n", factory->name);
element = gst_elementfactory_create(factory, factory->name);
factories[i] = g_list_next(factories[i]);
}
// we have arived to the final sink element
else {
element = sinkelement;
sinkelement = NULL;
}
// this element suggests the use of a thread, so we set one up...
if (GST_ELEMENT_IS_THREAD_SUGGESTED(element) || use_thread) {
GstElement *queue;
GList *sinkpads;
GstPad *srcpad, *sinkpad;
use_thread = FALSE;
GST_DEBUG (0,"sugest new thread for \"%s\" %08x\n", GST_ELEMENT_NAME (element), GST_FLAGS(element));
// create a new queue and add to the previous bin
queue = gst_elementfactory_make("queue", g_strconcat("queue_", GST_ELEMENT_NAME(element), NULL));
GST_DEBUG (0,"adding element \"%s\"\n", GST_ELEMENT_NAME (element));
gst_bin_add(GST_BIN(thebin), queue);
// this will be the new bin for all following elements
thebin = gst_elementfactory_make("thread", g_strconcat("thread_", GST_ELEMENT_NAME(element), NULL));
srcpad = gst_element_get_pad(queue, "src");
sinkpads = gst_element_get_pad_list(element);
while (sinkpads) {
sinkpad = (GstPad *)sinkpads->data;
// FIXME connect matching pads, not just the first one...
if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
!GST_PAD_CONNECTED(sinkpad)) {
GList *caps = gst_pad_get_caps_list (sinkpad);
// the queue has the type of the elements it connects
gst_pad_set_caps_list (srcpad, caps);
gst_pad_set_caps_list (gst_element_get_pad(queue, "sink"), caps);
break;
}
sinkpads = g_list_next(sinkpads);
}
gst_pipeline_pads_autoplug(thesrcelement, queue);
GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element));
gst_bin_add(GST_BIN(thebin), element);
GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (thebin));
gst_bin_add(GST_BIN(pipeline), thebin);
thesrcelement = queue;
}
// no thread needed, easy case
else {
GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element));
gst_bin_add(GST_BIN(thebin), element);
}
gst_pipeline_pads_autoplug(thesrcelement, element);
// this element is now the new source element
thesrcelement = element;
}
next:
elements = g_list_next(elements);
i++;
}
return TRUE;
GST_DEBUG (0,"GstPipeline: unable to autoplug pipeline \"%s\"\n",
GST_ELEMENT_NAME(GST_ELEMENT(pipeline)));
return FALSE;
}
static GstElementStateReturn
gst_pipeline_change_state (GstElement *element)
static GstElementStateReturn
gst_pipeline_change_state (GstElement *element)
{
GstPipeline *pipeline;
g_return_val_if_fail (GST_IS_PIPELINE (element), FALSE);
pipeline = GST_PIPELINE (element);
switch (GST_STATE_TRANSITION (pipeline)) {
@ -513,22 +136,21 @@ gst_pipeline_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;
}
/**
* gst_pipeline_iterate:
* @pipeline: #GstPipeline to iterate
*
* Cause the pipeline's contents to be run through one full 'iteration'.
*/
void
gst_pipeline_iterate (GstPipeline *pipeline)
void
gst_pipeline_iterate (GstPipeline *pipeline)
{
g_return_if_fail (pipeline != NULL);
g_return_if_fail (GST_IS_PIPELINE(pipeline));

View file

@ -50,30 +50,22 @@ typedef struct _GstPipelineClass GstPipelineClass;
struct _GstPipeline {
GstBin bin;
GstElement *src; /* we only allow one src element */
GList *sinks; /* and multiple sinks */
};
struct _GstPipelineClass {
GstBinClass parent_class;
};
GtkType gst_pipeline_get_type (void);
GtkType gst_pipeline_get_type (void);
GstElement* gst_pipeline_new (guchar *name);
#define gst_pipeline_destroy(pipeline) gst_object_destroy(GST_OBJECT(pipeline))
#define gst_pipeline_destroy(pipeline) gst_object_destroy(GST_OBJECT(pipeline))
void gst_pipeline_add_src (GstPipeline *pipeline, GstElement *src);
void gst_pipeline_add_sink (GstPipeline *pipeline, GstElement *sink);
gboolean gst_pipeline_autoplug (GstPipeline *pipeline);
void gst_pipeline_iterate (GstPipeline *pipeline);
void gst_pipeline_iterate (GstPipeline *pipeline);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_PIPELINE_H__ */
#endif /* __GST_PIPELINE_H__ */

View file

@ -82,6 +82,8 @@ _gst_plugin_initialize (void)
PLUGINS_SRCDIR "/gst/elements");
_gst_plugin_paths = g_list_prepend (_gst_plugin_paths,
PLUGINS_SRCDIR "/gst/types");
_gst_plugin_paths = g_list_prepend (_gst_plugin_paths,
PLUGINS_SRCDIR "/gst/autoplug");
#endif /* PLUGINS_USE_SRCDIR */
doc = xmlParseFile (GST_CONFIG_DIR"/reg.xml");
@ -407,6 +409,8 @@ gst_plugin_new (const gchar *name)
plugin->numelements = 0;
plugin->types = NULL;
plugin->numtypes = 0;
plugin->autopluggers = NULL;
plugin->numautopluggers = 0;
plugin->loaded = TRUE;
return plugin;
@ -541,15 +545,7 @@ gst_plugin_find (const gchar *name)
return NULL;
}
/**
* gst_plugin_find_elementfactory:
* @name: name of elementfactory to find
*
* Find a registered elementfactory by name.
*
* Returns: @GstElementFactory if found, NULL if not
*/
GstElementFactory*
static GstElementFactory*
gst_plugin_find_elementfactory (const gchar *name)
{
GList *plugins, *factories;
@ -621,6 +617,77 @@ gst_plugin_load_elementfactory (const gchar *name)
return factory;
}
static GstAutoplugFactory*
gst_plugin_find_autoplugfactory (const gchar *name)
{
GList *plugins, *factories;
GstAutoplugFactory *factory;
g_return_val_if_fail(name != NULL, NULL);
plugins = _gst_plugins;
while (plugins) {
factories = ((GstPlugin *)(plugins->data))->autopluggers;
while (factories) {
factory = (GstAutoplugFactory*)(factories->data);
if (!strcmp(factory->name, name))
return (GstAutoplugFactory*)(factory);
factories = g_list_next(factories);
}
plugins = g_list_next(plugins);
}
return NULL;
}
/**
* gst_plugin_load_autoplugfactory:
* @name: name of autoplugfactory to load
*
* Load a registered autoplugfactory by name.
*
* Returns: @GstAutoplugFactory if loaded, NULL if not
*/
GstAutoplugFactory*
gst_plugin_load_autoplugfactory (const gchar *name)
{
GList *plugins, *factories;
GstAutoplugFactory *factory = NULL;
GstPlugin *plugin;
g_return_val_if_fail(name != NULL, NULL);
plugins = _gst_plugins;
while (plugins) {
plugin = (GstPlugin *)plugins->data;
factories = plugin->autopluggers;
while (factories) {
factory = (GstAutoplugFactory*)(factories->data);
if (!strcmp(factory->name,name)) {
if (!plugin->loaded) {
gchar *filename = g_strdup (plugin->filename);
gchar *pluginname = g_strdup (plugin->name);
GST_INFO (GST_CAT_PLUGIN_LOADING,"loaded autoplugfactory %s from plugin %s",name,plugin->name);
gst_plugin_remove(plugin);
if (!gst_plugin_load_absolute(filename)) {
GST_DEBUG (0,"gstplugin: error loading autoplug factory %s from plugin %s\n", name, pluginname);
}
g_free (pluginname);
g_free (filename);
}
factory = gst_plugin_find_autoplugfactory(name);
return factory;
}
factories = g_list_next(factories);
}
plugins = g_list_next(plugins);
}
return factory;
}
/**
* gst_plugin_load_typefactory:
* @mime: name of typefactory to load
@ -708,6 +775,24 @@ gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory)
gst_type_register (factory);
}
/**
* gst_plugin_add_type:
* @plugin: plugin to add type to
* @factory: the typefactory to add
*
* Add a typefactory to the list of those provided by the plugin.
*/
void
gst_plugin_add_autoplugger (GstPlugin *plugin, GstAutoplugFactory *factory)
{
g_return_if_fail (plugin != NULL);
g_return_if_fail (factory != NULL);
// g_print("adding factory to plugin\n");
plugin->autopluggers = g_list_prepend (plugin->autopluggers, factory);
plugin->numautopluggers++;
}
/**
* gst_plugin_get_list:
*
@ -716,7 +801,7 @@ gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory)
* Returns; a GList of GstPlugin elements
*/
GList*
gst_plugin_get_list(void)
gst_plugin_get_list (void)
{
return _gst_plugins;
}
@ -733,34 +818,45 @@ xmlNodePtr
gst_plugin_save_thyself (xmlNodePtr parent)
{
xmlNodePtr tree, subtree;
GList *plugins = NULL, *elements = NULL, *types = NULL;
GList *plugins = NULL, *elements = NULL, *types = NULL, *autopluggers = NULL;
plugins = gst_plugin_get_list();
plugins = gst_plugin_get_list ();
while (plugins) {
GstPlugin *plugin = (GstPlugin *)plugins->data;
tree = xmlNewChild(parent,NULL,"plugin",NULL);
xmlNewChild(tree,NULL,"name",plugin->name);
xmlNewChild(tree,NULL,"longname",plugin->longname);
xmlNewChild(tree,NULL,"filename",plugin->filename);
tree = xmlNewChild (parent, NULL, "plugin", NULL);
xmlNewChild (tree, NULL, "name", plugin->name);
xmlNewChild (tree, NULL, "longname", plugin->longname);
xmlNewChild (tree, NULL, "filename", plugin->filename);
types = plugin->types;
while (types) {
GstTypeFactory *factory = (GstTypeFactory *)types->data;
subtree = xmlNewChild(tree,NULL,"typefactory",NULL);
subtree = xmlNewChild(tree, NULL, "typefactory", NULL);
gst_typefactory_save_thyself(factory, subtree);
gst_typefactory_save_thyself (factory, subtree);
types = g_list_next(types);
types = g_list_next (types);
}
elements = plugin->elements;
while (elements) {
GstElementFactory *factory = (GstElementFactory *)elements->data;
subtree = xmlNewChild(tree,NULL,"elementfactory",NULL);
subtree = xmlNewChild (tree, NULL, "elementfactory", NULL);
gst_elementfactory_save_thyself(factory, subtree);
gst_elementfactory_save_thyself (factory, subtree);
elements = g_list_next(elements);
elements = g_list_next (elements);
}
plugins = g_list_next(plugins);
autopluggers = plugin->autopluggers;
while (autopluggers) {
GstAutoplugFactory *factory = (GstAutoplugFactory *)autopluggers->data;
subtree = xmlNewChild (tree, NULL, "autoplugfactory", NULL);
gst_autoplugfactory_save_thyself (factory, subtree);
autopluggers = g_list_next (autopluggers);
}
plugins = g_list_next (plugins);
}
return parent;
}
@ -776,43 +872,50 @@ gst_plugin_load_thyself (xmlNodePtr parent)
{
xmlNodePtr kinderen;
gint elementcount = 0;
gint autoplugcount = 0;
gint typecount = 0;
gchar *pluginname;
kinderen = parent->xmlChildrenNode; // Dutch invasion :-)
while (kinderen) {
if (!strcmp(kinderen->name, "plugin")) {
if (!strcmp (kinderen->name, "plugin")) {
xmlNodePtr field = kinderen->xmlChildrenNode;
GstPlugin *plugin = g_new0 (GstPlugin, 1);
plugin->elements = NULL;
plugin->types = NULL;
plugin->loaded = FALSE;
while (field) {
if (!strcmp(field->name, "name")) {
pluginname = xmlNodeGetContent(field);
if (gst_plugin_find(pluginname)) {
g_free(pluginname);
g_free(plugin);
if (!strcmp (field->name, "name")) {
pluginname = xmlNodeGetContent (field);
if (gst_plugin_find (pluginname)) {
g_free (pluginname);
g_free (plugin);
plugin = NULL;
break;
} else {
plugin->name = pluginname;
}
}
else if (!strcmp(field->name, "longname")) {
plugin->longname = xmlNodeGetContent(field);
else if (!strcmp (field->name, "longname")) {
plugin->longname = xmlNodeGetContent (field);
}
else if (!strcmp(field->name, "filename")) {
plugin->filename = xmlNodeGetContent(field);
else if (!strcmp (field->name, "filename")) {
plugin->filename = xmlNodeGetContent (field);
}
else if (!strcmp(field->name, "elementfactory")) {
GstElementFactory *factory = gst_elementfactory_load_thyself(field);
else if (!strcmp (field->name, "elementfactory")) {
GstElementFactory *factory = gst_elementfactory_load_thyself (field);
gst_plugin_add_factory (plugin, factory);
elementcount++;
}
else if (!strcmp(field->name, "typefactory")) {
GstTypeFactory *factory = gst_typefactory_load_thyself(field);
else if (!strcmp (field->name, "autoplugfactory")) {
GstAutoplugFactory *factory = gst_autoplugfactory_load_thyself (field);
gst_plugin_add_autoplugger (plugin, factory);
autoplugcount++;
}
else if (!strcmp (field->name, "typefactory")) {
GstTypeFactory *factory = gst_typefactory_load_thyself (field);
gst_plugin_add_type (plugin, factory);
elementcount++;
typecount++;
@ -822,13 +925,14 @@ gst_plugin_load_thyself (xmlNodePtr parent)
}
if (plugin) {
_gst_plugins = g_list_prepend(_gst_plugins, plugin);
_gst_plugins = g_list_prepend (_gst_plugins, plugin);
}
}
kinderen = kinderen->next;
}
GST_INFO (GST_CAT_PLUGIN_LOADING,"added %d registered factories and %d types",elementcount,typecount);
GST_INFO (GST_CAT_PLUGIN_LOADING, "added %d registered factories, %d autopluggers and %d types",
elementcount, autoplugcount, typecount);
}
@ -863,3 +967,19 @@ gst_plugin_get_type_list (GstPlugin *plugin)
return plugin->types;
}
/**
* gst_plugin_get_autoplug_list:
* @plugin: the plugin to get the autoplugfactories from
*
* get a list of all the autoplugfactories that this plugin provides
*
* Returns: a GList of factories
*/
GList*
gst_plugin_get_autoplug_list (GstPlugin *plugin)
{
g_return_val_if_fail (plugin != NULL, NULL);
return plugin->autopluggers;
}

View file

@ -36,10 +36,11 @@
#include <gst/gsttype.h>
#include <gst/gstelement.h>
#include <gst/gstautoplug.h>
typedef struct _GstPlugin GstPlugin;
typedef struct _GstPluginElement GstPluginElement;
typedef struct _GstPlugin GstPlugin;
typedef struct _GstPluginElement GstPluginElement;
struct _GstPlugin {
gchar *name; /* name of the plugin */
@ -50,6 +51,8 @@ struct _GstPlugin {
gint numtypes;
GList *elements; /* list of elements provided */
gint numelements;
GList *autopluggers; /* list of autopluggers provided */
gint numautopluggers;
gboolean loaded; /* if the plugin is in memory */
};
@ -57,40 +60,41 @@ struct _GstPlugin {
typedef GstPlugin* (*GstPluginInitFunc) (GModule *module);
void _gst_plugin_initialize (void);
void _gst_plugin_initialize (void);
GstPlugin* gst_plugin_new (const gchar *name);
void gst_plugin_add_path (const gchar *path);
const gchar* gst_plugin_get_name (GstPlugin *plugin);
void gst_plugin_set_name (GstPlugin *plugin, const gchar *name);
void gst_plugin_set_name (GstPlugin *plugin, const gchar *name);
const gchar* gst_plugin_get_longname (GstPlugin *plugin);
void gst_plugin_set_longname (GstPlugin *plugin, const gchar *longname);
void gst_plugin_set_longname (GstPlugin *plugin, const gchar *longname);
const gchar* gst_plugin_get_filename (GstPlugin *plugin);
gboolean gst_plugin_is_loaded (GstPlugin *plugin);
gboolean gst_plugin_is_loaded (GstPlugin *plugin);
GList* gst_plugin_get_type_list (GstPlugin *plugin);
GList* gst_plugin_get_factory_list (GstPlugin *plugin);
GList* gst_plugin_get_autoplug_list (GstPlugin *plugin);
void gst_plugin_load_all (void);
gboolean gst_plugin_load (const gchar *name);
gboolean gst_plugin_load_absolute (const gchar *name);
gboolean gst_library_load (const gchar *name);
void gst_plugin_add_factory (GstPlugin *plugin, GstElementFactory *factory);
void gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory);
void gst_plugin_add_factory (GstPlugin *plugin, GstElementFactory *factory);
void gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory);
void gst_plugin_add_autoplugger (GstPlugin *plugin, GstAutoplugFactory *factory);
GstPlugin* gst_plugin_find (const gchar *name);
GList* gst_plugin_get_list (void);
GstElementFactory* gst_plugin_find_elementfactory (const gchar *name);
GstElementFactory* gst_plugin_load_elementfactory (const gchar *name);
void gst_plugin_load_typefactory (const gchar *mime);
void gst_plugin_load_typefactory (const gchar *mime);
GstAutoplugFactory* gst_plugin_load_autoplugfactory (const gchar *name);
xmlNodePtr gst_plugin_save_thyself (xmlNodePtr parent);
void gst_plugin_load_thyself (xmlNodePtr parent);
xmlNodePtr gst_plugin_save_thyself (xmlNodePtr parent);
void gst_plugin_load_thyself (xmlNodePtr parent);
#endif /* __GST_PLUGIN_H__ */

View file

@ -601,6 +601,10 @@ gst_props_load_thyself_func (xmlNodePtr field)
sscanf (prop, "%08x", &entry->data.fourcc_data);
g_free (prop);
}
else {
g_free (entry);
entry = NULL;
}
return entry;
}
@ -634,7 +638,8 @@ gst_props_load_thyself (xmlNodePtr parent)
while (subfield) {
GstPropsEntry *subentry = gst_props_load_thyself_func (subfield);
entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, subentry);
if (subentry)
entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, subentry);
subfield = subfield->next;
}

View file

@ -254,7 +254,7 @@ gst_thread_change_state (GstElement *element)
gst_thread_main_loop, thread);
// wait for it to 'spin up'
// gst_thread_wait_thread (thread);
//gst_thread_wait_thread (thread);
} else {
GST_INFO (GST_CAT_THREAD, "gstthread: NOT starting thread \"%s\"",
GST_ELEMENT_NAME (GST_ELEMENT (element)));

View file

@ -43,10 +43,10 @@ struct _GstTypeFindInfo {
GstPlugin *plugin; /* the plugin with this typefind function */
};
static GstCaps* gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv);
static GstCaps* gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv);
void
_gst_type_initialize (void)
void
_gst_type_initialize (void)
{
_gst_types = NULL;
_gst_maxtype = 1; /* type 0 is undefined */
@ -60,8 +60,8 @@ _gst_type_initialize (void)
*
* Returns: the new type id
*/
guint16
gst_type_register (GstTypeFactory *factory)
guint16
gst_type_register (GstTypeFactory *factory)
{
guint16 id;
GstType *type;
@ -70,16 +70,17 @@ gst_type_register (GstTypeFactory *factory)
// GST_INFO (GST_CAT_TYPES,"type register %s", factory->mime);
id = gst_type_find_by_mime (factory->mime);
if (!id) {
type = g_new0 (GstType, 1);
type->id = _gst_maxtype++;
type->mime = factory->mime;
type->exts = factory->exts;
_gst_types = g_list_prepend (_gst_types, type);
type->id = _gst_maxtype++;
type->mime = factory->mime;
type->exts = factory->exts;
_gst_types = g_list_prepend (_gst_types, type);
id = type->id;
GST_DEBUG (0,"gsttype: new mime type '%s', id %d\n", type->mime, type->id);
} else {
type = gst_type_find_by_id (id);
@ -96,8 +97,8 @@ gst_type_register (GstTypeFactory *factory)
return id;
}
static
guint16 gst_type_find_by_mime_func (const gchar *mime)
static
guint16 gst_type_find_by_mime_func (const gchar *mime)
{
GList *walk;
GstType *type;
@ -142,8 +143,8 @@ guint16 gst_type_find_by_mime_func (const gchar *mime)
*
* Returns: the type id
*/
guint16
gst_type_find_by_mime (const gchar *mime)
guint16
gst_type_find_by_mime (const gchar *mime)
{
return gst_type_find_by_mime_func (mime);
}
@ -156,8 +157,8 @@ gst_type_find_by_mime (const gchar *mime)
*
* Returns: the type id
*/
guint16
gst_type_find_by_ext (const gchar *ext)
guint16
gst_type_find_by_ext (const gchar *ext)
{
//FIXME
g_warning ("gsttype: find_by_ext not implemented");
@ -173,7 +174,7 @@ gst_type_find_by_ext (const gchar *ext)
* Returns: the type
*/
GstType*
gst_type_find_by_id (guint16 id)
gst_type_find_by_id (guint16 id)
{
GList *walk = _gst_types;
GstType *type;
@ -196,7 +197,7 @@ gst_type_find_by_id (guint16 id)
* Returns: a list of GstTypes
*/
GList*
gst_type_get_list (void)
gst_type_get_list (void)
{
return _gst_types;
}
@ -210,8 +211,8 @@ gst_type_get_list (void)
*
* Returns: the new xmlNodePtr
*/
xmlNodePtr
gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent)
xmlNodePtr
gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent)
{
xmlNewChild (parent, NULL, "mime", factory->mime);
if (factory->exts) {
@ -220,11 +221,11 @@ gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent)
if (factory->typefindfunc) {
xmlNewChild (parent, NULL, "typefind", NULL);
}
return parent;
}
static GstCaps *
static GstCaps *
gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv)
{
GstType *type = (GstType *)priv;
@ -263,7 +264,7 @@ gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv)
* Returns: the new typefactory
*/
GstTypeFactory*
gst_typefactory_load_thyself (xmlNodePtr parent)
gst_typefactory_load_thyself (xmlNodePtr parent)
{
GstTypeFactory *factory = g_new0 (GstTypeFactory, 1);

View file

@ -52,14 +52,14 @@ struct _GstTypeFactory {
/* initialize the subsystem */
void _gst_type_initialize (void);
void _gst_type_initialize (void);
/* create a new type, or find/merge an existing one */
guint16 gst_type_register (GstTypeFactory *factory);
guint16 gst_type_register (GstTypeFactory *factory);
/* look up a type by mime or extension */
guint16 gst_type_find_by_mime (const gchar *mime);
guint16 gst_type_find_by_ext (const gchar *ext);
guint16 gst_type_find_by_mime (const gchar *mime);
guint16 gst_type_find_by_ext (const gchar *ext);
/* get GstType by id */
GstType* gst_type_find_by_id (guint16 id);
@ -67,7 +67,7 @@ GstType* gst_type_find_by_id (guint16 id);
/* get the list of registered types (returns list of GstType!) */
GList* gst_type_get_list (void);
xmlNodePtr gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent);
xmlNodePtr gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent);
GstTypeFactory* gst_typefactory_load_thyself (xmlNodePtr parent);
#endif /* __GST_TYPE_H__ */

View file

@ -52,19 +52,20 @@ enum {
};
static void gst_typefind_class_init (GstTypeFindClass *klass);
static void gst_typefind_init (GstTypeFind *typefind);
static void gst_typefind_class_init (GstTypeFindClass *klass);
static void gst_typefind_init (GstTypeFind *typefind);
static void gst_typefind_set_arg (GtkObject *object, GtkArg *arg, guint id);
static void gst_typefind_get_arg (GtkObject *object, GtkArg *arg, guint id);
static void gst_typefind_set_arg (GtkObject *object, GtkArg *arg, guint id);
static void gst_typefind_get_arg (GtkObject *object, GtkArg *arg, guint id);
static void gst_typefind_chain (GstPad *pad, GstBuffer *buf);
static void gst_typefind_chain (GstPad *pad, GstBuffer *buf);
static GstElementClass *parent_class = NULL;
static guint gst_typefind_signals[LAST_SIGNAL] = { 0 };
GtkType
gst_typefind_get_type(void) {
gst_typefind_get_type (void)
{
static GtkType typefind_type = 0;
if (!typefind_type) {
@ -78,13 +79,13 @@ gst_typefind_get_type(void) {
(GtkArgGetFunc)gst_typefind_get_arg,
(GtkClassInitFunc)NULL,
};
typefind_type = gtk_type_unique(GST_TYPE_ELEMENT,&typefind_info);
typefind_type = gtk_type_unique (GST_TYPE_ELEMENT, &typefind_info);
}
return typefind_type;
}
static void
gst_typefind_class_init (GstTypeFindClass *klass)
gst_typefind_class_init (GstTypeFindClass *klass)
{
GtkObjectClass *gtkobject_class;
@ -107,22 +108,22 @@ gst_typefind_class_init (GstTypeFindClass *klass)
gtkobject_class->get_arg = gst_typefind_get_arg;
}
static void
gst_typefind_init (GstTypeFind *typefind)
static void
gst_typefind_init (GstTypeFind *typefind)
{
typefind->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
gst_element_add_pad (GST_ELEMENT (typefind), typefind->sinkpad);
gst_pad_set_chain_function (typefind->sinkpad, gst_typefind_chain);
}
static void
gst_typefind_set_arg (GtkObject *object, GtkArg *arg, guint id)
static void
gst_typefind_set_arg (GtkObject *object, GtkArg *arg, guint id)
{
GstTypeFind *typefind;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_TYPEFIND (object));
typefind = GST_TYPEFIND (object);
switch(id) {
@ -131,14 +132,14 @@ gst_typefind_set_arg (GtkObject *object, GtkArg *arg, guint id)
}
}
static void
gst_typefind_get_arg (GtkObject *object, GtkArg *arg, guint id)
static void
gst_typefind_get_arg (GtkObject *object, GtkArg *arg, guint id)
{
GstTypeFind *typefind;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_TYPEFIND (object));
typefind = GST_TYPEFIND (object);
switch(id) {
@ -150,8 +151,8 @@ gst_typefind_get_arg (GtkObject *object, GtkArg *arg, guint id)
}
}
static void
gst_typefind_chain (GstPad *pad, GstBuffer *buf)
static void
gst_typefind_chain (GstPad *pad, GstBuffer *buf)
{
GstTypeFind *typefind;
GList *type_list;

View file

@ -41,8 +41,8 @@ enum {
static GtkObject *parent_class = NULL;
static guint gst_play_signals[LAST_SIGNAL] = { 0 };
GtkType
gst_play_get_type (void)
GtkType
gst_play_get_type (void)
{
static GtkType play_type = 0;
@ -62,8 +62,8 @@ gst_play_get_type (void)
return play_type;
}
static void
gst_play_class_init (GstPlayClass *klass)
static void
gst_play_class_init (GstPlayClass *klass)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
@ -108,14 +108,13 @@ gst_play_class_init (GstPlayClass *klass)
object_class->set_arg = gst_play_set_arg;
object_class->get_arg = gst_play_get_arg;
widget_class->realize = gst_play_realize;
widget_class->realize = gst_play_realize;
}
static void
gst_play_init (GstPlay *play)
static void
gst_play_init (GstPlay *play)
{
GstPlayPrivate *priv = g_new0 (GstPlayPrivate, 1);
play->priv = priv;
@ -123,25 +122,20 @@ gst_play_init (GstPlay *play)
/* create a new bin to hold the elements */
priv->thread = gst_thread_new ("main_thread");
g_assert (priv->thread != NULL);
priv->pipeline = gst_pipeline_new ("main_pipeline");
g_assert (priv->pipeline != NULL);
priv->bin = gst_bin_new ("main_bin");
g_assert (priv->bin != NULL);
/* and an audio sink */
priv->audio_play = gst_elementfactory_make ("audiosink","play_audio");
g_return_if_fail (priv->audio_play != NULL);
gtk_signal_connect (GTK_OBJECT (priv->audio_play), "handoff",
priv->audio_element = gst_elementfactory_make ("audiosink", "play_audio");
g_return_if_fail (priv->audio_element != NULL);
gtk_signal_connect (GTK_OBJECT (priv->audio_element), "handoff",
GTK_SIGNAL_FUNC (gst_play_audio_handoff), play);
/* and a video sink */
priv->video_show = gst_elementfactory_make ("videosink","show");
g_return_if_fail (priv->video_show != NULL);
gtk_object_set (GTK_OBJECT (priv->video_show),"xv_enabled",FALSE,NULL);
gtk_signal_connect (GTK_OBJECT (priv->video_show), "frame_displayed",
priv->video_element = gst_elementfactory_make ("videosink", "show");
g_return_if_fail (priv->video_element != NULL);
gtk_object_set (GTK_OBJECT (priv->video_element), "xv_enabled", FALSE, NULL);
gtk_signal_connect (GTK_OBJECT (priv->video_element), "frame_displayed",
GTK_SIGNAL_FUNC (gst_play_frame_displayed), play);
gst_pipeline_add_sink (GST_PIPELINE (priv->pipeline), priv->audio_play);
gst_pipeline_add_sink (GST_PIPELINE (priv->pipeline), priv->video_show);
play->state = GST_PLAY_STOPPED;
play->flags = 0;
@ -155,155 +149,258 @@ gst_play_init (GstPlay *play)
}
GstPlay *
gst_play_new ()
gst_play_new ()
{
return GST_PLAY (gtk_type_new (GST_TYPE_PLAY));
}
static void
gst_play_eos (GstElement *element,
GstPlay *play)
static void
gst_play_eos (GstElement *element,
GstPlay *play)
{
g_print("gstplay: eos reached\n");
gst_play_stop(play);
}
static void
gst_play_frame_displayed (GstElement *element,
GstPlay *play)
static void
gst_play_frame_displayed (GstElement *element,
GstPlay *play)
{
GstPlayPrivate *priv;
priv = (GstPlayPrivate *)play->priv;
gdk_threads_enter ();
gtk_widget_show (GTK_WIDGET (priv->video_widget));
gdk_threads_leave ();
gtk_signal_emit (GTK_OBJECT (play), gst_play_signals[SIGNAL_FRAME_DISPLAYED],
NULL);
}
static void
gst_play_audio_handoff (GstElement *element,
GstPlay *play)
static void
gst_play_audio_handoff (GstElement *element,
GstPlay *play)
{
gtk_signal_emit (GTK_OBJECT (play), gst_play_signals[SIGNAL_AUDIO_PLAYED],
NULL);
}
static void
gst_play_object_introspect (GstElement *element,
static void
gst_play_object_introspect (GstObject *object,
const gchar *property,
GstElement **target)
{
gchar *info;
GtkArgInfo *arg;
GstElement *element;
info = gtk_object_arg_get_info( GTK_OBJECT_TYPE(element), property, &arg);
if (!GST_IS_ELEMENT (object))
return;
element = GST_ELEMENT (object);
info = gtk_object_arg_get_info (GTK_OBJECT_TYPE (element), property, &arg);
if (info) {
g_free(info);
}
else {
*target = element;
g_print("gstplay: using element \"%s\" for %s property\n",
g_print("gstplay: using element \"%s\" for %s property\n",
gst_element_get_name(element), property);
}
}
/* Dumb introspection of the interface...
* this will change with glib 1.4
* this will change with glib 1.4
* */
static void
gst_play_object_added (GstElement *pipeline,
GstElement *element,
GstPlay *play)
static void
gst_play_object_added (GstAutoplug* autoplug,
GstObject *object,
GstPlay *play)
{
GstPlayPrivate *priv;
g_return_if_fail (play != NULL);
priv = (GstPlayPrivate *)play->priv;
if (GST_FLAG_IS_SET (element, GST_ELEMENT_NO_SEEK)) {
if (GST_FLAG_IS_SET (object, GST_ELEMENT_NO_SEEK)) {
priv->can_seek = FALSE;
}
if (GST_IS_BIN (element)) {
gtk_signal_connect (GTK_OBJECT (element), "object_added", gst_play_object_added, play);
if (GST_IS_BIN (object)) {
//gtk_signal_connect (GTK_OBJECT (object), "object_added", gst_play_object_added, play);
}
else {
// first come first serve here...
if (!priv->offset_element)
gst_play_object_introspect (element, "offset", &priv->offset_element);
if (!priv->bit_rate_element)
gst_play_object_introspect (element, "bit_rate", &priv->bit_rate_element);
if (!priv->offset_element)
gst_play_object_introspect (object, "offset", &priv->offset_element);
if (!priv->bit_rate_element)
gst_play_object_introspect (object, "bit_rate", &priv->bit_rate_element);
if (!priv->media_time_element)
gst_play_object_introspect (element, "media_time", &priv->media_time_element);
gst_play_object_introspect (object, "media_time", &priv->media_time_element);
if (!priv->current_time_element)
gst_play_object_introspect (element, "current_time", &priv->current_time_element);
gst_play_object_introspect (object, "current_time", &priv->current_time_element);
}
}
GstPlayReturn
gst_play_set_uri (GstPlay *play,
const guchar *uri)
static void
gst_play_have_type (GstElement *sink, GstElement *sink2, gpointer data)
{
GST_DEBUG (0,"GstPipeline: play have type %p\n", (gboolean *)data);
*(gboolean *)data = TRUE;
}
static GstCaps*
gst_play_typefind (GstBin *bin, GstElement *element)
{
gboolean found = FALSE;
GstElement *typefind;
GstCaps *caps = NULL;
GST_DEBUG (0,"GstPipeline: typefind for element \"%s\" %p\n",
GST_ELEMENT_NAME(element), &found);
typefind = gst_elementfactory_make ("typefind", "typefind");
g_return_val_if_fail (typefind != NULL, FALSE);
gtk_signal_connect (GTK_OBJECT (typefind), "have_type",
GTK_SIGNAL_FUNC (gst_play_have_type), &found);
gst_pad_connect (gst_element_get_pad (element, "src"),
gst_element_get_pad (typefind, "sink"));
gst_bin_add (bin, typefind);
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
// push a buffer... the have_type signal handler will set the found flag
gst_bin_iterate (bin);
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
if (found) {
caps = gst_util_get_pointer_arg (GTK_OBJECT (typefind), "caps");
gst_pad_set_caps_list (gst_element_get_pad (element, "src"), g_list_prepend (NULL, caps));
}
gst_pad_disconnect (gst_element_get_pad (element, "src"),
gst_element_get_pad (typefind, "sink"));
gst_bin_remove (bin, typefind);
gst_object_unref (GST_OBJECT (typefind));
return caps;
}
static gboolean
connect_pads (GstElement *new_element, GstElement *target, gboolean add)
{
GList *pads = gst_element_get_pad_list (new_element);
GstPad *targetpad = gst_element_get_pad (target, "sink");
while (pads) {
GstPad *pad = GST_PAD (pads->data);
if (gst_pad_check_compatibility (pad, targetpad)) {
if (add) {
gst_bin_add (GST_BIN (gst_element_get_parent (
GST_ELEMENT (gst_pad_get_real_parent (pad)))),
target);
}
gst_pad_connect (pad, targetpad);
return TRUE;
}
pads = g_list_next (pads);
}
return FALSE;
}
GstPlayReturn
gst_play_set_uri (GstPlay *play,
const guchar *uri)
{
GstPlayPrivate *priv;
GstCaps *src_caps;
GstElement *new_element;
GstAutoplug *autoplug;
g_return_val_if_fail (play != NULL, GST_PLAY_ERROR);
g_return_val_if_fail (GST_IS_PLAY (play), GST_PLAY_ERROR);
g_return_val_if_fail (uri != NULL, GST_PLAY_ERROR);
priv = (GstPlayPrivate *)play->priv;
if (priv->src) {
}
if (priv->uri) g_free (priv->uri);
if (priv->uri)
g_free (priv->uri);
priv->uri = g_strdup (uri);
//priv->src = gst_elementfactory_make ("disksrc", "disk_src");
priv->src = gst_elementfactory_make ("disksrc", "disk_src");
//priv->src = gst_elementfactory_make ("dvdsrc", "disk_src");
priv->offset_element = priv->src;
g_return_val_if_fail (priv->src != NULL, -1);
gtk_object_set (GTK_OBJECT (priv->src),"location",uri,NULL);
gtk_signal_connect (GTK_OBJECT (priv->src), "eos", GTK_SIGNAL_FUNC (gst_play_eos), play);
gtk_object_set (GTK_OBJECT (priv->src), "location", uri, NULL);
gtk_signal_connect (GTK_OBJECT (priv->pipeline), "object_added", gst_play_object_added, play);
gst_bin_add (GST_BIN (priv->bin), priv->src);
gst_pipeline_add_src (GST_PIPELINE (priv->pipeline),GST_ELEMENT (priv->src));
src_caps = gst_play_typefind (GST_BIN (priv->bin), priv->src);
if (!gst_pipeline_autoplug (GST_PIPELINE (priv->pipeline))) {
if (!src_caps) {
return GST_PLAY_UNKNOWN_MEDIA;
}
if (GST_PAD_CONNECTED (gst_element_get_pad (priv->video_show, "sink"))) {
play->flags |= GST_PLAY_TYPE_VIDEO;
}
if (GST_PAD_CONNECTED (gst_element_get_pad (priv->audio_play, "sink"))) {
play->flags |= GST_PLAY_TYPE_AUDIO;
autoplug = gst_autoplugfactory_make ("staticrender");
g_assert (autoplug != NULL);
gtk_signal_connect (GTK_OBJECT (autoplug), "new_object", gst_play_object_added, play);
new_element = gst_autoplug_to_renderers (autoplug,
gst_pad_get_caps_list (gst_element_get_pad (priv->src, "src")),
priv->video_element,
priv->audio_element,
NULL);
if (!new_element) {
return GST_PLAY_CANNOT_PLAY;
}
// hmmmm hack? FIXME
GST_FLAG_UNSET (priv->pipeline, GST_BIN_FLAG_MANAGER);
gst_bin_remove (GST_BIN (priv->bin), priv->src);
gst_bin_add (GST_BIN (priv->thread), priv->src);
gst_bin_add (GST_BIN (priv->thread), priv->pipeline);
gst_bin_add (GST_BIN (priv->bin), new_element);
gst_element_connect (priv->src, "src", new_element, "sink");
gst_bin_add (GST_BIN (priv->thread), priv->bin);
gtk_signal_connect (GTK_OBJECT (priv->thread), "eos", GTK_SIGNAL_FUNC (gst_play_eos), play);
return GST_PLAY_OK;
}
static void
gst_play_realize (GtkWidget *widget)
static void
gst_play_realize (GtkWidget *widget)
{
GstPlay *play;
GtkWidget *video_widget;
GstPlayPrivate *priv;
g_return_if_fail (GST_IS_PLAY (widget));
g_print ("gst_play: realize\n");
play = GST_PLAY (widget);
priv = (GstPlayPrivate *)play->priv;
video_widget = gst_util_get_widget_arg (GTK_OBJECT (priv->video_show),"widget");
priv->video_widget = gst_util_get_widget_arg (GTK_OBJECT (priv->video_element), "widget");
if (video_widget) {
gtk_container_add (GTK_CONTAINER (widget), video_widget);
gtk_widget_show (video_widget);
if (priv->video_widget) {
gtk_container_add (GTK_CONTAINER (widget), priv->video_widget);
}
else {
g_print ("oops, no video widget found\n");
}
if (GTK_WIDGET_CLASS (parent_class)->realize) {
@ -311,8 +408,8 @@ gst_play_realize (GtkWidget *widget)
}
}
void
gst_play_play (GstPlay *play)
void
gst_play_play (GstPlay *play)
{
GstPlayPrivate *priv;
@ -333,8 +430,8 @@ gst_play_play (GstPlay *play)
play->state);
}
void
gst_play_pause (GstPlay *play)
void
gst_play_pause (GstPlay *play)
{
GstPlayPrivate *priv;
@ -353,8 +450,8 @@ gst_play_pause (GstPlay *play)
play->state);
}
void
gst_play_stop (GstPlay *play)
void
gst_play_stop (GstPlay *play)
{
GstPlayPrivate *priv;
@ -374,8 +471,8 @@ gst_play_stop (GstPlay *play)
play->state);
}
gulong
gst_play_get_media_size (GstPlay *play)
gulong
gst_play_get_media_size (GstPlay *play)
{
GstPlayPrivate *priv;
@ -387,7 +484,7 @@ gst_play_get_media_size (GstPlay *play)
return gst_util_get_long_arg (GTK_OBJECT (priv->src), "size");
}
gulong
gulong
gst_play_get_media_offset (GstPlay *play)
{
GstPlayPrivate *priv;
@ -397,15 +494,18 @@ gst_play_get_media_offset (GstPlay *play)
priv = (GstPlayPrivate *)play->priv;
return gst_util_get_long_arg (GTK_OBJECT (priv->offset_element), "offset");
if (priv->offset_element)
return gst_util_get_long_arg (GTK_OBJECT (priv->offset_element), "offset");
else
return 0;
}
gulong
gulong
gst_play_get_media_total_time (GstPlay *play)
{
gulong total_time, bit_rate;
GstPlayPrivate *priv;
g_return_val_if_fail (play != NULL, 0);
g_return_val_if_fail (GST_IS_PLAY (play), 0);
@ -419,7 +519,7 @@ gst_play_get_media_total_time (GstPlay *play)
bit_rate = gst_util_get_long_arg (GTK_OBJECT (priv->bit_rate_element), "bit_rate");
if (bit_rate)
if (bit_rate)
total_time = (gst_play_get_media_size (play) * 8) / bit_rate;
else
total_time = 0;
@ -427,12 +527,12 @@ gst_play_get_media_total_time (GstPlay *play)
return total_time;
}
gulong
gulong
gst_play_get_media_current_time (GstPlay *play)
{
gulong current_time, bit_rate;
GstPlayPrivate *priv;
g_return_val_if_fail (play != NULL, 0);
g_return_val_if_fail (GST_IS_PLAY (play), 0);
@ -446,7 +546,7 @@ gst_play_get_media_current_time (GstPlay *play)
bit_rate = gst_util_get_long_arg (GTK_OBJECT (priv->bit_rate_element), "bit_rate");
if (bit_rate)
if (bit_rate)
current_time = (gst_play_get_media_offset (play) * 8) / bit_rate;
else
current_time = 0;
@ -454,7 +554,7 @@ gst_play_get_media_current_time (GstPlay *play)
return current_time;
}
gboolean
gboolean
gst_play_media_can_seek (GstPlay *play)
{
GstPlayPrivate *priv;
@ -467,8 +567,8 @@ gst_play_media_can_seek (GstPlay *play)
return priv->can_seek;
}
void
gst_play_media_seek (GstPlay *play,
void
gst_play_media_seek (GstPlay *play,
gulong offset)
{
GstPlayPrivate *priv;
@ -482,10 +582,10 @@ gst_play_media_seek (GstPlay *play,
}
static void
static void
gst_play_set_arg (GtkObject *object,
GtkArg *arg,
guint id)
guint id)
{
GstPlay *play;
@ -503,10 +603,10 @@ gst_play_set_arg (GtkObject *object,
}
}
static void
static void
gst_play_get_arg (GtkObject *object,
GtkArg *arg,
guint id)
guint id)
{
GstPlay *play;
GstPlayPrivate *priv;

View file

@ -31,6 +31,7 @@ typedef enum {
typedef enum {
GST_PLAY_OK,
GST_PLAY_UNKNOWN_MEDIA,
GST_PLAY_CANNOT_PLAY,
GST_PLAY_ERROR,
} GstPlayReturn;

View file

@ -12,9 +12,9 @@ typedef struct _GstPlayPrivate GstPlayPrivate;
struct _GstPlayPrivate {
GstElement *thread;
GstElement *pipeline;
GstElement *audio_play;
GstElement *video_show;
GstElement *bin;
GstElement *video_element, *audio_element;
GtkWidget *video_widget;
GstElement *src;
guchar *uri;

View file

@ -2,7 +2,7 @@
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstdisksrc.c:
* gstdisksrc.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -56,23 +56,23 @@ enum {
};
static void gst_disksrc_class_init (GstDiskSrcClass *klass);
static void gst_disksrc_init (GstDiskSrc *disksrc);
static void gst_disksrc_class_init (GstDiskSrcClass *klass);
static void gst_disksrc_init (GstDiskSrc *disksrc);
static void gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id);
static void gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id);
static void gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id);
static void gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id);
static GstBuffer * gst_disksrc_get (GstPad *pad);
static GstBuffer * gst_disksrc_get_region (GstPad *pad,GstRegionType type,guint64 offset,guint64 len);
static GstElementStateReturn gst_disksrc_change_state (GstElement *element);
static GstElementStateReturn gst_disksrc_change_state (GstElement *element);
static GstElementClass *parent_class = NULL;
//static guint gst_disksrc_signals[LAST_SIGNAL] = { 0 };
GtkType
gst_disksrc_get_type(void)
gst_disksrc_get_type(void)
{
static GtkType disksrc_type = 0;
@ -93,7 +93,7 @@ gst_disksrc_get_type(void)
}
static void
gst_disksrc_class_init (GstDiskSrcClass *klass)
gst_disksrc_class_init (GstDiskSrcClass *klass)
{
GtkObjectClass *gtkobject_class;
GstElementClass *gstelement_class;
@ -118,8 +118,8 @@ gst_disksrc_class_init (GstDiskSrcClass *klass)
gstelement_class->change_state = gst_disksrc_change_state;
}
static void
gst_disksrc_init (GstDiskSrc *disksrc)
static void
gst_disksrc_init (GstDiskSrc *disksrc)
{
// GST_FLAG_SET (disksrc, GST_SRC_);
@ -139,14 +139,14 @@ gst_disksrc_init (GstDiskSrc *disksrc)
}
static void
gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id)
static void
gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id)
{
GstDiskSrc *src;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_DISKSRC (object));
src = GST_DISKSRC (object);
switch(id) {
@ -176,14 +176,14 @@ gst_disksrc_set_arg (GtkObject *object, GtkArg *arg, guint id)
}
}
static void
gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id)
static void
gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id)
{
GstDiskSrc *src;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_DISKSRC (object));
src = GST_DISKSRC (object);
switch (id) {
@ -212,7 +212,7 @@ gst_disksrc_get_arg (GtkObject *object, GtkArg *arg, guint id)
* Push a new buffer from the disksrc at the current offset.
*/
static GstBuffer *
gst_disksrc_get (GstPad *pad)
gst_disksrc_get (GstPad *pad)
{
GstDiskSrc *src;
GstBuffer *buf;
@ -223,7 +223,7 @@ gst_disksrc_get (GstPad *pad)
/* deal with EOF state */
if (src->curoffset >= src->size) {
gst_element_signal_eos (GST_ELEMENT (src));
gst_pad_set_eos (pad);
return NULL;
}
@ -269,7 +269,7 @@ gst_disksrc_get (GstPad *pad)
* Push a new buffer from the disksrc of given size at given offset.
*/
static GstBuffer *
gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len)
gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len)
{
GstDiskSrc *src;
GstBuffer *buf;
@ -281,10 +281,10 @@ gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 l
g_return_val_if_fail (GST_IS_DISKSRC (src), NULL);
g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN), NULL);
/* deal with EOF state */
if (offset >= src->size) {
gst_element_signal_eos (GST_ELEMENT (src));
gst_pad_set_eos (pad);
return NULL;
}
@ -312,8 +312,8 @@ gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 l
/* open the file and mmap it, necessary to go to READY state */
static
gboolean gst_disksrc_open_file (GstDiskSrc *src)
static
gboolean gst_disksrc_open_file (GstDiskSrc *src)
{
g_return_val_if_fail (!GST_FLAG_IS_SET (src ,GST_DISKSRC_OPEN), FALSE);
@ -343,8 +343,8 @@ gboolean gst_disksrc_open_file (GstDiskSrc *src)
}
/* unmap and close the file */
static void
gst_disksrc_close_file (GstDiskSrc *src)
static void
gst_disksrc_close_file (GstDiskSrc *src)
{
g_return_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN));
@ -365,8 +365,8 @@ gst_disksrc_close_file (GstDiskSrc *src)
}
static GstElementStateReturn
gst_disksrc_change_state (GstElement *element)
static GstElementStateReturn
gst_disksrc_change_state (GstElement *element)
{
g_return_val_if_fail (GST_IS_DISKSRC (element), GST_STATE_FAILURE);
@ -375,7 +375,7 @@ gst_disksrc_change_state (GstElement *element)
gst_disksrc_close_file (GST_DISKSRC (element));
} else {
if (!GST_FLAG_IS_SET (element, GST_DISKSRC_OPEN)) {
if (!gst_disksrc_open_file (GST_DISKSRC (element)))
if (!gst_disksrc_open_file (GST_DISKSRC (element)))
return GST_STATE_FAILURE;
}
}

View file

@ -2,7 +2,7 @@
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstelements.c:
* gstelements.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -61,13 +61,13 @@ static struct _elements_entry _elements[] = {
{ "tee", gst_tee_get_type, &gst_tee_details, gst_tee_factory_init },
#if HAVE_LIBGHTTP
{ "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details, NULL },
{ "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details, NULL },
#endif /* HAVE_LIBGHTTP */
{ NULL, 0 },
};
GstPlugin *plugin_init (GModule *module)
GstPlugin *plugin_init (GModule *module)
{
GstPlugin *plugin;
GstElementFactory *factory;

View file

@ -62,7 +62,6 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
// set up thread state and kick things off
gtk_object_set(GTK_OBJECT(audio_thread),"create_thread",TRUE,NULL);
g_print("setting to READY state\n");
gst_element_set_state(GST_ELEMENT(audio_thread),GST_STATE_READY);
} else if (strncmp(gst_pad_get_name(pad), "video_", 6) == 0) {
//} else if (0) {
@ -116,7 +115,6 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
// set up thread state and kick things off
gtk_object_set(GTK_OBJECT(video_thread),"create_thread",TRUE,NULL);
g_print("setting to READY state\n");
gst_element_set_state(GST_ELEMENT(video_thread),GST_STATE_READY);
}
g_print("\n");
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);

4
tests/.gitignore vendored
View file

@ -6,7 +6,7 @@ Makefile.in
.deps
.libs
*.xml
*.gst
init
loadall
simplefake
@ -24,3 +24,5 @@ markup
load
padfactory
tee
autoplug2
autoplug3

View file

@ -1,7 +1,7 @@
SUBDIRS = sched eos
noinst_PROGRAMS = init loadall simplefake states caps queue registry \
paranoia rip mp3encode autoplug props case4 markup load tee
paranoia rip mp3encode autoplug props case4 markup load tee autoplug2 autoplug3
# we have nothing but apps here, we can do this safely
LIBS += $(GST_LIBS)

View file

@ -1,63 +1,45 @@
#include <gst/gst.h>
static GList*
autoplug_caps (gchar *mime1, gchar *mime2)
{
GstCaps *caps1, *caps2;
caps1 = gst_caps_new ("tescaps1", mime1);
caps2 = gst_caps_new ("tescaps2", mime2);
return gst_autoplug_caps (caps1, caps2);
}
static void
dump_factories (GList *factories)
new_object_added (GstAutoplug *autoplug, GstObject *object)
{
g_print ("dumping factories\n");
while (factories) {
GstElementFactory *factory = (GstElementFactory *)factories->data;
g_print ("factory: \"%s\"\n", factory->name);
factories = g_list_next (factories);
}
g_print ("added new object \"%s\"\n", gst_object_get_name (object));
}
int main(int argc,char *argv[])
int
main (int argc, char *argv[])
{
GList *factories;
GstElement *element;
GstElement *videosink, *audiosink;
GstAutoplug *autoplugger;
GList *testcaps;
gst_init(&argc,&argv);
factories = autoplug_caps ("audio/mp3", "audio/raw");
dump_factories (factories);
audiosink = gst_elementfactory_make ("audiosink", "audiosink");
g_assert (audiosink != NULL);
videosink = gst_elementfactory_make ("videosink", "videosink");
g_assert (videosink != NULL);
factories = autoplug_caps ("video/mpeg", "audio/raw");
dump_factories (factories);
testcaps = g_list_append (NULL,
gst_caps_new_with_props ("test_caps",
"video/mpeg",
gst_props_new (
"mpegversion", GST_PROPS_INT (1),
"systemstream", GST_PROPS_BOOLEAN (TRUE),
NULL)));
factories = gst_autoplug_caps (
gst_caps_new_with_props(
"testcaps3",
"video/mpeg",
gst_props_new (
"mpegversion", GST_PROPS_INT (1),
"systemstream", GST_PROPS_BOOLEAN (TRUE),
NULL)),
gst_caps_new("testcaps4","audio/raw"));
dump_factories (factories);
autoplugger = gst_autoplugfactory_make ("static");
factories = gst_autoplug_caps (
gst_caps_new_with_props(
"testcaps5",
"video/mpeg",
gst_props_new (
"mpegversion", GST_PROPS_INT (1),
"systemstream", GST_PROPS_BOOLEAN (FALSE),
NULL)),
gst_caps_new("testcaps6", "video/raw"));
dump_factories (factories);
gtk_signal_connect (GTK_OBJECT (autoplugger), "new_object", new_object_added, NULL);
element = gst_autoplug_to_caps (autoplugger, testcaps,
gst_pad_get_caps_list (gst_element_get_pad (audiosink, "sink")),
gst_pad_get_caps_list (gst_element_get_pad (videosink, "sink")),
NULL);
g_assert (element != NULL);
xmlDocDump (stdout, gst_xml_write (element));
exit (0);
}

78
tests/autoplug2.c Normal file
View file

@ -0,0 +1,78 @@
#include <gst/gst.h>
static GstElement*
autoplug_caps (GstAutoplug *autoplug, gchar *mime1, gchar *mime2)
{
GList *caps1, *caps2;
caps1 = g_list_append (NULL, gst_caps_new ("tescaps1", mime1));
caps2 = g_list_append (NULL, gst_caps_new ("tescaps2", mime2));
return gst_autoplug_to_caps (autoplug, caps1, caps2, NULL);
}
int
main (int argc, char *argv[])
{
GstElement *element;
GstAutoplug *autoplug;
gst_init(&argc,&argv);
autoplug = gst_autoplugfactory_make ("static");
element = autoplug_caps (autoplug, "audio/mp3", "audio/raw");
xmlSaveFile ("autoplug2_1.gst", gst_xml_write (element));
element = autoplug_caps (autoplug, "video/mpeg", "audio/raw");
xmlSaveFile ("autoplug2_2.gst", gst_xml_write (element));
element = gst_autoplug_to_caps (autoplug,
g_list_append (NULL, gst_caps_new_with_props(
"testcaps3",
"video/mpeg",
gst_props_new (
"mpegversion", GST_PROPS_INT (1),
"systemstream", GST_PROPS_BOOLEAN (TRUE),
NULL))),
g_list_append (NULL, gst_caps_new("testcaps4","audio/raw")),
NULL);
xmlSaveFile ("autoplug2_3.gst", gst_xml_write (element));
element = gst_autoplug_to_caps (autoplug,
g_list_append (NULL, gst_caps_new_with_props(
"testcaps5",
"video/mpeg",
gst_props_new (
"mpegversion", GST_PROPS_INT (1),
"systemstream", GST_PROPS_BOOLEAN (FALSE),
NULL))),
g_list_append (NULL, gst_caps_new("testcaps6", "video/raw")),
NULL);
xmlSaveFile ("autoplug2_4.gst", gst_xml_write (element));
element = gst_autoplug_to_caps (autoplug,
g_list_append (NULL, gst_caps_new(
"testcaps7",
"video/avi")),
g_list_append (NULL, gst_caps_new("testcaps8", "video/raw")),
g_list_append (NULL, gst_caps_new("testcaps9", "audio/raw")),
NULL);
xmlSaveFile ("autoplug2_5.gst", gst_xml_write (element));
element = gst_autoplug_to_caps (autoplug,
g_list_append (NULL, gst_caps_new_with_props(
"testcaps10",
"video/mpeg",
gst_props_new (
"mpegversion", GST_PROPS_INT (1),
"systemstream", GST_PROPS_BOOLEAN (TRUE),
NULL))),
g_list_append (NULL, gst_caps_new("testcaps10", "video/raw")),
g_list_append (NULL, gst_caps_new("testcaps11", "audio/raw")),
NULL);
xmlSaveFile ("autoplug2_6.gst", gst_xml_write (element));
exit (0);
exit (0);
}

102
tests/autoplug3.c Normal file
View file

@ -0,0 +1,102 @@
#include <gst/gst.h>
int
main (int argc, char *argv[])
{
GstElement *element;
GstElement *sink1, *sink2;
GstAutoplug *autoplug;
GstAutoplug *autoplug2;
gst_init(&argc,&argv);
sink1 = gst_elementfactory_make ("videosink", "videosink");
sink2 = gst_elementfactory_make ("audiosink", "audiosink");
autoplug = gst_autoplugfactory_make ("staticrender");
autoplug2 = gst_autoplugfactory_make ("static");
element = gst_autoplug_to_renderers (autoplug,
g_list_append (NULL, gst_caps_new ("mp3caps", "audio/mp3")), sink2, NULL);
xmlSaveFile ("autoplug3_1.gst", gst_xml_write (element));
element = gst_autoplug_to_renderers (autoplug,
g_list_append (NULL, gst_caps_new ("mpeg1caps", "video/mpeg")), sink1, NULL);
if (element) {
xmlSaveFile ("autoplug3_2.gst", gst_xml_write (element));
}
element = gst_autoplug_to_caps (autoplug2,
g_list_append (NULL, gst_caps_new_with_props(
"testcaps3",
"video/mpeg",
gst_props_new (
"mpegversion", GST_PROPS_INT (1),
"systemstream", GST_PROPS_BOOLEAN (TRUE),
NULL))),
g_list_append (NULL, gst_caps_new("testcaps4","audio/raw")),
NULL);
if (element) {
xmlSaveFile ("autoplug3_3.gst", gst_xml_write (element));
}
element = gst_autoplug_to_caps (autoplug2,
g_list_append (NULL, gst_caps_new_with_props(
"testcaps5",
"video/mpeg",
gst_props_new (
"mpegversion", GST_PROPS_INT (1),
"systemstream", GST_PROPS_BOOLEAN (FALSE),
NULL))),
g_list_append (NULL, gst_caps_new("testcaps6", "video/raw")),
NULL);
if (element) {
xmlSaveFile ("autoplug3_4.gst", gst_xml_write (element));
}
element = gst_autoplug_to_caps (autoplug2,
g_list_append (NULL, gst_caps_new(
"testcaps7",
"video/avi")),
g_list_append (NULL, gst_caps_new("testcaps8", "video/raw")),
g_list_append (NULL, gst_caps_new("testcaps9", "audio/raw")),
NULL);
if (element) {
xmlSaveFile ("autoplug3_5.gst", gst_xml_write (element));
}
element = gst_autoplug_to_caps (autoplug2,
g_list_append (NULL, gst_caps_new_with_props(
"testcaps10",
"video/mpeg",
gst_props_new (
"mpegversion", GST_PROPS_INT (1),
"systemstream", GST_PROPS_BOOLEAN (TRUE),
NULL))),
g_list_append (NULL, gst_caps_new("testcaps10", "video/raw")),
g_list_append (NULL, gst_caps_new("testcaps11", "audio/raw")),
NULL);
if (element) {
xmlSaveFile ("autoplug3_6.gst", gst_xml_write (element));
}
sink1 = gst_elementfactory_make ("videosink", "videosink");
sink2 = gst_elementfactory_make ("audiosink", "audiosink");
element = gst_autoplug_to_renderers (autoplug,
g_list_append (NULL, gst_caps_new_with_props(
"testcaps10",
"video/mpeg",
gst_props_new (
"mpegversion", GST_PROPS_INT (1),
"systemstream", GST_PROPS_BOOLEAN (TRUE),
NULL))),
sink1,
sink2,
NULL);
if (element) {
xmlSaveFile ("autoplug3_7.gst", gst_xml_write (element));
}
exit (0);
}

View file

@ -31,8 +31,6 @@ int main(int argc,char *argv[])
exit(-1);
}
/* create a new bin to hold the elements */
pipeline = gst_pipeline_new("pipeline");
g_assert(pipeline != NULL);
@ -59,6 +57,7 @@ int main(int argc,char *argv[])
gtk_widget_show_all(appwindow);
/* add objects to the main pipeline */
/*
gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc);
gst_pipeline_add_sink(GST_PIPELINE(pipeline), videosink);
gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink);
@ -67,6 +66,7 @@ int main(int argc,char *argv[])
g_print("unable to handle stream\n");
exit(-1);
}
*/
xmlSaveFile("xmlTest.gst", gst_xml_write(GST_ELEMENT(pipeline)));

View file

@ -41,6 +41,7 @@ int main(int argc,char *argv[])
g_assert(audiosink != NULL);
/* add objects to the main pipeline */
/*
gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc);
gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink);
@ -48,6 +49,7 @@ int main(int argc,char *argv[])
g_print("unable to handle stream\n");
exit(-1);
}
*/
// hmmmm hack? FIXME
GST_FLAG_UNSET (pipeline, GST_BIN_FLAG_MANAGER);

View file

@ -46,11 +46,12 @@ int main(int argc,char *argv[])
g_assert(audiosink != NULL);
/* add objects to the main pipeline */
/*
gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc);
gst_pipeline_add_sink(GST_PIPELINE(pipeline), queue);
gst_bin_add(GST_BIN(thread), audiosink);
gst_pad_connect(gst_element_get_pad(queue,"src"),
gst_element_get_pad(audiosink,"sink"));
@ -58,6 +59,7 @@ int main(int argc,char *argv[])
g_print("cannot autoplug pipeline\n");
exit(-1);
}
*/
gst_bin_add(GST_BIN(pipeline), thread);

View file

@ -45,6 +45,7 @@ int main(int argc,char *argv[])
g_assert(audiosink != NULL);
/* add objects to the main pipeline */
/*
gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc);
gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink);
@ -52,6 +53,7 @@ int main(int argc,char *argv[])
g_print("unable to handle stream\n");
exit(-1);
}
*/
//gst_bin_remove(GST_BIN(pipeline), disksrc);

View file

@ -42,7 +42,7 @@ void print_prop(GstPropsEntry *prop,gboolean showname,gchar *pfx) {
g_free(longprefix);
break;
default:
printf("\n");
printf("unknown props %d\n", prop->propstype);
}
}
@ -59,30 +59,9 @@ void print_props(GstProps *properties,gchar *pfx) {
}
}
/*
struct _GstPropsEntry {
GQuark propid;
GstPropsId propstype;
union {
// flat values
gboolean bool_data;
guint32 fourcc_data;
gint int_data;
// structured values
struct {
GList *entries;
} list_data;
struct {
gint min;
gint max;
} int_range_data;
} data;
};
*/
gint print_element_info(GstElementFactory *factory) {
gint
print_element_info (GstElementFactory *factory)
{
GstElement *element;
GstObjectClass *gstobject_class;
GstElementClass *gstelement_class;
@ -322,11 +301,9 @@ void print_element_list() {
}
}
void print_plugin_info(GstPlugin *plugin) {
GList *factories;
GstElementFactory *factory;
void
print_plugin_info (GstPlugin *plugin)
{
printf("Plugin Details:\n");
printf(" Name:\t\t%s\n",plugin->name);
printf(" Long Name:\t%s\n",plugin->longname);
@ -334,6 +311,9 @@ void print_plugin_info(GstPlugin *plugin) {
printf("\n");
if (plugin->numelements) {
GList *factories;
GstElementFactory *factory;
printf("Element Factories:\n");
factories = gst_plugin_get_factory_list(plugin);
@ -344,6 +324,36 @@ void print_plugin_info(GstPlugin *plugin) {
printf(" %s: %s\n",factory->name,factory->details->longname);
}
}
if (plugin->numautopluggers) {
GList *factories;
GstAutoplugFactory *factory;
printf("Autpluggers:\n");
factories = gst_plugin_get_autoplug_list(plugin);
while (factories) {
factory = (GstAutoplugFactory*)(factories->data);
factories = g_list_next(factories);
printf(" %s: %s\n", factory->name, factory->longdesc);
}
}
if (plugin->numtypes) {
GList *factories;
GstTypeFactory *factory;
printf("Types:\n");
factories = gst_plugin_get_type_list(plugin);
while (factories) {
factory = (GstTypeFactory*)(factories->data);
factories = g_list_next(factories);
printf(" %s: %s\n", factory->mime, factory->exts);
if (factory->typefindfunc)
printf(" Has typefind function: %s\n",GST_DEBUG_FUNCPTR_NAME(factory->typefindfunc));
}
}
printf("\n");
}
@ -357,7 +367,7 @@ int main(int argc,char *argv[]) {
// if no arguments, print out list of elements
if (argc == 1) {
print_element_list();
print_element_list();
// else we try to get a factory
} else {