Commit 6fbff1c1 authored by Ronald S. Bultje's avatar Ronald S. Bultje
Browse files

New typefind system: bytestream is now part of the core all plugins have been...

New typefind system: bytestream is now part of the core all plugins have been modified to use this new typefind syste...

Original commit message from CVS:
New typefind system:
* bytestream is now part of the core
* all plugins have been modified to use this new typefind system
* asf typefinding added
* mpeg video stream typefiding removed because it's broken
* duplicate typefind entries removed
* extra id3 typefinding added, because we've seen 4 types of files
(riff/wav, flac, vorbis, mp3) with id3 headers and each of these needs
to work. Instead, I've added an id3 element and let it redo typefiding
after the id3 header. this needs a hack because spider only typefinds
once. We can remove this hack once spider supports multiple typefinds.
* with all this, mp3 typefinding is semi-rewritten
* id3 typefinding in flac/vorbis is removed, it's no longer needed
* fixed spider and gst-typefind to use this, too.
* Other general cleanups
parent 00d6aa9c
......@@ -568,7 +568,6 @@ gst/types/Makefile
gst/registries/Makefile
libs/Makefile
libs/gst/Makefile
libs/gst/bytestream/Makefile
libs/gst/getbits/Makefile
libs/gst/control/Makefile
libs/ext/Makefile
......
......@@ -210,17 +210,6 @@ macros GST_IS_MIXER () and GST_MIXER () would then look like this:
So the application would just tread it with the known macro, and
everything would look extremely simple to the end user.
Also some convenience function to set the element:
void
gst_interface_set_element (GstInterface *iface,
GstElement *element)
{
g_return_if_fail (GST_IS_INTERFACE (iface));
iface->element = element;
}
4a) mixer
---------
A mixer is a way of controlling volume and input/output channels.
......@@ -317,7 +306,7 @@ typedef struct _GstOverlayClass {
XID xid);
} GstOverlayClass;
That's all!
That's all! It would look similar for FB & co.
4c) user input
--------------
......@@ -335,8 +324,9 @@ input-from-application APIs.
5) Status of this document
==========================
This is a proposal, nothing more. Nothing is implemented. Target
release is 0.8.0 or any 0.7.x version.
The interfaces are implemented, more (for metadata, framebuffer-
overlay, video balancing (brightness), user input etc. are all
pending.
6) Copyright and blabla
=======================
......
......@@ -16,13 +16,13 @@ GST_LOADSAVE_SRC = gstxml.c
endif
if GST_DISABLE_TYPEFIND
GST_TYPEFIND_SRC =
GST_TYPEFIND_SRC =
else
GST_TYPEFIND_SRC = gsttypefind.c
endif
if GST_DISABLE_AUTOPLUG
GST_AUTOPLUG_SRC =
GST_AUTOPLUG_SRC =
GST_AUTOPLUG_DIRS =
else
GST_AUTOPLUG_SRC = gstautoplug.c
......@@ -91,11 +91,12 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
gstmarshal.c \
$(GST_ENUMTYPES_SRC) \
gstobject.c \
$(GST_AUTOPLUG_SRC) \
gstatomic.c \
$(GST_AUTOPLUG_SRC) \
gstbin.c \
gstbuffer.c \
gstbufferpool-default.c \
gstbytestream.c \
gstcaps.c \
gstclock.c \
gstcpu.c \
......@@ -157,6 +158,7 @@ gst_headers = \
gstbin.h \
gstbuffer.h \
gstbufferpool-default.h \
gstbytestream.h \
gstcaps.h \
gstclock.h \
gstcompat.h \
......
......@@ -27,13 +27,15 @@ libgstautoplugger_la_CFLAGS = $(GST_CFLAGS)
libgstautoplugger_la_LIBADD =
libgstautoplugger_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstspider_la_SOURCES = gstspider.c gstspideridentity.c gstsearchfuncs.c
libgstspider_la_SOURCES = \
gstspider.c gstspideridentity.c \
gstsearchfuncs.c
libgstspider_la_CFLAGS = $(GST_CFLAGS)
libgstspider_la_LIBADD =
libgstspider_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = gststaticautoplug.h gststaticautoplugrender.h \
gstspider.h gstspideridentity.h gstsearchfuncs.h
gstspider.h gstspideridentity.h gstsearchfuncs.h
noinst_PROGRAMS = autoplugtest spidertest
......
......@@ -250,11 +250,12 @@ gst_autoplug_factories_filters_with_sink_caps (GList *factories)
GList *ret = NULL;
GstElementFactory *factory;
GList *templs;
while (factories)
{
factory = (GstElementFactory *) factories->data;
templs = factory->padtemplates;
if (GST_PLUGIN_FEATURE (factory)->rank > 0){
gboolean have_src = FALSE;
gboolean have_sink = FALSE;
......@@ -341,6 +342,7 @@ gst_autoplug_sp (GstCaps *srccaps, GstCaps *sinkcaps, GList *factories)
GST_INFO ("attempting to autoplug via shortest path from %s to %s",
gst_caps_get_mime (srccaps), gst_caps_get_mime (sinkcaps));
gst_caps_debug (srccaps, "source caps");
gst_caps_debug (sinkcaps, "sink caps");
/* wrap all factories as GstAutoplugNode
......
......@@ -413,61 +413,22 @@ gst_spider_identity_src_loop (GstSpiderIdentity *ident)
static void
gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *ident)
{
GstBuffer *buf=NULL;
GstBuffer *typefindbuf = NULL;
gboolean getmorebuf = TRUE;
GstBuffer *buf = NULL;
GList *type_list;
GstCaps *caps;
GstByteStream *bs;
/* this should possibly be a property */
guint bufsizelimit = 4096;
g_return_if_fail (GST_IS_SPIDER_IDENTITY (ident));
while (getmorebuf){
/* check if our buffer is big enough to do a typefind */
if (typefindbuf && GST_BUFFER_SIZE(typefindbuf) >= bufsizelimit){
getmorebuf = FALSE;
break;
}
buf = gst_pad_pull (ident->sink);
/* if it's an event... */
while (GST_IS_EVENT (buf)) {
switch (GST_EVENT_TYPE (GST_EVENT (buf))){
case GST_EVENT_EOS:
getmorebuf = FALSE;
/* FIXME Notify the srcs that EOS has happened */
gst_pad_event_default (ident->sink, GST_EVENT (buf));
break;
default:
gst_pad_event_default (ident->sink, GST_EVENT (buf));
buf = gst_pad_pull (ident->sink);
break;
}
/* handle DISCONT events, please */
}
typefindbuf = buf;
getmorebuf = FALSE;
/* FIXME merging doesn't work for some reason so
* we'll just typefind with the first element
if (!typefindbuf){
typefindbuf = buf;
gst_buffer_ref(buf);
}
else {
GstBuffer *oldbuf = typefindbuf;
typefindbuf = gst_buffer_merge(typefindbuf, buf);
gst_buffer_unref(oldbuf);
gst_buffer_unref(buf);
}
*/
}
if (!typefindbuf){
/* get a bytestream object */
bs = gst_bytestream_new (ident->sink);
if (gst_bytestream_peek (bs, &buf, 1) != 1 || !buf) {
buf = NULL;
g_warning ("Failed to read fake buffer - serious idiocy going on here");
goto end;
} else {
gst_buffer_unref (buf);
buf = NULL;
}
/* maybe there are already valid caps now? */
......@@ -487,7 +448,7 @@ gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *ident)
GstTypeFindFunc typefindfunc = (GstTypeFindFunc)factory->typefindfunc;
GST_DEBUG ("trying typefind function %s", GST_PLUGIN_FEATURE_NAME (factory));
if (typefindfunc && (caps = typefindfunc (buf, factory))) {
if (typefindfunc && (caps = typefindfunc (bs, factory))) {
GST_INFO ("typefind function %s found caps", GST_PLUGIN_FEATURE_NAME (factory));
if (gst_pad_try_set_caps (ident->src, caps) <= 0) {
g_warning ("typefind: found type but peer didn't accept it");
......@@ -501,7 +462,6 @@ gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *ident)
type_list = g_list_next (type_list);
}
gst_element_error(GST_ELEMENT(ident), "Could not find media type", NULL);
gst_buffer_unref(buf);
buf = GST_BUFFER (gst_event_new (GST_EVENT_EOS));
end:
......@@ -512,15 +472,19 @@ end:
/* push the buffer */
gst_spider_identity_chain (ident->sink, buf);
/* bytestream no longer needed */
gst_bytestream_destroy (bs);
return;
plug:
gst_caps_debug (caps, "spider starting caps");
gst_caps_sink (caps);
gst_spider_identity_plug (ident);
gst_spider_identity_plug (ident);
gst_bytestream_read (bs, &buf, bs->listavail);
goto end;
}
......
......@@ -28,7 +28,7 @@
#include <stdlib.h>
#include <gst/gstinfo.h>
#include "bytestream.h"
#include <gst/gstbytestream.h>
GST_DEBUG_CATEGORY_STATIC(debug_bs);
#define GST_CAT_DEFAULT debug_bs
......@@ -744,18 +744,3 @@ gst_bytestream_print_status (GstByteStream * bs)
GST_BUFFER_OFFSET (buf), GST_BUFFER_SIZE (buf));
}
}
static gboolean
plugin_init (GModule *module, GstPlugin *plugin)
{
gst_plugin_set_longname (plugin, "GstByteStream: a byte-oriented layer on top of buffer-passing");
return TRUE;
}
GstPluginDesc plugin_desc = {
GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"gstbytestream",
plugin_init
};
......@@ -20,7 +20,9 @@
#ifndef __GST_BYTESTREAM_H__
#define __GST_BYTESTREAM_H__
#include <gst/gst.h>
#include <glib.h>
#include <gst/gstpad.h>
#include <gst/gstevent.h>
G_BEGIN_DECLS
......
......@@ -29,6 +29,7 @@
#include "gst_private.h"
#include "gstbytestream.h"
#include "gsttype.h"
#include "gstregistrypool.h"
#include "gstobject.h"
......@@ -42,9 +43,7 @@ static guint16 _gst_maxtype;
static void gst_type_factory_class_init (GstTypeFactoryClass *klass);
static void gst_type_factory_init (GstTypeFactory *factory);
static GstCaps* gst_type_type_find_dummy (GstBuffer *buffer, gpointer priv);
static void gst_type_factory_unload_thyself (GstPluginFeature *feature);
static void gst_type_factory_unload_thyself (GstPluginFeature *feature);
static GstPluginFeatureClass *parent_class = NULL;
/* static guint gst_type_factory_signals[LAST_SIGNAL] = { 0 }; */
......@@ -315,8 +314,8 @@ gst_type_factory_unload_thyself (GstPluginFeature *feature)
factory->typefindfunc = gst_type_type_find_dummy;
}
static GstCaps*
gst_type_type_find_dummy (GstBuffer *buffer, gpointer priv)
GstCaps*
gst_type_type_find_dummy (GstByteStream *bs, gpointer priv)
{
GstCaps *res = NULL;
GstTypeFactory *factory = (GstTypeFactory *)priv;
......@@ -329,7 +328,7 @@ gst_type_type_find_dummy (GstBuffer *buffer, gpointer priv)
g_warning ("could not load valid typefind function for %s\n", factory->mime);
}
else if (factory->typefindfunc) {
res = factory->typefindfunc (buffer, factory);
res = factory->typefindfunc (bs, priv);
}
}
......
......@@ -24,14 +24,14 @@
#ifndef __GST_TYPE_H__
#define __GST_TYPE_H__
#include <gst/gstbuffer.h>
#include <gst/gstcaps.h>
#include <gst/gstpluginfeature.h>
#include <gst/gstbytestream.h>
G_BEGIN_DECLS
/* type of function used to check a stream for equality with type */
typedef GstCaps* (*GstTypeFindFunc) (GstBuffer *buf, gpointer priv);
typedef GstCaps* (*GstTypeFindFunc) (GstByteStream *bs, gpointer priv);
typedef struct _GstType GstType;
typedef struct _GstTypeDefinition GstTypeDefinition;
......@@ -74,7 +74,7 @@ struct _GstTypeFactory {
struct _GstTypeFactoryClass {
GstPluginFeatureClass parent;
gpointer dummy[8];
gpointer dummy[8];
};
......@@ -98,6 +98,9 @@ GstType* gst_type_find_by_id (guint16 id);
/* get the list of registered types (returns list of GstType!) */
const GList* gst_type_get_list (void);
/* dummy typefind function */
GstCaps* gst_type_type_find_dummy (GstByteStream *bs, gpointer priv);
G_END_DECLS
#endif /* __GST_TYPE_H__ */
......@@ -26,8 +26,6 @@
#include "gstinfo.h"
#include "gsttypefind.h"
#define DEFAULT_MAX_BUFFERS 1
GstElementDetails gst_type_find_details = {
"TypeFind",
"Generic",
......@@ -39,6 +37,13 @@ GstElementDetails gst_type_find_details = {
"(C) 1999",
};
/* generic templates */
GST_PAD_TEMPLATE_FACTORY (type_find_sink_factory,
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
NULL
);
/* TypeFind signals and args */
enum {
......@@ -49,7 +54,6 @@ enum {
enum {
ARG_0,
ARG_CAPS,
ARG_MAX_BUFFERS,
};
......@@ -63,7 +67,7 @@ static void gst_type_find_get_property (GObject *object, guint prop_id,
GValue *value,
GParamSpec *pspec);
static void gst_type_find_chain (GstPad *pad, GstBuffer *buf);
static void gst_type_find_loopfunc (GstElement *element);
static GstElementStateReturn
gst_type_find_change_state (GstElement *element);
......@@ -88,7 +92,9 @@ gst_type_find_get_type (void)
(GInstanceInitFunc)gst_type_find_init,
NULL
};
typefind_type = g_type_register_static (GST_TYPE_ELEMENT, "GstTypeFind", &typefind_info, 0);
typefind_type = g_type_register_static (GST_TYPE_ELEMENT,
"GstTypeFind",
&typefind_info, 0);
}
return typefind_type;
}
......@@ -106,11 +112,6 @@ gst_type_find_class_init (GstTypeFindClass *klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CAPS,
g_param_spec_pointer ("caps", "Caps", "Found capabilities", G_PARAM_READABLE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BUFFERS,
g_param_spec_int ("max_buffers",
"Max Buffers",
"Maximal amount of buffers before giving en error (0 == unlimited)",
0, G_MAXINT, DEFAULT_MAX_BUFFERS, G_PARAM_READWRITE));
gst_type_find_signals[HAVE_TYPE] =
g_signal_new ("have_type", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
......@@ -127,12 +128,13 @@ gst_type_find_class_init (GstTypeFindClass *klass)
static void
gst_type_find_init (GstTypeFind *typefind)
{
typefind->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
typefind->sinkpad = gst_pad_new_from_template (
GST_PAD_TEMPLATE_GET (type_find_sink_factory), "sink");
gst_element_add_pad (GST_ELEMENT (typefind), typefind->sinkpad);
gst_pad_set_chain_function (typefind->sinkpad, gst_type_find_chain);
typefind->num_buffer = 0;
typefind->max_buffers = DEFAULT_MAX_BUFFERS;
gst_element_set_loop_function (GST_ELEMENT (typefind),
gst_type_find_loopfunc);
typefind->caps = NULL;
}
......@@ -147,9 +149,6 @@ gst_type_find_set_property (GObject *object, guint prop_id,
typefind = GST_TYPE_FIND (object);
switch (prop_id) {
case ARG_MAX_BUFFERS:
typefind->max_buffers = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
......@@ -170,9 +169,6 @@ gst_type_find_get_property (GObject *object, guint prop_id,
case ARG_CAPS:
g_value_set_pointer (value, typefind->caps);
break;
case ARG_MAX_BUFFERS:
g_value_set_int (value, typefind->max_buffers);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
......@@ -180,18 +176,16 @@ gst_type_find_get_property (GObject *object, guint prop_id,
}
static void
gst_type_find_chain (GstPad *pad, GstBuffer *buf)
gst_type_find_loopfunc (GstElement *element)
{
GstTypeFind *typefind;
const GList *type_list;
GstType *type;
g_return_if_fail (GST_IS_PAD (pad));
typefind = GST_TYPE_FIND (GST_OBJECT_PARENT (pad));
typefind = GST_TYPE_FIND (element);
GST_DEBUG ("got buffer of %d bytes in '%s'",
GST_BUFFER_SIZE (buf), GST_OBJECT_NAME (typefind));
GST_DEBUG ("Started typefinding loop in '%s'",
GST_OBJECT_NAME (typefind));
type_list = gst_type_get_list ();
......@@ -203,42 +197,34 @@ gst_type_find_chain (GstPad *pad, GstBuffer *buf)
while (factories) {
GstTypeFactory *factory = GST_TYPE_FACTORY (factories->data);
GstTypeFindFunc typefindfunc = (GstTypeFindFunc)factory->typefindfunc;
GstTypeFindFunc typefindfunc = (GstTypeFindFunc) factory->typefindfunc;
GstCaps *caps;
GST_CAT_DEBUG (GST_CAT_TYPES, "try type (%p) :%d \"%s\" %p",
factory, type->id, type->mime, typefindfunc);
if (typefindfunc && (caps = typefindfunc (buf, factory))) {
if (typefindfunc && (caps = typefindfunc (typefind->bs, factory))) {
GST_CAT_DEBUG (GST_CAT_TYPES, "found type: %d \"%s\" \"%s\"",
caps->id, type->mime, gst_caps_get_name (caps));
typefind->caps = caps;
gst_caps_replace (&typefind->caps, caps);
if (gst_pad_try_set_caps (pad, caps) <= 0) {
if (gst_pad_try_set_caps (typefind->sinkpad, caps) <= 0) {
g_warning ("typefind: found type but peer didn't accept it");
}
{
gst_object_ref (GST_OBJECT (typefind));
g_signal_emit (G_OBJECT (typefind), gst_type_find_signals[HAVE_TYPE], 0,
typefind->caps);
gst_object_unref (GST_OBJECT (typefind));
goto end;
}
gst_object_ref (GST_OBJECT (typefind));
g_signal_emit (G_OBJECT (typefind), gst_type_find_signals[HAVE_TYPE],
0, typefind->caps);
gst_object_unref (GST_OBJECT (typefind));
return;
}
factories = g_slist_next (factories);
}
type_list = g_list_next (type_list);
}
typefind->num_buffer++;
end:
gst_buffer_unref (buf);
if (typefind->max_buffers && typefind->num_buffer >= typefind->max_buffers) {
gst_element_error (GST_ELEMENT (typefind),
"typefind could not determine type after %d buffers", typefind->num_buffer);
}
/* if we get here, nothing worked... :'(. */
gst_element_error (GST_ELEMENT (typefind),
"media type could not be detected");
}
static GstElementStateReturn
......@@ -250,17 +236,14 @@ gst_type_find_change_state (GstElement *element)
typefind = GST_TYPE_FIND (element);
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
break;
case GST_STATE_READY_TO_PAUSED:
typefind->num_buffer = 0;
gst_caps_unref (typefind->caps);
typefind->caps = NULL;
typefind->bs = gst_bytestream_new (typefind->sinkpad);
break;
case GST_STATE_PAUSED_TO_PLAYING:
case GST_STATE_PLAYING_TO_PAUSED:
case GST_STATE_PAUSED_TO_READY:
case GST_STATE_READY_TO_NULL:
gst_bytestream_destroy (typefind->bs);
gst_caps_replace (&typefind->caps, NULL);
break;
default:
break;
}
......
......@@ -27,6 +27,7 @@
#ifndef GST_DISABLE_TYPE_FIND
#include <gst/gstelement.h>
#include <gst/gstbytestream.h>
G_BEGIN_DECLS
......@@ -46,11 +47,9 @@ struct _GstTypeFind {
GstElement element;
GstPad *sinkpad;
GstByteStream *bs;
GstCaps *caps;
gint num_buffer;
gint max_buffers;
};
struct _GstTypeFindClass {
......
......@@ -711,29 +711,6 @@ gst_xml_registry_parse_element_factory (GMarkupParseContext *context, const gcha
return TRUE;
}
static GstCaps*
gst_type_type_find_dummy (GstBuffer *buffer, gpointer priv)
{
GstTypeFactory *factory = (GstTypeFactory *)priv;
GST_CAT_DEBUG (GST_CAT_TYPES,"gsttype: need to load typefind function for %s", factory->mime);
if (gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory))) {
if (factory->typefindfunc) {
if (factory->typefindfunc == gst_type_type_find_dummy) {
GST_CAT_WARNING (GST_CAT_TYPES, "GstTypeFactory %s for mime %s exts %s does not install a valid typefindfunc",
factory->feature.name, factory->mime, factory->exts);
} else {
GstCaps *res = factory->typefindfunc (buffer, factory);
if (res)
return res;
}
}
}
return NULL;
}
static gboolean
gst_xml_registry_parse_type_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
gsize text_len, GstXMLRegistry *registry, GError **error)
......
SUBDIRS = bytestream control getbits
SUBDIRS = control getbits
DIST_SUBDIRS = bytestream control getbits
DIST_SUBDIRS = control getbits
librarydir = $(libdir)/gstreamer-@GST_MAJORMINOR@
library_LTLIBRARIES = libgstbytestream.la
noinst_LTLIBRARIES = libgstbstest.la
libgstbytestreamincludedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/bytestream
libgstbytestreaminclude_HEADERS = bytestream.h
libgstbytestream_la_SOURCES = bytestream.c
libgstbytestream_la_CFLAGS = $(GST_CFLAGS)
libgstbytestream_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstbstest_la_SOURCES = bstest.c
libgstbstest_la_CFLAGS = $(GST_CFLAGS)
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstidentity.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.