Updated the autoplugger:

Original commit message from CVS:
Updated the autoplugger:
- moved all of the code out of gstpipeline.c to autoplug.c
- The autoplugger now creates a GstElement based on the given src and
sink caps. The API now is:
GstElement* gst_autoplug_caps_list (GList *srcpad, GList *sinkpad, ...);
- the typefind function is moved from gstpipeline.c to gstplay.c. Not sure
if this is right behaviour but we need at least a bin in order to run
the typedetect functions.
- fixed a bug in gstbin.c where the MANAGER flag of the bin was not cleared
when going to the NULL state.
- a bug in the videosink was fixed. It was possible that more instances
of the video widget were created, causing major errors.
- commented out most of the 'old' autoplug examples.
- added the new autoplugger to gstplay.c. There still is a bit of hacking
needed to insert a queue into the autogenerated element. This will be fixed
when the autoplugger can also create the video/audio elements.
Fixed some more extranous spaces problems in various files.
This commit is contained in:
Wim Taymans 2001-02-06 20:42:28 +00:00
parent 5e1257437d
commit 5a52fd4009
32 changed files with 808 additions and 764 deletions

View file

@ -217,13 +217,6 @@ the stream.
</para>
<!-- ##### FUNCTION gst_object_get_type ##### -->
<para>
</para>
@Returns:
<!-- ##### MACRO GST_SINESRC ##### -->
<para>
@ -231,6 +224,13 @@ the stream.
@obj:
<!-- ##### FUNCTION gst_object_get_type ##### -->
<para>
</para>
@Returns:
<!-- ##### SECTION ./tmpl/plugin.sgml:Long_Description ##### -->
<para>

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

@ -42,6 +42,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);
@ -49,6 +50,7 @@ int main(int argc,char *argv[])
g_print("unable to handle stream\n");
exit(-1);
}
*/
/* make it ready */
gst_element_set_state(GST_ELEMENT(thread), GST_STATE_READY);

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

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

@ -24,6 +24,7 @@
#include "gst_private.h"
#include "gstautoplug.h"
#include "gstbin.h"
static void gst_autoplug_class_init (GstAutoplugClass *klass);
static void gst_autoplug_init (GstAutoplug *autoplug);
@ -89,7 +90,8 @@ gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest)
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);
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,
"factory \"%s\" can connect with factory \"%s\"", src->name, dest->name);
return TRUE;
}
}
@ -98,10 +100,75 @@ gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest)
}
srctemps = g_list_next (srctemps);
}
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory \"%s\" cannot connect with factory \"%s\"", src->name, dest->name);
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;
}
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)
{
@ -143,58 +210,6 @@ gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data)
return GST_AUTOPLUG_MAX_COST;
}
/**
* gst_autoplug_caps:
* @srccaps: the source caps
* @sinkcaps: the sink caps
*
* Perform autoplugging between the two given caps.
*
* Returns: a list of elementfactories that can connect
* the two caps
*/
GList*
gst_autoplug_caps (GstCaps *srccaps, GstCaps *sinkcaps)
{
caps_struct caps;
caps.src = g_list_prepend (NULL,srccaps);
caps.sink = g_list_prepend (NULL,sinkcaps);
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);
}
/**
* gst_autoplug_caps_list:
* @srccaps: the source caps list
* @sinkcaps: the sink caps list
*
* Perform autoplugging between the two given caps lists.
*
* Returns: a list of elementfactories that can connect
* the two caps lists
*/
GList*
gst_autoplug_caps_list (GList *srccaps, GList *sinkcaps)
{
caps_struct caps;
caps.src = srccaps;
caps.sink = sinkcaps;
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps list structures");
return gst_autoplug_func (caps.src, caps.sink,
gst_autoplug_elementfactory_get_list,
gst_autoplug_caps_find_cost,
&caps);
}
/**
* gst_autoplug_pads:
* @srcpad: the source pad
@ -205,21 +220,239 @@ gst_autoplug_caps_list (GList *srccaps, GList *sinkcaps)
* Returns: a list of elementfactories that can connect
* the two pads
*/
GList*
gst_autoplug_pads (GstPad *srcpad, GstPad *sinkpad)
GstElement*
gst_autoplug_caps_list (GList *srccaps, GList *sinkcaps, ...)
{
caps_struct caps;
va_list args;
GList *capslist;
GstElement *result = NULL, *srcelement = NULL;
GList **factories;
GList *chains = NULL;
GList *endcaps = NULL;
guint numsinks = 0, i;
gboolean have_common = FALSE;
caps.src = gst_pad_get_caps_list(srcpad);
caps.sink = gst_pad_get_caps_list(sinkpad);
va_start (args, sinkcaps);
capslist = sinkcaps;
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures");
/*
* 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;
return gst_autoplug_func (caps.src, caps.sink,
gst_autoplug_elementfactory_get_list,
gst_autoplug_caps_find_cost,
&caps);
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 *);
}
va_end (args);
/*
* 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);
}
}
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);
gboolean use_thread;
use_thread = have_common;
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);
// 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_autoplug_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(result), 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_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);
endcaps = g_list_next (endcaps);
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));
break;
}
}
}
}
return result;
}
static gint
find_factory (gst_autoplug_node *rgnNodes, gpointer factory)
{

View file

@ -55,13 +55,20 @@ struct _GstAutoplug {
struct _GstAutoplugClass {
GtkObjectClass parent_class;
/* signal callbacks */
void (*element_added) (GstAutoplug *eutoplug, GstElement *element);
};
GtkType gst_autoplug_get_type (void);
struct _GstAutoplugFactory {
gchar *name; /* name of element */
GtkType type; /* unique GtkType of the autoplugger */
};
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);
GtkType gst_autoplug_get_type (void);
GstElement* gst_autoplug_caps_list (GList *srcpad, GList *sinkpad, ...);
#ifdef __cplusplus
@ -69,5 +76,5 @@ GList* gst_autoplug_pads (GstPad *srcpad, GstPad *sinkpad);
#endif /* __cplusplus */
#endif /* __GST_AUTOPLUG_H__ */
#endif /* __GST_AUTOPLUG_H__ */

View file

@ -263,6 +263,8 @@ gst_bin_change_state (GstElement *element)
break;
}
case GST_STATE_READY_TO_NULL:
GST_FLAG_UNSET (bin, GST_BIN_FLAG_MANAGER);
default:
break;
}
@ -585,7 +587,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);
@ -754,7 +756,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++;
}
@ -851,7 +855,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

@ -48,7 +48,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);
@ -56,21 +56,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 typeid);
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

@ -518,7 +518,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;
@ -901,13 +901,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);
}

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

@ -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
@ -956,6 +974,65 @@ GstBuffer *gst_pad_pullregion(GstPad *pad,GstRegionType type,guint64 offset,guin
* 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:
@ -975,7 +1052,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);
@ -1016,7 +1093,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;
@ -1087,21 +1166,24 @@ GstPadTemplate*
gst_padtemplate_load_thyself (xmlNodePtr parent)
{
xmlNodePtr field = parent->childs;
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);
}
@ -1109,21 +1191,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;
}
@ -1241,13 +1326,6 @@ gst_pad_get_element_private (GstPad *pad)
}
/***** ghost pads *****/
static void gst_ghost_pad_class_init (GstGhostPadClass *klass);

View file

@ -271,6 +271,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

@ -51,15 +51,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 +83,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 +94,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,394 +111,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_READY);
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)) {
@ -514,22 +140,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

@ -38,8 +38,8 @@
#include <gst/gstelement.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 */
@ -57,28 +57,28 @@ struct _GstPlugin {
typedef GstPlugin* (*GstPluginInitFunc) (GModule *module);
void _gst_plugin_initialize (void);
void _gst_plugin_initialize (void);
GstPlugin* gst_plugin_new (const gchar *name);
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);
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_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);
GstPlugin* gst_plugin_find (const gchar *name);
GList* gst_plugin_get_list (void);
@ -86,9 +86,9 @@ 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);
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

@ -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,24 +122,46 @@ 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");
priv->audio_play = gst_thread_new ("audio_render_thread");
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);
priv->audio_queue = gst_elementfactory_make ("queue", "audio_queue");
gst_bin_add (GST_BIN (priv->audio_play), priv->audio_element),
gst_element_connect (priv->audio_queue, "src", priv->audio_element, "sink");
// FIXME, we need caps negiciation
gst_pad_set_caps_list (gst_element_get_pad (priv->audio_queue, "sink"),
gst_pad_get_caps_list (
gst_element_get_pad (priv->audio_element, "sink")));
/* and a video sink */
priv->video_show = gst_elementfactory_make ("videosink","show");
priv->video_show = gst_thread_new ("video_render_thread");
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);
priv->video_queue = gst_elementfactory_make ("queue", "video_queue");
gst_bin_add (GST_BIN (priv->video_show), priv->video_element),
gst_element_connect (priv->video_queue, "src", priv->video_element, "sink");
gst_pad_set_caps_list (gst_element_get_pad (priv->video_queue, "sink"),
gst_pad_get_caps_list (
gst_element_get_pad (priv->video_element, "sink")));
play->state = GST_PLAY_STOPPED;
play->flags = 0;
@ -155,37 +176,37 @@ 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)
{
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 (GstElement *element,
const gchar *property,
GstElement **target)
{
@ -199,21 +220,21 @@ gst_play_object_introspect (GstElement *element,
}
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,
static void
gst_play_object_added (GstElement *pipeline,
GstElement *element,
GstPlay *play)
GstPlay *play)
{
GstPlayPrivate *priv;
g_return_if_fail (play != NULL);
priv = (GstPlayPrivate *)play->priv;
@ -227,9 +248,9 @@ gst_play_object_added (GstElement *pipeline,
}
else {
// first come first serve here...
if (!priv->offset_element)
if (!priv->offset_element)
gst_play_object_introspect (element, "offset", &priv->offset_element);
if (!priv->bit_rate_element)
if (!priv->bit_rate_element)
gst_play_object_introspect (element, "bit_rate", &priv->bit_rate_element);
if (!priv->media_time_element)
gst_play_object_introspect (element, "media_time", &priv->media_time_element);
@ -238,72 +259,162 @@ gst_play_object_added (GstElement *pipeline,
}
}
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)
{
GList *pads = gst_element_get_pad_list (new_element);
while (pads) {
GstPad *pad = GST_PAD (pads->data);
GstPad *targetpad = gst_element_get_pad (target, "sink");
if (gst_pad_check_compatibility (pad, targetpad)) {
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;
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");
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;
new_element = gst_autoplug_caps_list
(gst_pad_get_caps_list (gst_element_get_pad (priv->src, "src")),
gst_pad_get_caps_list (gst_element_get_pad (priv->video_queue, "sink")),
gst_pad_get_caps_list (gst_element_get_pad (priv->audio_queue, "sink")),
NULL);
if (!new_element) {
return GST_PLAY_CANNOT_PLAY;
}
if (GST_PAD_CONNECTED (gst_element_get_pad (priv->audio_play, "sink"))) {
gst_bin_remove (GST_BIN (priv->bin), priv->src);
gst_bin_add (GST_BIN (priv->thread), priv->src);
gst_bin_add (GST_BIN (priv->bin), new_element);
gst_element_connect (priv->src, "src", new_element, "sink");
if (connect_pads (new_element, priv->video_queue)) {
gst_bin_add (GST_BIN (priv->bin), priv->video_show),
play->flags |= GST_PLAY_TYPE_VIDEO;
gtk_widget_show (priv->video_widget);
}
if (connect_pads (new_element, priv->audio_queue)) {
gst_bin_add (GST_BIN (priv->bin), priv->audio_play),
play->flags |= GST_PLAY_TYPE_AUDIO;
}
// hmmmm hack? FIXME
GST_FLAG_UNSET (priv->pipeline, GST_BIN_FLAG_MANAGER);
gst_bin_add (GST_BIN (priv->thread), priv->pipeline);
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 +422,8 @@ gst_play_realize (GtkWidget *widget)
}
}
void
gst_play_play (GstPlay *play)
void
gst_play_play (GstPlay *play)
{
GstPlayPrivate *priv;
@ -333,8 +444,8 @@ gst_play_play (GstPlay *play)
play->state);
}
void
gst_play_pause (GstPlay *play)
void
gst_play_pause (GstPlay *play)
{
GstPlayPrivate *priv;
@ -353,8 +464,8 @@ gst_play_pause (GstPlay *play)
play->state);
}
void
gst_play_stop (GstPlay *play)
void
gst_play_stop (GstPlay *play)
{
GstPlayPrivate *priv;
@ -374,8 +485,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 +498,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 +508,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 +533,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 +541,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 +560,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 +568,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 +581,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 +596,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 +617,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,11 @@ typedef struct _GstPlayPrivate GstPlayPrivate;
struct _GstPlayPrivate {
GstElement *thread;
GstElement *pipeline;
GstElement *audio_play;
GstElement *video_show;
GstElement *bin;
GstElement *audio_play, *video_show;
GstElement *video_element, *audio_element;
GstElement *video_queue, *audio_queue;
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

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

1
tests/.gitignore vendored
View file

@ -24,3 +24,4 @@ markup
load
padfactory
tee
autoplug2

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
# we have nothing but apps here, we can do this safely
LIBS += $(GST_LIBS)

View file

@ -1,63 +1,33 @@
#include <gst/gst.h>
static GList*
autoplug_caps (gchar *mime1, gchar *mime2)
int
main (int argc, char *argv[])
{
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)
{
g_print ("dumping factories\n");
while (factories) {
GstElementFactory *factory = (GstElementFactory *)factories->data;
g_print ("factory: \"%s\"\n", factory->name);
factories = g_list_next (factories);
}
}
int main(int argc,char *argv[])
{
GList *factories;
GstElement *element;
GstElement *videosink, *audiosink;
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);
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);
element = gst_autoplug_caps_list (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);
}

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

@ -42,6 +42,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);
@ -49,6 +50,7 @@ int main(int argc,char *argv[])
g_print("unable to handle stream\n");
exit(-1);
}
*/
/* make it ready */
gst_element_set_state(GST_ELEMENT(thread), GST_STATE_READY);

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);