Commit 8c9cd079 authored by David Schleef's avatar David Schleef

Merge CAPS branch

Original commit message from CVS:
Merge CAPS branch
parent 54b38507
......@@ -604,6 +604,7 @@ testsuite/Makefile
testsuite/bins/Makefile
testsuite/bytestream/Makefile
testsuite/caps/Makefile
testsuite/caps2/Makefile
testsuite/cleanup/Makefile
testsuite/clock/Makefile
testsuite/debug/Makefile
......
The new caps code uses the type name GstCaps2 and the function
names gst_caps2_*(). Before the CAPS branch is merged, there
will be a global change from caps2 to caps. Since GstCaps is
no longer defined, it no longer compiles, thus highlighting
exactly what needs to be changed in an element.
Pad Templates:
Old style:
GST_PAD_TEMPLATE_FACTORY (fakesrc_src_factory,
"src%d",
GST_PAD_SRC,
GST_PAD_REQUEST,
GST_CAPS_ANY
);
New style:
GstStaticPadTemplate fakesrc_src_template = GST_STATIC_PAD_TEMPLATE (
"src%d",
GST_PAD_SRC,
GST_PAD_REQUEST,
GST_STATIC_CAPS2_ANY
);
The old style defined a function called fakesrc_src_factory(), which,
when called, returns a pad template. The new style defines a
GstStaticPadTemplate, which can be converted to a GstPadTemplate
by the function gst_static_pad_template_get(). The 4th argument
is also different -- previously it would call the GST_CAPS_NEW()
function. Now it is a GstStaticCaps.
Not every pad template can be converted to a GstStaticPadTemplate,
particularly those which create caps from another source at runtime,
such as videotestsrc.
Caps:
Old style:
GST_CAPS_NEW (
"sinesrc_src",
"audio/x-raw-int",
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
"signed", GST_PROPS_BOOLEAN (TRUE),
"width", GST_PROPS_INT (16),
"depth", GST_PROPS_INT (16),
"rate", GST_PROPS_INT_RANGE (8000, 48000),
"channels", GST_PROPS_INT (1)
)
New style:
GST_STATIC_CAPS2 ( "audio/x-raw-int, "
"endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
"signed = (boolean) true, "
"width = (int) 16, "
"depth = (int) 16, "
"rate = (int) [ 8000, 48000 ], "
"channels = (int) 1"
)
The old style calls a function that creates a GstCaps. The new style
stores a string in a GstStaticCaps2, and this string is converted to
a caps in the function gst_static_caps2_get().
Note that the old caps name is no longer used.
Old style:
caps = GST_CAPS_NEW ("videotestsrc_filter",
"video/x-raw-rgb",
"bpp", GST_PROPS_INT(format->bitspp),
"endianness", GST_PROPS_INT(endianness),
"depth", GST_PROPS_INT(format->depth),
"red_mask", GST_PROPS_INT(format->red_mask),
"green_mask", GST_PROPS_INT(format->green_mask),
"blue_mask", GST_PROPS_INT(format->blue_mask));
New style:
caps = gst_caps2_new_simple("video/x-raw-rgb",
"bpp", G_TYPE_INT, format->bitspp,
"endianness", G_TYPE_INT, endianness,
"depth", G_TYPE_INT, format->depth,
"red_mask", G_TYPE_INT, format->red_mask,
"green_mask", G_TYPE_INT, format->green_mask,
"blue_mask", G_TYPE_INT, format->blue_mask);
Not everything can be converted in this way, especially lists and
ranges.
IMPLEMENTATION
Pad Capabilities (caps) are mathematical sets that represent all the
possible stream types that a pad can use. These general sets are
represented by unions of simpler sets known as caps structures. Each
caps structure has a media type (e.g., "audio/mpeg") and a number of
properties. Each property has a name and a GValue. In normal
circumstances, the GValue will have the types int, boolean, string,
fourcc, and double. Simple sets are constructed by using GValues
that are lists of other GValues, or the special types that represent
int ranges and double ranges.
A "fixed" caps represents exactly one media format. This means that
the caps is a union of exactly one caps structure, and each property
in the caps structure is a simple type, i.e., no ranges or lists.
There are two special caps values, "ANY" which represents the union
of all stream types, and "EMPTY", which represents the set of no
stream types. The ANY caps is often used on generic elements that
handle any type of data (e.g., filesrc and filesink). The EMPTY
caps is the return value of gst_caps_intersect(), when the two
given caps do not intersect. In many cases, using EMPTY is invalid.
CAPS NEGOTIATION
Elements provide information to the core about what stream formats
they understand in four ways: the caps in the pad templates, the
caps returned by a pad's getcaps function, accepting/denying
a given caps in the pad link function, and a new fixate function.
The pad template caps should be the union of caps a pad supports
in any potential situation. Simultaneously, these caps should be
as specific as possible, since it is used to decide which elements
to attempt for autoplugging, without having to load the element.
The pad template caps are generally detemined at compile time, but
might be actually computed at run-time from other information.
The getcaps() function returns the caps supported by a given pad,
in the context of the element's state, its link to other elements,
and the devices or files it has opened. These caps must be a
subset of the pad template caps. In the NULL state with no links,
the getcaps function should ideally return the same caps as the
pad template. In rare circumstances, an object property can affect
the caps returned by getcaps, but this is discouraged. For most
filters, the caps returned by getcaps is directly affected by the
allowed caps on other pads. For demuxers and decoders, the caps
returned by the srcpad's getcaps function is directly related to
the stream data. Again, getcaps should return the most specific
caps it reasonably can, since this helps with autoplugging.
The pad link function is the last step in negotiating caps. The
core calls the pad link function with a fixed caps, meaning that
the stream format is precisely defined, with the caps having one
structure, with no fields that are ranges or lists.
There is also a new pad function "fixate", which is used to help
choose a fixed caps from a non-fixed caps. This is called in
situations where normal negotiation cannot decide on a fixed caps.
You should almost never implement a fixate function, please ask
me if it is appropriate for your case. Fixate functions are called
iteratively on the pads until a fixed caps is found. Fixate functions
are called with a const caps, and should return a caps that is a
strict subset of the given caps. That is, the function should
create a caps that is "more fixed" than previously, but does not
have to return fixed caps. If the fixate function can't provide
more fixed caps, it should return NULL.
Checklist for getcaps:
- The getcaps function prototype no longer has the caps parameter.
Remove it.
- The returned caps is owned by the caller. Make sure you don't
keep a pointer to the caps.
- Make sure that the getcaps function can be called safely in each
element state (NULL, READY, PAUSED, PLAYING), and for any element
configuration (properties, links, devices/files opened or not,
error state, etc.)
- Make sure that the returned caps do not depend on the caps that
indicate the stream type that the pad is currently using.
Checklist for pad_link:
- The pad link function prototypes uses a const GstCaps *.
- Pad link functions are called with fixed caps. There's no need
to check for this. This means that you can assume that the caps
is not ANY or EMPTY, and that there is exactly one structure in
the caps, and that all the properties in the caps
- Pad link functions are called with caps that are a subset of the
most recent return value of the pad's getcaps function. Generally,
the getcaps function was called immediately prior to calling the
src_link function. For 0.8, you can assume that nothing has changed
in your element that would cause a change to the return value of
getcaps.
- the return value GST_PAD_LINK_OK should be used when the caps are
acceptable, and you've extracted all the necessary information from
the caps and set the element's internal state appropriately.
- the return value GST_PAD_LINK_REFUSED should be used when the caps
are unacceptable for whatever reason.
- the return value GST_PAD_LINK_DELAYED should be used when the
element is in a state where it can't determine whether the caps
are acceptable or not. This is often used if the element needs
to open a device or process data before determining acceptable
caps.
- the pad_link function must not call gst_caps_try_set_caps() on
the pad that was specified as a parameter.
- the pad_link function may (and often should) call
gst_caps_try_set_caps() on pads that are not specified as the
pad parameter.
Checklist for fixate:
- Make sure you actually should be using a fixate function. Fixate
functions are reasonable for non-fixed primary sources, such as
videotestsrc, v4lsrc, and osssrc.
- The user_data parameter is mainly used for user-provided fixate
function. It should be ignored in element fixate functions.
Canonical caps/structure strings (those created by gst_caps_to_string()
and gst_structure_to_string()) do not have AUTO_VALUE.
Goals:
- UTF-8 clean
- SIMPLE_STRINGs should cover most simple cases that don't interfere
with other parts of the gst_caps or gst_parse grammar
- forward-parsed grammar
- quoted strings handle backslash escaping as well as XML-style (&ack;)
escaping
CAPS = STRUCTURE [ ';' STRUCTURE ]*
STRUCTURE = STRUCTURE_NAME [ ',' FIELD ]*
STRUCTURE_NAME = STRING
FIELD = FIELD_NAME '=' TYPED_VALUE
FIELD_NAME = SIMPLE_STRING
TYPED_VALUE = CANONICAL_VALUE | AUTO_VALUE
CANONICAL_VALUE = '{' TYPED_VALUE [ ',' TYPED_VALUE ]* '}'
| '[' TYPED_VALUE ',' TYPED_VALUE ']'
| '(' TYPE ')' VALUE
AUTO_VALUE = [-+]?[0-9][0-9]*
| [-+]?[0-9][0-9]*[.][0-9]*[eE][-+][0-9]*
| STRING
VALUE = STRING
STRING = ["][^"]["]
| ['][^'][']
| SIMPLE_STRING
SIMPLE_STRING = [A-Za-z0-9_+-:./]+
TYPE = "int" | "i" | "float" | "f" | "double" | "d" | "fourcc" | "4"
| "boolean" | "bool" | "b"
| GTYPE
Canonical Examples:
"audio/raw"
"audio/raw", rate=(int)44100
"audio/raw", rate=(int)44100, signed=(boolean)true
"audio/raw", rate={ (int)44100, (int)48000 }
"audio/raw", rate=[ (int)8000, (int)48000 ]
......@@ -330,7 +330,7 @@ create_input_channel (int id, char* location)
#endif
new_element = gst_autoplug_to_caps (autoplug, srccaps,
gst_caps_new ("audio", "audio/raw", NULL), NULL);
gst_caps_new ("audio/raw", NULL), NULL);
if (!new_element) {
g_print ("could not autoplug, no suitable codecs found...\n");
......
......@@ -57,31 +57,25 @@ enum {
* can have. They can be quite complex, but for this example plugin
* they are rather simple.
*/
GST_PAD_TEMPLATE_FACTORY (sink_factory,
"sink", /* The name of the pad */
GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE (
"sink", /* The name of the pad */
GST_PAD_SINK, /* Direction of the pad */
GST_PAD_ALWAYS, /* The pad exists for every instance */
GST_CAPS_NEW (
"example_sink", /* The name of the caps */
"unknown/unknown", /* The overall MIME/type */
"foo", GST_PROPS_INT (1), /* An integer property */
"bar", GST_PROPS_BOOLEAN (TRUE), /* A boolean */
"baz", GST_PROPS_LIST ( /* A list of values for */
GST_PROPS_INT (1),
GST_PROPS_INT (3)
)
GST_STATIC_CAPS (
"unknown/unknown, " /* The MIME media type */
"foo:int=1, " /* an integer property */
"bar:boolean=true, " /* a boolean property */
"baz:int={ 1, 3 }" /* a list of values */
)
);
/* This factory is much simpler, and defines the source pad. */
GST_PAD_TEMPLATE_FACTORY (src_factory,
GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE (
"src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"example_src",
"unknown/unknown",
NULL
GST_STATIC_CAPS (
"unknown/unknown"
)
);
......@@ -189,8 +183,10 @@ gst_example_class_init (GstExampleClass *klass)
/* The pad templates can be easily generated from the factories above,
* and then added to the list of padtemplates for the class.
*/
gst_element_class_add_pad_template (gstelement_class, GST_PAD_TEMPLATE_GET (sink_factory));
gst_element_class_add_pad_template (gstelement_class, GST_PAD_TEMPLATE_GET (src_factory));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sink_template));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&src_template));
}
/* This function is responsible for initializing a specific instance of
......@@ -203,7 +199,7 @@ gst_example_init(GstExample *example)
* We will use the template constructed by the factory.
*/
example->sinkpad = gst_pad_new_from_template (
GST_PAD_TEMPLATE_GET (sink_factory), "sink");
gst_static_pad_template_get (&sink_template), "sink");
/* Setting the chain function allows us to supply the function that will
* actually be performing the work. Without this, the element would do
* nothing, with undefined results (assertion failures and such).
......@@ -220,7 +216,7 @@ gst_example_init(GstExample *example)
* they only produce them.
*/
example->srcpad = gst_pad_new_from_template (
GST_PAD_TEMPLATE_GET (src_factory), "src");
gst_static_pad_template_get (&src_template), "src");
gst_element_add_pad(GST_ELEMENT(example),example->srcpad);
/* Initialization of element's private variables. */
......
#include <gst/gst.h>
void
type_found (GstElement *typefind, GstCaps* caps)
type_found (GstElement *typefind, const GstCaps * caps)
{
xmlDocPtr doc;
xmlNodePtr parent;
......@@ -10,7 +10,8 @@ type_found (GstElement *typefind, GstCaps* caps)
doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Capabilities", NULL);
parent = xmlNewChild (doc->xmlRootNode, NULL, "Caps1", NULL);
gst_caps_save_thyself (caps, parent);
/* FIXME */
//gst_caps_save_thyself (caps, parent);
xmlDocDump (stdout, doc);
}
......
......@@ -80,8 +80,7 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
gstatomic.c \
gstbin.c \
gstbuffer.c \
gstbufferpool-default.c \
gstcaps.c \
gstcaps2.c \
gstclock.c \
gstcpu.c \
gstdata.c \
......@@ -98,7 +97,6 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
gstpipeline.c \
gstplugin.c \
gstpluginfeature.c \
gstprops.c \
gstprobe.c \
gstqueue.c \
gstquery.c \
......@@ -143,8 +141,7 @@ gst_headers = \
gstobject.h \
gstbin.h \
gstbuffer.h \
gstbufferpool-default.h \
gstcaps.h \
gstcaps2.h \
gstclock.h \
gstcompat.h \
gstcpu.h \
......@@ -164,7 +161,6 @@ gst_headers = \
gstplugin.h \
gstpluginfeature.h \
gstprobe.h \
gstprops.h \
gstqueue.h \
gstquery.h \
gstscheduler.h \
......
......@@ -58,7 +58,7 @@ g_list_free_list_and_elements (GList *list)
* Returns: TRUE, if both caps intersect.
*/
gboolean
gst_autoplug_caps_intersect (GstCaps *src, GstCaps *sink)
gst_autoplug_caps_intersect (const GstCaps *src, const GstCaps *sink)
{
GstCaps *caps;
......@@ -74,7 +74,7 @@ gst_autoplug_caps_intersect (GstCaps *src, GstCaps *sink)
return FALSE;
/* hurrah, we can link, now remove the intersection */
gst_caps_unref (caps);
gst_caps_free (caps);
return TRUE;
}
......@@ -88,7 +88,7 @@ gst_autoplug_caps_intersect (GstCaps *src, GstCaps *sink)
* Returns: #GstPadTemplate that can connect to the given caps
*/
GstPadTemplate *
gst_autoplug_can_connect_src (GstElementFactory *fac, GstCaps *src)
gst_autoplug_can_connect_src (GstElementFactory *fac, const GstCaps *src)
{
GList *templs;
......@@ -117,7 +117,7 @@ gst_autoplug_can_connect_src (GstElementFactory *fac, GstCaps *src)
* Returns: #GstPadTemplate that can connect to the given caps
*/
GstPadTemplate *
gst_autoplug_can_connect_sink (GstElementFactory *fac, GstCaps *sink)
gst_autoplug_can_connect_sink (GstElementFactory *fac, const GstCaps *sink)
{
GList *templs;
......@@ -331,7 +331,7 @@ gst_autoplug_factories_at_most_templates(GList *factories, GstPadDirection dir,
* to get the shortest path.
*/
GList *
gst_autoplug_sp (GstCaps *srccaps, GstCaps *sinkcaps, GList *factories)
gst_autoplug_sp (const GstCaps *srccaps, const GstCaps *sinkcaps, GList *factories)
{
GList *factory_nodes = NULL;
guint curcost = GST_AUTOPLUG_MAX_COST; /* below this cost, there is no path */
......@@ -340,11 +340,9 @@ gst_autoplug_sp (GstCaps *srccaps, GstCaps *sinkcaps, GList *factories)
g_return_val_if_fail (srccaps != NULL, NULL);
g_return_val_if_fail (sinkcaps != NULL, NULL);
GST_INFO ("attempting to autoplug via shortest path from %s to %s",
gst_caps_get_mime (srccaps), gst_caps_get_mime (sinkcaps));
GST_INFO ("attempting to autoplug via shortest path from %s to %s",
gst_caps_to_string(srccaps), gst_caps_to_string(sinkcaps));
gst_caps_debug (srccaps, "source caps");
gst_caps_debug (sinkcaps, "sink caps");
/* wrap all factories as GstAutoplugNode
* initialize the cost */
while (factories)
......
......@@ -40,9 +40,9 @@ struct _GstAutoplugNode {
};
/* helper functions */
gboolean gst_autoplug_caps_intersect (GstCaps *src, GstCaps *sink);
GstPadTemplate * gst_autoplug_can_connect_src (GstElementFactory *fac, GstCaps *src);
GstPadTemplate * gst_autoplug_can_connect_sink (GstElementFactory *fac, GstCaps *sink);
gboolean gst_autoplug_caps_intersect (const GstCaps *src, const GstCaps *sink);
GstPadTemplate * gst_autoplug_can_connect_src (GstElementFactory *fac, const GstCaps *src);
GstPadTemplate * gst_autoplug_can_connect_sink (GstElementFactory *fac, const GstCaps *sink);
GstPadTemplate * gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest);
gboolean gst_autoplug_factory_has_direction (GstElementFactory *fac, GstPadDirection dir);
#define gst_autoplug_factory_has_sink(fac) gst_autoplug_factory_has_direction((fac), GST_PAD_SINK)
......@@ -59,6 +59,6 @@ GList * gst_autoplug_factories_filters_with_sink_caps(GList *factories);
GList * gst_autoplug_factories_at_most_templates(GList *factories, GstPadDirection dir, guint maxtemplates);
/* shortest path algorithm */
GList * gst_autoplug_sp (GstCaps *src_caps, GstCaps *sink_caps, GList *factories);
GList * gst_autoplug_sp (const GstCaps *src_caps, const GstCaps *sink_caps, GList *factories);
#endif /* __GST_SEARCHFUNCS_H__ */
......@@ -65,11 +65,12 @@ enum {
};
/* generic templates */
GST_PAD_TEMPLATE_FACTORY (spider_src_factory,
static GstStaticPadTemplate spider_src_factory =
GST_STATIC_PAD_TEMPLATE (
"src_%d",
GST_PAD_SRC,
GST_PAD_REQUEST,
NULL /* no caps */
GST_STATIC_CAPS_ANY
);
/* standard GObject stuff */
......@@ -152,7 +153,8 @@ gst_spider_class_init (GstSpiderClass *klass)
gobject_class->get_property = gst_spider_get_property;
gobject_class->dispose = gst_spider_dispose;
gst_element_class_add_pad_template (gstelement_class, GST_PAD_TEMPLATE_GET (spider_src_factory));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&spider_src_factory));
gst_element_class_set_details (gstelement_class, &gst_spider_details);
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_spider_request_new_pad);
......
......@@ -41,18 +41,20 @@ static GstElementDetails gst_spider_identity_details = GST_ELEMENT_DETAILS (
/* generic templates
* delete me when meging with spider.c
*/
GST_PAD_TEMPLATE_FACTORY (spider_src_factory,
static GstStaticPadTemplate spider_src_factory =
GST_STATIC_PAD_TEMPLATE (
"src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
NULL /* no caps */
GST_STATIC_CAPS_ANY
);
GST_PAD_TEMPLATE_FACTORY (spider_sink_factory,
static GstStaticPadTemplate spider_sink_factory =
GST_STATIC_PAD_TEMPLATE (
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
NULL /* no caps */
GST_STATIC_CAPS_ANY
);
/* SpiderIdentity signals and args */
......@@ -73,8 +75,8 @@ static void gst_spider_identity_init (GstSpiderIdentity *spider_identity);
/* functions set in pads, elements and stuff */
static void gst_spider_identity_chain (GstPad *pad, GstBuffer *buf);
static GstElementStateReturn gst_spider_identity_change_state (GstElement *element);
static GstPadLinkReturn gst_spider_identity_link (GstPad *pad, GstCaps *caps);
static GstCaps * gst_spider_identity_getcaps (GstPad *pad, GstCaps *caps);
static GstPadLinkReturn gst_spider_identity_link (GstPad *pad, const GstCaps *caps);
static GstCaps * gst_spider_identity_getcaps (GstPad *pad);
/* loop functions */
static void gst_spider_identity_dumb_loop (GstSpiderIdentity *ident);
static void gst_spider_identity_src_loop (GstSpiderIdentity *ident);
......@@ -121,35 +123,28 @@ gst_spider_identity_class_init (GstSpiderIdentityClass *klass)
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
/* add our two pad templates */
gst_element_class_add_pad_template (gstelement_class, GST_PAD_TEMPLATE_GET (spider_src_factory));
gst_element_class_add_pad_template (gstelement_class, GST_PAD_TEMPLATE_GET (spider_sink_factory));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&spider_src_factory));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&spider_sink_factory));
gst_element_class_set_details (gstelement_class, &gst_spider_identity_details);
gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_spider_identity_change_state);
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_spider_identity_request_new_pad);
}
static GstBufferPool*
gst_spider_identity_get_bufferpool (GstPad *pad)
{
GstSpiderIdentity *ident;
ident = GST_SPIDER_IDENTITY (gst_pad_get_parent (pad));
return gst_pad_get_bufferpool (ident->src);
}
static void
gst_spider_identity_init (GstSpiderIdentity *ident)
{
/* sink */
ident->sink = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (spider_sink_factory), "sink");
ident->sink = gst_pad_new_from_template (
gst_static_pad_template_get (&spider_sink_factory), "sink");
gst_element_add_pad (GST_ELEMENT (ident), ident->sink);
gst_pad_set_link_function (ident->sink, GST_DEBUG_FUNCPTR (gst_spider_identity_link));
gst_pad_set_getcaps_function (ident->sink, GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
gst_pad_set_bufferpool_function (ident->sink, GST_DEBUG_FUNCPTR (gst_spider_identity_get_bufferpool));
/* src */
ident->src = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (spider_src_factory), "src");
ident->src = gst_pad_new_from_template (
gst_static_pad_template_get (&spider_src_factory), "src");
gst_element_add_pad (GST_ELEMENT (ident), ident->src);
gst_pad_set_link_function (ident->src, GST