From 499659f65ff7c5766427f5458ad97680f00a6c9c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 12 Apr 2005 10:52:55 +0000 Subject: [PATCH] Added typefind helper. Original commit message from CVS: Added typefind helper. Small preroll fix in the base sink. Disable typefind code in basesrc. Crude port of typefindelement. Fakesrc cleanups. --- ChangeLog | 53 +++++++- gst/base/Makefile.am | 14 +- gst/base/gstbasesink.c | 6 +- gst/base/gstbasesrc.c | 119 +++-------------- gst/base/gsttypefindhelper.c | 131 ++++++++++++++++++ gst/base/gsttypefindhelper.h | 34 +++++ gst/elements/Makefile.am | 8 +- gst/elements/gstelements.c | 2 +- gst/elements/gstfakesink.c | 2 +- gst/elements/gstfakesrc.c | 160 ++++++++++------------ gst/elements/gstfakesrc.h | 2 - gst/elements/gstfilesrc.c | 8 ++ gst/elements/gsttypefindelement.c | 244 ++++++++++++++++++++++------------ gst/elements/gsttypefindelement.h | 1 - gst/gstpipeline.c | 1 + libs/gst/base/Makefile.am | 14 +- libs/gst/base/gstbasesink.c | 6 +- libs/gst/base/gstbasesrc.c | 119 +++-------------- libs/gst/base/gsttypefindhelper.c | 131 ++++++++++++++++++ libs/gst/base/gsttypefindhelper.h | 34 +++++ plugins/elements/Makefile.am | 8 +- plugins/elements/gstelements.c | 2 +- plugins/elements/gstfakesink.c | 2 +- plugins/elements/gstfakesrc.c | 160 ++++++++++------------ plugins/elements/gstfakesrc.h | 2 - plugins/elements/gstfilesrc.c | 8 ++ plugins/elements/gsttypefindelement.c | 244 ++++++++++++++++++++++------------ plugins/elements/gsttypefindelement.h | 1 - 28 files changed, 933 insertions(+), 583 deletions(-) create mode 100644 gst/base/gsttypefindhelper.c create mode 100644 gst/base/gsttypefindhelper.h create mode 100644 libs/gst/base/gsttypefindhelper.c create mode 100644 libs/gst/base/gsttypefindhelper.h diff --git a/ChangeLog b/ChangeLog index 57f2f9c..c04b93a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,55 @@ -2005-04-11 set REAL_NAME environment variable +2005-04-12 Wim Taymans + + * gst/base/Makefile.am: + * gst/base/gstbasesink.c: (gst_basesink_base_init), + (gst_basesink_pad_getcaps), (gst_basesink_init), + (gst_basesink_event), (gst_basesink_change_state): + * gst/base/gstbasesrc.c: (gst_basesrc_get_type), + (gst_basesrc_init), (gst_basesrc_query), + (gst_basesrc_get_event_mask), (gst_basesrc_do_seek), + (gst_basesrc_event_handler), (gst_basesrc_get_range_unlocked), + (gst_basesrc_check_get_range), (gst_basesrc_loop), + (gst_basesrc_unlock), (gst_basesrc_get_size), (gst_basesrc_start), + (gst_basesrc_stop), (gst_basesrc_activate), + (gst_basesrc_change_state): + * gst/base/gsttypefindhelper.c: (helper_find_peek), + (helper_find_suggest), (gst_type_find_helper): + * gst/base/gsttypefindhelper.h: + * gst/elements/Makefile.am: + * gst/elements/gstelements.c: + * gst/elements/gstfakesink.c: (gst_fakesink_class_init), + (gst_fakesink_get_times), (gst_fakesink_event), + (gst_fakesink_preroll), (gst_fakesink_render): + * gst/elements/gstfakesrc.c: (gst_fakesrc_class_init), + (gst_fakesrc_init), (gst_fakesrc_event_handler), + (gst_fakesrc_get_property), (gst_fakesrc_create), + (gst_fakesrc_start), (gst_fakesrc_stop): + * gst/elements/gstfakesrc.h: + * gst/elements/gstfilesrc.c: (gst_filesrc_class_init), + (gst_filesrc_free_parent_mmap), (gst_filesrc_map_region), + (gst_filesrc_map_small_region), (gst_filesrc_create_mmap), + (gst_filesrc_create_read), (gst_filesrc_create), + (gst_filesrc_is_seekable), (gst_filesrc_get_size), + (gst_filesrc_start): + * gst/elements/gsttypefindelement.c: + (gst_type_find_element_have_type), (gst_type_find_element_init), + (start_typefinding), (stop_typefinding), (push_buffer_store), + (gst_type_find_element_handle_event), + (gst_type_find_element_chain), + (gst_type_find_element_checkgetrange), + (gst_type_find_element_getrange), (do_typefind), + (gst_type_find_element_activate), + (gst_type_find_element_change_state): + * gst/elements/gsttypefindelement.h: + * gst/gstpipeline.c: (pipeline_bus_handler): + Added typefind helper. + Small preroll fix in the base sink. + Disable typefind code in basesrc. + Crude port of typefindelement. + Fakesrc cleanups. + + +2005-04-11 Wim Taymans * check/gst/gstbus.c: (gstbus_suite): * check/gst/gstdata.c: (thread_ref), (gst_data_suite): diff --git a/gst/base/Makefile.am b/gst/base/Makefile.am index 39c382c..528f63a 100644 --- a/gst/base/Makefile.am +++ b/gst/base/Makefile.am @@ -7,9 +7,10 @@ noinst_DATA = $(as_libtool_noinst_DATA_files) libgstbase_@GST_MAJORMINOR@_la_DEPENDENCIES = \ ../libgstreamer-@GST_MAJORMINOR@.la libgstbase_@GST_MAJORMINOR@_la_SOURCES = \ - gstbasesink.c \ - gstbasesrc.c \ - gstbasetransform.c + gstbasesink.c \ + gstbasesrc.c \ + gstbasetransform.c \ + gsttypefindhelper.c libgstbase_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS) libgstbase_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS) \ @@ -20,9 +21,10 @@ libgstbase_@GST_MAJORMINOR@includedir = \ $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/base libgstbase_@GST_MAJORMINOR@include_HEADERS = \ - gstbasesink.h \ - gstbasesrc.h \ - gstbasetransform.h + gstbasesink.h \ + gstbasesrc.h \ + gstbasetransform.h \ + gsttypefindhelper.h install-data-local: as-libtool-install-data-local diff --git a/gst/base/gstbasesink.c b/gst/base/gstbasesink.c index 49696c6..6bc6ce0 100644 --- a/gst/base/gstbasesink.c +++ b/gst/base/gstbasesink.c @@ -502,9 +502,7 @@ gst_basesink_event (GstPad * pad, GstEvent * event) GST_STREAM_LOCK (pad); - GST_PREROLL_LOCK (pad); - gst_basesink_preroll_queue_empty (basesink, pad); - GST_PREROLL_UNLOCK (pad); + gst_basesink_finish_preroll (basesink, pad, NULL); GST_LOCK (basesink); need_eos = basesink->eos = TRUE; @@ -880,6 +878,8 @@ gst_basesink_change_state (GstElement * element) /* make sure the element is finished processing */ GST_STREAM_LOCK (basesink->sinkpad); GST_STREAM_UNLOCK (basesink->sinkpad); + /* clear EOS state */ + basesink->eos = FALSE; break; case GST_STATE_READY_TO_NULL: break; diff --git a/gst/base/gstbasesrc.c b/gst/base/gstbasesrc.c index 7ff18ba..47b259c 100644 --- a/gst/base/gstbasesrc.c +++ b/gst/base/gstbasesrc.c @@ -29,6 +29,7 @@ #endif #include "gstbasesrc.h" +#include "gsttypefindhelper.h" #include #define DEFAULT_BLOCKSIZE 4096 @@ -103,8 +104,6 @@ static gboolean gst_basesrc_check_get_range (GstPad * pad); static GstFlowReturn gst_basesrc_get_range (GstPad * pad, guint64 offset, guint length, GstBuffer ** buf); -static GstCaps *gst_basesrc_type_find (GstBaseSrc * src); - static void gst_basesrc_base_init (gpointer g_class) { @@ -351,8 +350,14 @@ static gboolean gst_basesrc_event_handler (GstPad * pad, GstEvent * event) { GstBaseSrc *src; + GstBaseSrcClass *bclass; + gboolean result; src = GST_BASESRC (GST_PAD_PARENT (pad)); + bclass = GST_BASESRC_GET_CLASS (src); + + if (bclass->event) + result = bclass->event (src, event); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: @@ -594,12 +599,14 @@ gst_basesrc_start (GstBaseSrc * basesrc) basesrc->segment_start = 0; /* figure out the size */ - if (bclass->get_size) + if (bclass->get_size) { result = bclass->get_size (basesrc, &basesrc->size); - else + } else { result = FALSE; + basesrc->size = -1; + } - GST_DEBUG ("size %lld", basesrc->size); + GST_DEBUG ("size %d %lld", result, basesrc->size); /* we always run to the end */ basesrc->segment_end = -1; @@ -611,12 +618,15 @@ gst_basesrc_start (GstBaseSrc * basesrc) basesrc->seekable = FALSE; /* run typefind */ +#if 0 if (basesrc->seekable) { GstCaps *caps; - caps = gst_basesrc_type_find (basesrc); + caps = gst_type_find_helper (basesrc->srcpad, basesrc->size); gst_pad_set_caps (basesrc->srcpad, caps); } +#endif + return TRUE; /* ERROR */ @@ -750,100 +760,3 @@ gst_basesrc_change_state (GstElement * element) return result; } - -/** - * typefind code here - */ -typedef struct -{ - GstBaseSrc *src; - guint best_probability; - GstCaps *caps; - - GstBuffer *buffer; -} -BaseSrcTypeFind; - -static guint8 * -basesrc_find_peek (gpointer data, gint64 offset, guint size) -{ - BaseSrcTypeFind *find; - GstBuffer *buffer; - GstBaseSrc *src; - GstFlowReturn ret; - - if (size == 0) - return NULL; - - find = (BaseSrcTypeFind *) data; - src = find->src; - - if (offset < 0) { - offset += src->size; - } - - buffer = NULL; - ret = gst_basesrc_get_range_unlocked (src->srcpad, offset, size, &buffer); - - if (find->buffer) { - gst_buffer_unref (find->buffer); - find->buffer = NULL; - } - - if (ret != GST_FLOW_OK) - goto error; - - find->buffer = buffer; - - return GST_BUFFER_DATA (buffer); - -error: - { - return NULL; - } -} - -static void -basesrc_find_suggest (gpointer data, guint probability, const GstCaps * caps) -{ - BaseSrcTypeFind *find = (BaseSrcTypeFind *) data; - - if (probability > find->best_probability) { - gst_caps_replace (&find->caps, gst_caps_copy (caps)); - find->best_probability = probability; - } -} - -static GstCaps * -gst_basesrc_type_find (GstBaseSrc * src) -{ - GstTypeFind gst_find; - BaseSrcTypeFind find; - GList *walk, *type_list = NULL; - GstCaps *result = NULL; - - walk = type_list = gst_type_find_factory_get_list (); - - find.src = src; - find.best_probability = 0; - find.caps = NULL; - find.buffer = NULL; - gst_find.data = &find; - gst_find.peek = basesrc_find_peek; - gst_find.suggest = basesrc_find_suggest; - gst_find.get_length = NULL; - - while (walk) { - GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data); - - gst_type_find_factory_call_function (factory, &gst_find); - if (find.best_probability >= GST_TYPE_FIND_MAXIMUM) - break; - walk = g_list_next (walk); - } - - if (find.best_probability > 0) - result = find.caps; - - return result; -} diff --git a/gst/base/gsttypefindhelper.c b/gst/base/gsttypefindhelper.c new file mode 100644 index 0000000..6aa44b4 --- /dev/null +++ b/gst/base/gsttypefindhelper.c @@ -0,0 +1,131 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2005 Wim Taymans + * + * gsttypefindhelper.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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gsttypefindhelper.h" + +/** + * typefind code here + */ +typedef struct +{ + GstPad *src; + guint best_probability; + GstCaps *caps; + guint64 size; + GstBuffer *buffer; +} +GstTypeFindHelper; + +static guint8 * +helper_find_peek (gpointer data, gint64 offset, guint size) +{ + GstTypeFindHelper *find; + GstBuffer *buffer; + GstPad *src; + GstFlowReturn ret; + + if (size == 0) + return NULL; + + find = (GstTypeFindHelper *) data; + src = find->src; + + if (offset < 0) { + if (find->size == -1) + return NULL; + + offset += find->size; + } + + buffer = NULL; + ret = GST_RPAD_GETRANGEFUNC (src) (src, offset, size, &buffer); + + if (find->buffer) { + gst_buffer_unref (find->buffer); + find->buffer = NULL; + } + + if (ret != GST_FLOW_OK) + goto error; + + find->buffer = buffer; + + return GST_BUFFER_DATA (buffer); + +error: + { + return NULL; + } +} + +static void +helper_find_suggest (gpointer data, guint probability, const GstCaps * caps) +{ + GstTypeFindHelper *find = (GstTypeFindHelper *) data; + + if (probability > find->best_probability) { + gst_caps_replace (&find->caps, gst_caps_copy (caps)); + find->best_probability = probability; + } +} + +GstCaps * +gst_type_find_helper (GstPad * src, guint64 size) +{ + GstTypeFind gst_find; + GstTypeFindHelper find; + GList *walk, *type_list = NULL; + GstCaps *result = NULL; + + walk = type_list = gst_type_find_factory_get_list (); + + find.src = src; + find.best_probability = 0; + find.caps = NULL; + find.size = size; + find.buffer = NULL; + gst_find.data = &find; + gst_find.peek = helper_find_peek; + gst_find.suggest = helper_find_suggest; + gst_find.get_length = NULL; + + while (walk) { + GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data); + + gst_type_find_factory_call_function (factory, &gst_find); + if (find.best_probability >= GST_TYPE_FIND_MAXIMUM) + break; + walk = g_list_next (walk); + } + + if (find.best_probability > 0) + result = find.caps; + + return result; +} diff --git a/gst/base/gsttypefindhelper.h b/gst/base/gsttypefindhelper.h new file mode 100644 index 0000000..6b1e608 --- /dev/null +++ b/gst/base/gsttypefindhelper.h @@ -0,0 +1,34 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2005 Wim Taymans + * + * gsttypefindhelper.h: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_TYPEFINDHELPER_H__ +#define __GST_TYPEFINDHELPER_H__ + +#include + +G_BEGIN_DECLS + +GstCaps * gst_type_find_helper (GstPad *src, guint64 size); + +G_END_DECLS + +#endif /* __GST_TYPEFINDHELPER_H__ */ diff --git a/gst/elements/Makefile.am b/gst/elements/Makefile.am index 1cd9bc1..8565358 100644 --- a/gst/elements/Makefile.am +++ b/gst/elements/Makefile.am @@ -24,19 +24,20 @@ endif libgstelements_la_DEPENDENCIES = ../libgstreamer-@GST_MAJORMINOR@.la libgstelements_la_SOURCES = \ + gstbufferstore.c \ gstfakesrc.c \ gstfakesink.c \ gstfilesrc.c \ gstidentity.c \ gstelements.c \ - gsttee.c + gsttee.c \ + gsttypefindelement.c # FIXME 0.9: mentioned by po/POTFILES.in, so we include them here -- # this is a short-term hack, really we should just decide the fate of # these files above, then this will be unnecessary EXTRA_DIST += \ gstaggregator.c \ - gstbufferstore.c \ gstfilesink.c \ gstfdsink.c \ gstfdsrc.c \ @@ -44,8 +45,7 @@ EXTRA_DIST += \ gstmultifilesrc.c \ gstpipefilter.c \ gstshaper.c \ - gststatistics.c \ - gsttypefindelement.c + gststatistics.c libgstelements_la_CFLAGS = $(GST_OBJ_CFLAGS) diff --git a/gst/elements/gstelements.c b/gst/elements/gstelements.c index 2099c74..249a944 100644 --- a/gst/elements/gstelements.c +++ b/gst/elements/gstelements.c @@ -71,7 +71,7 @@ static struct _elements_entry _elements[] = { // {"shaper", GST_RANK_NONE, gst_shaper_get_type}, // {"statistics", GST_RANK_NONE, gst_statistics_get_type}, {"tee", GST_RANK_NONE, gst_tee_get_type}, -// {"typefind", GST_RANK_NONE, gst_type_find_element_get_type}, + {"typefind", GST_RANK_NONE, gst_type_find_element_get_type}, // {NULL, 0}, }; diff --git a/gst/elements/gstfakesink.c b/gst/elements/gstfakesink.c index b8d483c..30a8fdb 100644 --- a/gst/elements/gstfakesink.c +++ b/gst/elements/gstfakesink.c @@ -278,7 +278,7 @@ gst_fakesink_event (GstBaseSink * bsink, GstEvent * event) g_free (sink->last_message); sink->last_message = - g_strdup_printf ("chain ******* E (type: %d) %p", + g_strdup_printf ("event ******* E (type: %d) %p", GST_EVENT_TYPE (event), event); g_object_notify (G_OBJECT (sink), "last_message"); diff --git a/gst/elements/gstfakesrc.c b/gst/elements/gstfakesrc.c index 3be5c0b..b437fa3 100644 --- a/gst/elements/gstfakesrc.c +++ b/gst/elements/gstfakesrc.c @@ -31,12 +31,6 @@ #include "gstfakesrc.h" #include -#define DEFAULT_SIZEMIN 0 -#define DEFAULT_SIZEMAX 4096 -#define DEFAULT_PARENTSIZE 4096*10 -#define DEFAULT_DATARATE 0 -#define DEFAULT_SYNC FALSE - static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, @@ -60,10 +54,25 @@ enum LAST_SIGNAL }; +#define DEFAULT_OUTPUT FAKESRC_FIRST_LAST_LOOP +#define DEFAULT_DATA FAKESRC_DATA_ALLOCATE +#define DEFAULT_SIZETYPE FAKESRC_SIZETYPE_NULL +#define DEFAULT_SIZEMIN 0 +#define DEFAULT_SIZEMAX 4096 +#define DEFAULT_FILLTYPE FAKESRC_FILLTYPE_NULL +#define DEFAULT_DATARATE 0 +#define DEFAULT_SYNC FALSE +#define DEFAULT_PATTERN NULL +#define DEFAULT_NUM_BUFFERS -1 +#define DEFAULT_EOS FALSE +#define DEFAULT_SIGNAL_HANDOFFS FALSE +#define DEFAULT_SILENT FALSE +#define DEFAULT_DUMP FALSE +#define DEFAULT_PARENTSIZE 4096*10 + enum { ARG_0, - ARG_NUM_SOURCES, ARG_OUTPUT, ARG_DATA, ARG_SIZETYPE, @@ -176,7 +185,8 @@ static void gst_fakesrc_set_property (GObject * object, guint prop_id, static void gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstElementStateReturn gst_fakesrc_change_state (GstElement * element); +static gboolean gst_fakesrc_start (GstBaseSrc * basesrc); +static gboolean gst_fakesrc_stop (GstBaseSrc * basesrc); static gboolean gst_fakesrc_event_handler (GstBaseSrc * src, GstEvent * event); static GstFlowReturn gst_fakesrc_create (GstBaseSrc * src, guint64 offset, @@ -209,19 +219,16 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property); - g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SOURCES, - g_param_spec_int ("num-sources", "num-sources", "Number of sources", - 1, G_MAXINT, 1, G_PARAM_READABLE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_OUTPUT, g_param_spec_enum ("output", "output", "Output method (currently unused)", - GST_TYPE_FAKESRC_OUTPUT, FAKESRC_FIRST_LAST_LOOP, G_PARAM_READWRITE)); + GST_TYPE_FAKESRC_OUTPUT, DEFAULT_OUTPUT, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATA, g_param_spec_enum ("data", "data", "Data allocation method", - GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE)); + GST_TYPE_FAKESRC_DATA, DEFAULT_DATA, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZETYPE, g_param_spec_enum ("sizetype", "sizetype", "How to determine buffer sizes", GST_TYPE_FAKESRC_SIZETYPE, - FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE)); + DEFAULT_SIZETYPE, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN, g_param_spec_int ("sizemin", "sizemin", "Minimum buffer size", 0, G_MAXINT, DEFAULT_SIZEMIN, G_PARAM_READWRITE)); @@ -235,7 +242,7 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILLTYPE, g_param_spec_enum ("filltype", "filltype", "How to fill the buffer, if at all", GST_TYPE_FAKESRC_FILLTYPE, - FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE)); + DEFAULT_FILLTYPE, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATARATE, g_param_spec_int ("datarate", "Datarate", "Timestamps buffers with number of bytes per second (0 = none)", 0, @@ -244,27 +251,29 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) g_param_spec_boolean ("sync", "Sync", "Sync to the clock to the datarate", DEFAULT_SYNC, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PATTERN, - g_param_spec_string ("pattern", "pattern", "pattern", NULL, + g_param_spec_string ("pattern", "pattern", "pattern", DEFAULT_PATTERN, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_BUFFERS, g_param_spec_int ("num-buffers", "num-buffers", - "Number of buffers to output before sending EOS", -1, G_MAXINT, 0, - G_PARAM_READWRITE)); + "Number of buffers to output before sending EOS", -1, G_MAXINT, + DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EOS, - g_param_spec_boolean ("eos", "eos", "Send out the EOS event?", TRUE, - G_PARAM_READWRITE)); + g_param_spec_boolean ("eos", "eos", "Send out the EOS event?", + DEFAULT_EOS, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE, g_param_spec_string ("last-message", "last-message", "The last status message", NULL, G_PARAM_READABLE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT, g_param_spec_boolean ("silent", "Silent", - "Don't produce last_message events", FALSE, G_PARAM_READWRITE)); + "Don't produce last_message events", DEFAULT_SILENT, + G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_HANDOFFS, g_param_spec_boolean ("signal-handoffs", "Signal handoffs", - "Send a signal before pushing the buffer", FALSE, G_PARAM_READWRITE)); + "Send a signal before pushing the buffer", DEFAULT_SIGNAL_HANDOFFS, + G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP, g_param_spec_boolean ("dump", "Dump", "Dump produced bytes to stdout", - FALSE, G_PARAM_READWRITE)); + DEFAULT_DUMP, G_PARAM_READWRITE)); gst_fakesrc_signals[SIGNAL_HANDOFF] = g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, @@ -272,8 +281,8 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) gst_marshal_VOID__BOXED_OBJECT, G_TYPE_NONE, 1, GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE); - gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state); - + gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_fakesrc_start); + gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_fakesrc_stop); gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_fakesrc_event_handler); gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_fakesrc_create); } @@ -284,14 +293,13 @@ gst_fakesrc_init (GstFakeSrc * fakesrc) fakesrc->output = FAKESRC_FIRST_LAST_LOOP; fakesrc->segment_start = -1; fakesrc->segment_end = -1; - fakesrc->num_buffers = -1; + fakesrc->num_buffers = DEFAULT_NUM_BUFFERS; fakesrc->rt_num_buffers = -1; fakesrc->buffer_count = 0; - fakesrc->silent = FALSE; - fakesrc->signal_handoffs = FALSE; - fakesrc->dump = FALSE; + fakesrc->silent = DEFAULT_SILENT; + fakesrc->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS; + fakesrc->dump = DEFAULT_DUMP; fakesrc->pattern_byte = 0x00; - fakesrc->need_flush = FALSE; fakesrc->data = FAKESRC_DATA_ALLOCATE; fakesrc->sizetype = FAKESRC_SIZETYPE_NULL; fakesrc->filltype = FAKESRC_FILLTYPE_NOTHING; @@ -302,7 +310,6 @@ gst_fakesrc_init (GstFakeSrc * fakesrc) fakesrc->last_message = NULL; fakesrc->datarate = DEFAULT_DATARATE; fakesrc->sync = DEFAULT_SYNC; - fakesrc->pad_mode = GST_ACTIVATE_NONE; } static gboolean @@ -312,22 +319,16 @@ gst_fakesrc_event_handler (GstBaseSrc * basesrc, GstEvent * event) src = GST_FAKESRC (basesrc); - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEEK: - src->segment_start = GST_EVENT_SEEK_OFFSET (event); - src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event); - src->buffer_count = src->segment_start; - src->segment_loop = - GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_SEGMENT_LOOP; - src->need_flush = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH; - break; - case GST_EVENT_FLUSH: - src->need_flush = TRUE; - break; - default: - break; + if (!src->silent) { + g_free (src->last_message); + + src->last_message = + g_strdup_printf ("event ******* E (type: %d) %p", + GST_EVENT_TYPE (event), event); + + g_object_notify (G_OBJECT (src), "last_message"); } - gst_event_unref (event); + return TRUE; } @@ -427,9 +428,6 @@ gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value, src = GST_FAKESRC (object); switch (prop_id) { - case ARG_NUM_SOURCES: - g_value_set_int (value, GST_ELEMENT (src)->numsrcpads); - break; case ARG_OUTPUT: g_value_set_enum (value, src->output); break; @@ -632,6 +630,8 @@ gst_fakesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length, src = GST_FAKESRC (basesrc); if (src->buffer_count == src->segment_end) { + GST_INFO ("buffer_count reaches segment_end %d %d", src->buffer_count, + src->segment_end); return GST_FLOW_UNEXPECTED; } @@ -686,51 +686,35 @@ gst_fakesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length, return GST_FLOW_OK; } -static GstElementStateReturn -gst_fakesrc_change_state (GstElement * element) +static gboolean +gst_fakesrc_start (GstBaseSrc * basesrc) { - GstFakeSrc *fakesrc; - GstElementStateReturn result = GST_STATE_FAILURE; + GstFakeSrc *src; - g_return_val_if_fail (GST_IS_FAKESRC (element), result); + src = GST_FAKESRC (basesrc); - fakesrc = GST_FAKESRC (element); + src->buffer_count = 0; + src->pattern_byte = 0x00; + src->eos = FALSE; + src->bytes_sent = 0; + src->rt_num_buffers = src->num_buffers; - switch (GST_STATE_TRANSITION (element)) { - case GST_STATE_NULL_TO_READY: - break; - case GST_STATE_READY_TO_PAUSED: - { - fakesrc->buffer_count = 0; - fakesrc->pattern_byte = 0x00; - fakesrc->need_flush = FALSE; - fakesrc->eos = FALSE; - fakesrc->bytes_sent = 0; - fakesrc->rt_num_buffers = fakesrc->num_buffers; - break; - } - case GST_STATE_PAUSED_TO_PLAYING: - break; - } + return TRUE; +} - result = GST_ELEMENT_CLASS (parent_class)->change_state (element); +static gboolean +gst_fakesrc_stop (GstBaseSrc * basesrc) +{ + GstFakeSrc *src; - switch (GST_STATE_TRANSITION (element)) { - case GST_STATE_PLAYING_TO_PAUSED: - break; - case GST_STATE_PAUSED_TO_READY: - if (fakesrc->parent) { - gst_buffer_unref (fakesrc->parent); - fakesrc->parent = NULL; - } - g_free (fakesrc->last_message); - fakesrc->last_message = NULL; - break; - case GST_STATE_READY_TO_NULL: - break; - default: - break; + src = GST_FAKESRC (basesrc); + + if (src->parent) { + gst_buffer_unref (src->parent); + src->parent = NULL; } + g_free (src->last_message); + src->last_message = NULL; - return result; + return TRUE; } diff --git a/gst/elements/gstfakesrc.h b/gst/elements/gstfakesrc.h index 3cda131..af286fd 100644 --- a/gst/elements/gstfakesrc.h +++ b/gst/elements/gstfakesrc.h @@ -84,7 +84,6 @@ struct _GstFakeSrc { GstFakeSrcDataType data; GstFakeSrcSizeType sizetype; GstFakeSrcFillType filltype; - GstActivateMode pad_mode; guint sizemin; guint sizemax; @@ -106,7 +105,6 @@ struct _GstFakeSrc { gboolean silent; gboolean signal_handoffs; gboolean dump; - gboolean need_flush; guint64 bytes_sent; diff --git a/gst/elements/gstfilesrc.c b/gst/elements/gstfilesrc.c index 2c60acd..22f93d5 100644 --- a/gst/elements/gstfilesrc.c +++ b/gst/elements/gstfilesrc.c @@ -135,6 +135,7 @@ static void gst_filesrc_get_property (GObject * object, guint prop_id, static gboolean gst_filesrc_start (GstBaseSrc * basesrc); static gboolean gst_filesrc_stop (GstBaseSrc * basesrc); +static gboolean gst_filesrc_is_seekable (GstBaseSrc * src); static gboolean gst_filesrc_get_size (GstBaseSrc * src, guint64 * size); static GstFlowReturn gst_filesrc_create (GstBaseSrc * src, guint64 offset, guint length, GstBuffer ** buffer); @@ -203,6 +204,7 @@ gst_filesrc_class_init (GstFileSrcClass * klass) gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_filesrc_start); gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_filesrc_stop); + gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_filesrc_is_seekable); gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_filesrc_get_size); gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_filesrc_create); } @@ -713,6 +715,12 @@ gst_filesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length, } static gboolean +gst_filesrc_is_seekable (GstBaseSrc * src) +{ + return TRUE; +} + +static gboolean gst_filesrc_get_size (GstBaseSrc * basesrc, guint64 * size) { struct stat stat_results; diff --git a/gst/elements/gsttypefindelement.c b/gst/elements/gsttypefindelement.c index 9c7b162..a0e9ae9 100644 --- a/gst/elements/gsttypefindelement.c +++ b/gst/elements/gsttypefindelement.c @@ -32,6 +32,19 @@ * requests * 7) goto 2 * 8) take best available result and use its caps + * + * The element has two scheduling modes: + * + * 1) chain based, it will collect buffers and run the typefind function on + * the buffer until something is found. + * 2) getrange based, it will proxy the getrange function to the sinkpad. It + * is assumed that the peer element is happy with whatever format we + * eventually read. + * + * When the element has no connected srcpad, and the sinkpad can operate in + * getrange based mode, the element starts its own task to figure out the + * type of the stream. + * */ #ifdef HAVE_CONFIG_H @@ -41,6 +54,7 @@ #include "gsttypefindelement.h" #include "gst/gst_private.h" #include "gst/gst-i18n-lib.h" +#include "gst/base/gsttypefindhelper.h" #include #include @@ -84,8 +98,6 @@ enum enum { MODE_NORMAL, /* act as identity */ - MODE_TRANSITION, /* wait for the discont between the two - * other modes */ MODE_TYPEFIND /* do typefinding */ }; @@ -108,11 +120,19 @@ static gboolean gst_type_find_element_src_event (GstPad * pad, GstEvent * event); static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQueryType type, GstFormat * fmt, gint64 * value); -static void push_buffer_store (GstTypeFindElement * typefind); +static GstFlowReturn push_buffer_store (GstTypeFindElement * typefind); -static void gst_type_find_element_chain (GstPad * sinkpad, GstData * data); +static gboolean gst_type_find_element_handle_event (GstPad * pad, + GstEvent * event); +static GstFlowReturn gst_type_find_element_chain (GstPad * sinkpad, + GstBuffer * buffer); +static GstFlowReturn gst_type_find_element_getrange (GstPad * srcpad, + guint64 offset, guint length, GstBuffer ** buffer); +static gboolean gst_type_find_element_checkgetrange (GstPad * srcpad); static GstElementStateReturn gst_type_find_element_change_state (GstElement * element); +static gboolean +gst_type_find_element_activate (GstPad * pad, GstActivateMode mode); static guint gst_type_find_element_signals[LAST_SIGNAL] = { 0 }; @@ -125,8 +145,9 @@ gst_type_find_element_have_type (GstTypeFindElement * typefind, GST_INFO_OBJECT (typefind, "found caps %" GST_PTR_FORMAT, caps); typefind->caps = gst_caps_copy (caps); - gst_pad_set_explicit_caps (typefind->src, caps); + gst_pad_set_caps (typefind->src, (GstCaps *) caps); } + static void gst_type_find_element_base_init (gpointer g_class) { @@ -182,18 +203,26 @@ gst_type_find_element_init (GstTypeFindElement * typefind) typefind->sink = gst_pad_new_from_template (gst_static_pad_template_get (&type_find_element_sink_template), "sink"); + gst_pad_set_activate_function (typefind->sink, + gst_type_find_element_activate); gst_pad_set_chain_function (typefind->sink, gst_type_find_element_chain); + gst_pad_set_event_function (typefind->sink, + gst_type_find_element_handle_event); gst_element_add_pad (GST_ELEMENT (typefind), typefind->sink); /* srcpad */ typefind->src = gst_pad_new_from_template (gst_static_pad_template_get (&type_find_element_src_template), "src"); + gst_pad_set_activate_function (typefind->src, gst_type_find_element_activate); + gst_pad_set_checkgetrange_function (typefind->src, + gst_type_find_element_checkgetrange); + gst_pad_set_getrange_function (typefind->src, gst_type_find_element_getrange); gst_pad_set_event_function (typefind->src, gst_type_find_element_src_event); gst_pad_set_event_mask_function (typefind->src, gst_type_find_element_src_event_mask); gst_pad_set_query_function (typefind->src, GST_DEBUG_FUNCPTR (gst_type_find_handle_src_query)); - gst_pad_use_explicit_caps (typefind->src); + gst_pad_use_fixed_caps (typefind->src); gst_element_add_pad (GST_ELEMENT (typefind), typefind->src); typefind->caps = NULL; @@ -201,8 +230,6 @@ gst_type_find_element_init (GstTypeFindElement * typefind) typefind->max_probability = GST_TYPE_FIND_MAXIMUM; typefind->store = gst_buffer_store_new (); - - GST_FLAG_SET (typefind, GST_ELEMENT_EVENT_AWARE); } static void gst_type_find_element_dispose (GObject * object) @@ -359,7 +386,7 @@ start_typefinding (GstTypeFindElement * typefind) g_assert (typefind->possibilities == NULL); GST_DEBUG_OBJECT (typefind, "starting typefinding"); - gst_pad_unnegotiate (typefind->src); + gst_pad_set_caps (typefind->src, NULL); if (typefind->caps) { gst_caps_replace (&typefind->caps, NULL); } @@ -370,9 +397,14 @@ start_typefinding (GstTypeFindElement * typefind) static void stop_typefinding (GstTypeFindElement * typefind) { + GstElementState state; + /* stop all typefinding and set mode back to normal */ - gboolean push_cached_buffers = - gst_element_get_state (GST_ELEMENT (typefind)) == GST_STATE_PLAYING; + gboolean push_cached_buffers; + + gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, NULL); + + push_cached_buffers = (state >= GST_STATE_PAUSED); GST_DEBUG_OBJECT (typefind, "stopping typefinding%s", push_cached_buffers ? " and pushing cached buffers" : ""); @@ -384,47 +416,35 @@ stop_typefinding (GstTypeFindElement * typefind) g_list_free (typefind->possibilities); typefind->possibilities = NULL; } - - typefind->mode = MODE_TRANSITION; + //typefind->mode = MODE_TRANSITION; if (!push_cached_buffers) { gst_buffer_store_clear (typefind->store); } else { - guint size = gst_buffer_store_get_size (typefind->store, 0); - - GST_DEBUG_OBJECT (typefind, "seeking back to current position %u", size); - if (!gst_pad_send_event (GST_PAD_PEER (typefind->sink), - gst_event_new_seek (GST_SEEK_METHOD_SET | GST_FORMAT_BYTES, - size))) { - GST_WARNING_OBJECT (typefind, - "could not seek to required position %u, hope for the best", size); - typefind->mode = MODE_NORMAL; - /* push out our queued buffers here */ - push_buffer_store (typefind); - } else { - typefind->waiting_for_discont_offset = size; - } + typefind->mode = MODE_NORMAL; + /* push out our queued buffers here */ + push_buffer_store (typefind); } } -static void +static GstFlowReturn push_buffer_store (GstTypeFindElement * typefind) { guint size = gst_buffer_store_get_size (typefind->store, 0); GstBuffer *buffer; + GstFlowReturn ret; - gst_pad_push (typefind->src, GST_DATA (gst_event_new_discontinuous (TRUE, - GST_FORMAT_DEFAULT, (guint64) 0, GST_FORMAT_BYTES, (guint64) 0, - GST_FORMAT_UNDEFINED))); if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) { GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size); - gst_pad_push (typefind->src, GST_DATA (buffer)); + ret = gst_pad_push (typefind->src, buffer); } else { - /* FIXME: shouldn't we throw an error here? */ size = 0; + ret = GST_FLOW_ERROR; } gst_buffer_store_clear (typefind->store); + + return ret; } static guint64 @@ -460,9 +480,11 @@ find_element_get_length (gpointer data) return entry->self->stream_length; } -static void + +static gboolean gst_type_find_element_handle_event (GstPad * pad, GstEvent * event) { + gboolean res = FALSE; TypeFindEntry *entry; GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); @@ -485,9 +507,9 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event) 0, entry->probability, entry->caps); stop_typefinding (typefind); push_buffer_store (typefind); - gst_pad_event_default (pad, event); + res = gst_pad_event_default (pad, event); } else { - gst_pad_event_default (pad, event); + res = gst_pad_event_default (pad, event); GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL)); stop_typefinding (typefind); @@ -495,44 +517,23 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event) break; default: gst_data_unref (GST_DATA (event)); + res = TRUE; break; } break; - case MODE_TRANSITION: - if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS) { - if (GST_EVENT_DISCONT_NEW_MEDIA (event)) { - start_typefinding (typefind); - gst_event_unref (event); - } else { - guint64 off; - - if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &off) && - off == typefind->waiting_for_discont_offset) { - typefind->mode = MODE_NORMAL; - push_buffer_store (typefind); - } else { - gst_event_unref (event); - } - } - } else if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { - push_buffer_store (typefind); - gst_pad_event_default (pad, event); - } else { - gst_event_unref (event); - } - break; case MODE_NORMAL: - if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS && - GST_EVENT_DISCONT_NEW_MEDIA (event)) { + if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS) { start_typefinding (typefind); gst_event_unref (event); + res = TRUE; } else { - gst_pad_event_default (pad, event); + res = gst_pad_event_default (pad, event); } break; default: g_assert_not_reached (); } + return res; } static guint8 * find_peek (gpointer data, gint64 offset, guint size) @@ -583,6 +584,7 @@ find_suggest (gpointer data, guint probability, const GstCaps * caps) gst_caps_replace (&entry->caps, gst_caps_copy (caps)); } } + static gint compare_type_find_entry (gconstpointer a, gconstpointer b) { @@ -596,40 +598,37 @@ compare_type_find_entry (gconstpointer a, gconstpointer b) return two->probability - one->probability; } } + static gint compare_type_find_factory (gconstpointer fac1, gconstpointer fac2) { return GST_PLUGIN_FEATURE (fac1)->rank - GST_PLUGIN_FEATURE (fac2)->rank; } -static void -gst_type_find_element_chain (GstPad * pad, GstData * data) + +static GstFlowReturn +gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer) { GstTypeFindElement *typefind; GList *entries; TypeFindEntry *entry; GList *walk; + GstFlowReturn res = GST_FLOW_OK; GstTypeFind find = { find_peek, find_suggest, NULL, find_element_get_length }; typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); - if (GST_IS_EVENT (data)) { - gst_type_find_element_handle_event (pad, GST_EVENT (data)); - return; - } + switch (typefind->mode) { case MODE_NORMAL: - gst_pad_push (typefind->src, data); - return; - case MODE_TRANSITION: - gst_data_unref (data); - return; + return gst_pad_push (typefind->src, buffer); case MODE_TYPEFIND:{ guint64 current_offset; - gst_buffer_store_add_buffer (typefind->store, GST_BUFFER (data)); - current_offset = GST_BUFFER_OFFSET_IS_VALID (data) ? - GST_BUFFER_OFFSET (data) + GST_BUFFER_SIZE (data) : + gst_buffer_store_add_buffer (typefind->store, buffer); + current_offset = GST_BUFFER_OFFSET_IS_VALID (buffer) ? + GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer) : gst_buffer_store_get_size (typefind->store, 0); - gst_data_unref (data); + gst_buffer_unref (buffer); + if (typefind->possibilities == NULL) { /* not yet started, get all typefinding functions into our "queue" */ GList *all_factories = gst_type_find_factory_get_list (); @@ -800,27 +799,108 @@ gst_type_find_element_chain (GstPad * pad, GstData * data) } default: g_assert_not_reached (); - return; + return GST_FLOW_ERROR; } + + return res; } + +static gboolean +gst_type_find_element_checkgetrange (GstPad * srcpad) +{ + GstTypeFindElement *typefind; + + typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (srcpad)); + + return gst_pad_check_pull_range (typefind->sink); +} + +static GstFlowReturn +gst_type_find_element_getrange (GstPad * srcpad, + guint64 offset, guint length, GstBuffer ** buffer) +{ + GstTypeFindElement *typefind; + + typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (srcpad)); + + return gst_pad_pull_range (typefind->sink, offset, length, buffer); +} + +static gboolean +do_typefind (GstTypeFindElement * typefind) +{ + GstCaps *caps; + GstPad *peer; + + peer = gst_pad_get_peer (typefind->sink); + if (peer) { + gst_pad_peer_set_active (typefind->sink, GST_ACTIVATE_PULL); + + caps = gst_type_find_helper (peer, 0); + gst_pad_set_caps (typefind->src, caps); + + if (caps) { + g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], + 0, 100, caps); + } + + gst_object_unref (GST_OBJECT (peer)); + } + + return TRUE; +} + +static gboolean +gst_type_find_element_activate (GstPad * pad, GstActivateMode mode) +{ + gboolean result; + GstTypeFindElement *typefind; + + typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad)); + + switch (mode) { + case GST_ACTIVATE_PUSH: + case GST_ACTIVATE_PULL: + result = TRUE; + break; + default: + result = TRUE; + break; + } + + return result; +} + static GstElementStateReturn gst_type_find_element_change_state (GstElement * element) { + GstElementState transition; + GstElementStateReturn ret; GstTypeFindElement *typefind; typefind = GST_TYPE_FIND_ELEMENT (element); - switch (GST_STATE_TRANSITION (element)) { + transition = GST_STATE_TRANSITION (element); + switch (transition) { case GST_STATE_READY_TO_PAUSED: - start_typefinding (typefind); + do_typefind (typefind); + + //start_typefinding (typefind); break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { case GST_STATE_PAUSED_TO_READY: - stop_typefinding (typefind); + //stop_typefinding (typefind); gst_caps_replace (&typefind->caps, NULL); break; default: break; } - return GST_ELEMENT_CLASS (parent_class)->change_state (element); + return ret; } diff --git a/gst/elements/gsttypefindelement.h b/gst/elements/gsttypefindelement.h index 43debd5..03eeccd 100644 --- a/gst/elements/gsttypefindelement.h +++ b/gst/elements/gsttypefindelement.h @@ -53,7 +53,6 @@ struct _GstTypeFindElement { GstCaps * caps; guint mode; - guint64 waiting_for_discont_offset; GstBufferStore * store; guint64 stream_length; gboolean stream_length_available; diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index 1446fbd..62f9005 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -318,6 +318,7 @@ pipeline_bus_handler (GstBus * bus, GstMessage * message, switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_EOS: if (GST_MESSAGE_SRC (message) != GST_OBJECT (pipeline)) { + GST_DEBUG ("got EOS message"); GST_LOCK (bus); pipeline->eosed = g_list_prepend (pipeline->eosed, GST_MESSAGE_SRC (message)); diff --git a/libs/gst/base/Makefile.am b/libs/gst/base/Makefile.am index 39c382c..528f63a 100644 --- a/libs/gst/base/Makefile.am +++ b/libs/gst/base/Makefile.am @@ -7,9 +7,10 @@ noinst_DATA = $(as_libtool_noinst_DATA_files) libgstbase_@GST_MAJORMINOR@_la_DEPENDENCIES = \ ../libgstreamer-@GST_MAJORMINOR@.la libgstbase_@GST_MAJORMINOR@_la_SOURCES = \ - gstbasesink.c \ - gstbasesrc.c \ - gstbasetransform.c + gstbasesink.c \ + gstbasesrc.c \ + gstbasetransform.c \ + gsttypefindhelper.c libgstbase_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS) libgstbase_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS) \ @@ -20,9 +21,10 @@ libgstbase_@GST_MAJORMINOR@includedir = \ $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/base libgstbase_@GST_MAJORMINOR@include_HEADERS = \ - gstbasesink.h \ - gstbasesrc.h \ - gstbasetransform.h + gstbasesink.h \ + gstbasesrc.h \ + gstbasetransform.h \ + gsttypefindhelper.h install-data-local: as-libtool-install-data-local diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index 49696c6..6bc6ce0 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -502,9 +502,7 @@ gst_basesink_event (GstPad * pad, GstEvent * event) GST_STREAM_LOCK (pad); - GST_PREROLL_LOCK (pad); - gst_basesink_preroll_queue_empty (basesink, pad); - GST_PREROLL_UNLOCK (pad); + gst_basesink_finish_preroll (basesink, pad, NULL); GST_LOCK (basesink); need_eos = basesink->eos = TRUE; @@ -880,6 +878,8 @@ gst_basesink_change_state (GstElement * element) /* make sure the element is finished processing */ GST_STREAM_LOCK (basesink->sinkpad); GST_STREAM_UNLOCK (basesink->sinkpad); + /* clear EOS state */ + basesink->eos = FALSE; break; case GST_STATE_READY_TO_NULL: break; diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index 7ff18ba..47b259c 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -29,6 +29,7 @@ #endif #include "gstbasesrc.h" +#include "gsttypefindhelper.h" #include #define DEFAULT_BLOCKSIZE 4096 @@ -103,8 +104,6 @@ static gboolean gst_basesrc_check_get_range (GstPad * pad); static GstFlowReturn gst_basesrc_get_range (GstPad * pad, guint64 offset, guint length, GstBuffer ** buf); -static GstCaps *gst_basesrc_type_find (GstBaseSrc * src); - static void gst_basesrc_base_init (gpointer g_class) { @@ -351,8 +350,14 @@ static gboolean gst_basesrc_event_handler (GstPad * pad, GstEvent * event) { GstBaseSrc *src; + GstBaseSrcClass *bclass; + gboolean result; src = GST_BASESRC (GST_PAD_PARENT (pad)); + bclass = GST_BASESRC_GET_CLASS (src); + + if (bclass->event) + result = bclass->event (src, event); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: @@ -594,12 +599,14 @@ gst_basesrc_start (GstBaseSrc * basesrc) basesrc->segment_start = 0; /* figure out the size */ - if (bclass->get_size) + if (bclass->get_size) { result = bclass->get_size (basesrc, &basesrc->size); - else + } else { result = FALSE; + basesrc->size = -1; + } - GST_DEBUG ("size %lld", basesrc->size); + GST_DEBUG ("size %d %lld", result, basesrc->size); /* we always run to the end */ basesrc->segment_end = -1; @@ -611,12 +618,15 @@ gst_basesrc_start (GstBaseSrc * basesrc) basesrc->seekable = FALSE; /* run typefind */ +#if 0 if (basesrc->seekable) { GstCaps *caps; - caps = gst_basesrc_type_find (basesrc); + caps = gst_type_find_helper (basesrc->srcpad, basesrc->size); gst_pad_set_caps (basesrc->srcpad, caps); } +#endif + return TRUE; /* ERROR */ @@ -750,100 +760,3 @@ gst_basesrc_change_state (GstElement * element) return result; } - -/** - * typefind code here - */ -typedef struct -{ - GstBaseSrc *src; - guint best_probability; - GstCaps *caps; - - GstBuffer *buffer; -} -BaseSrcTypeFind; - -static guint8 * -basesrc_find_peek (gpointer data, gint64 offset, guint size) -{ - BaseSrcTypeFind *find; - GstBuffer *buffer; - GstBaseSrc *src; - GstFlowReturn ret; - - if (size == 0) - return NULL; - - find = (BaseSrcTypeFind *) data; - src = find->src; - - if (offset < 0) { - offset += src->size; - } - - buffer = NULL; - ret = gst_basesrc_get_range_unlocked (src->srcpad, offset, size, &buffer); - - if (find->buffer) { - gst_buffer_unref (find->buffer); - find->buffer = NULL; - } - - if (ret != GST_FLOW_OK) - goto error; - - find->buffer = buffer; - - return GST_BUFFER_DATA (buffer); - -error: - { - return NULL; - } -} - -static void -basesrc_find_suggest (gpointer data, guint probability, const GstCaps * caps) -{ - BaseSrcTypeFind *find = (BaseSrcTypeFind *) data; - - if (probability > find->best_probability) { - gst_caps_replace (&find->caps, gst_caps_copy (caps)); - find->best_probability = probability; - } -} - -static GstCaps * -gst_basesrc_type_find (GstBaseSrc * src) -{ - GstTypeFind gst_find; - BaseSrcTypeFind find; - GList *walk, *type_list = NULL; - GstCaps *result = NULL; - - walk = type_list = gst_type_find_factory_get_list (); - - find.src = src; - find.best_probability = 0; - find.caps = NULL; - find.buffer = NULL; - gst_find.data = &find; - gst_find.peek = basesrc_find_peek; - gst_find.suggest = basesrc_find_suggest; - gst_find.get_length = NULL; - - while (walk) { - GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data); - - gst_type_find_factory_call_function (factory, &gst_find); - if (find.best_probability >= GST_TYPE_FIND_MAXIMUM) - break; - walk = g_list_next (walk); - } - - if (find.best_probability > 0) - result = find.caps; - - return result; -} diff --git a/libs/gst/base/gsttypefindhelper.c b/libs/gst/base/gsttypefindhelper.c new file mode 100644 index 0000000..6aa44b4 --- /dev/null +++ b/libs/gst/base/gsttypefindhelper.c @@ -0,0 +1,131 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2005 Wim Taymans + * + * gsttypefindhelper.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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gsttypefindhelper.h" + +/** + * typefind code here + */ +typedef struct +{ + GstPad *src; + guint best_probability; + GstCaps *caps; + guint64 size; + GstBuffer *buffer; +} +GstTypeFindHelper; + +static guint8 * +helper_find_peek (gpointer data, gint64 offset, guint size) +{ + GstTypeFindHelper *find; + GstBuffer *buffer; + GstPad *src; + GstFlowReturn ret; + + if (size == 0) + return NULL; + + find = (GstTypeFindHelper *) data; + src = find->src; + + if (offset < 0) { + if (find->size == -1) + return NULL; + + offset += find->size; + } + + buffer = NULL; + ret = GST_RPAD_GETRANGEFUNC (src) (src, offset, size, &buffer); + + if (find->buffer) { + gst_buffer_unref (find->buffer); + find->buffer = NULL; + } + + if (ret != GST_FLOW_OK) + goto error; + + find->buffer = buffer; + + return GST_BUFFER_DATA (buffer); + +error: + { + return NULL; + } +} + +static void +helper_find_suggest (gpointer data, guint probability, const GstCaps * caps) +{ + GstTypeFindHelper *find = (GstTypeFindHelper *) data; + + if (probability > find->best_probability) { + gst_caps_replace (&find->caps, gst_caps_copy (caps)); + find->best_probability = probability; + } +} + +GstCaps * +gst_type_find_helper (GstPad * src, guint64 size) +{ + GstTypeFind gst_find; + GstTypeFindHelper find; + GList *walk, *type_list = NULL; + GstCaps *result = NULL; + + walk = type_list = gst_type_find_factory_get_list (); + + find.src = src; + find.best_probability = 0; + find.caps = NULL; + find.size = size; + find.buffer = NULL; + gst_find.data = &find; + gst_find.peek = helper_find_peek; + gst_find.suggest = helper_find_suggest; + gst_find.get_length = NULL; + + while (walk) { + GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data); + + gst_type_find_factory_call_function (factory, &gst_find); + if (find.best_probability >= GST_TYPE_FIND_MAXIMUM) + break; + walk = g_list_next (walk); + } + + if (find.best_probability > 0) + result = find.caps; + + return result; +} diff --git a/libs/gst/base/gsttypefindhelper.h b/libs/gst/base/gsttypefindhelper.h new file mode 100644 index 0000000..6b1e608 --- /dev/null +++ b/libs/gst/base/gsttypefindhelper.h @@ -0,0 +1,34 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2005 Wim Taymans + * + * gsttypefindhelper.h: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_TYPEFINDHELPER_H__ +#define __GST_TYPEFINDHELPER_H__ + +#include + +G_BEGIN_DECLS + +GstCaps * gst_type_find_helper (GstPad *src, guint64 size); + +G_END_DECLS + +#endif /* __GST_TYPEFINDHELPER_H__ */ diff --git a/plugins/elements/Makefile.am b/plugins/elements/Makefile.am index 1cd9bc1..8565358 100644 --- a/plugins/elements/Makefile.am +++ b/plugins/elements/Makefile.am @@ -24,19 +24,20 @@ endif libgstelements_la_DEPENDENCIES = ../libgstreamer-@GST_MAJORMINOR@.la libgstelements_la_SOURCES = \ + gstbufferstore.c \ gstfakesrc.c \ gstfakesink.c \ gstfilesrc.c \ gstidentity.c \ gstelements.c \ - gsttee.c + gsttee.c \ + gsttypefindelement.c # FIXME 0.9: mentioned by po/POTFILES.in, so we include them here -- # this is a short-term hack, really we should just decide the fate of # these files above, then this will be unnecessary EXTRA_DIST += \ gstaggregator.c \ - gstbufferstore.c \ gstfilesink.c \ gstfdsink.c \ gstfdsrc.c \ @@ -44,8 +45,7 @@ EXTRA_DIST += \ gstmultifilesrc.c \ gstpipefilter.c \ gstshaper.c \ - gststatistics.c \ - gsttypefindelement.c + gststatistics.c libgstelements_la_CFLAGS = $(GST_OBJ_CFLAGS) diff --git a/plugins/elements/gstelements.c b/plugins/elements/gstelements.c index 2099c74..249a944 100644 --- a/plugins/elements/gstelements.c +++ b/plugins/elements/gstelements.c @@ -71,7 +71,7 @@ static struct _elements_entry _elements[] = { // {"shaper", GST_RANK_NONE, gst_shaper_get_type}, // {"statistics", GST_RANK_NONE, gst_statistics_get_type}, {"tee", GST_RANK_NONE, gst_tee_get_type}, -// {"typefind", GST_RANK_NONE, gst_type_find_element_get_type}, + {"typefind", GST_RANK_NONE, gst_type_find_element_get_type}, // {NULL, 0}, }; diff --git a/plugins/elements/gstfakesink.c b/plugins/elements/gstfakesink.c index b8d483c..30a8fdb 100644 --- a/plugins/elements/gstfakesink.c +++ b/plugins/elements/gstfakesink.c @@ -278,7 +278,7 @@ gst_fakesink_event (GstBaseSink * bsink, GstEvent * event) g_free (sink->last_message); sink->last_message = - g_strdup_printf ("chain ******* E (type: %d) %p", + g_strdup_printf ("event ******* E (type: %d) %p", GST_EVENT_TYPE (event), event); g_object_notify (G_OBJECT (sink), "last_message"); diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c index 3be5c0b..b437fa3 100644 --- a/plugins/elements/gstfakesrc.c +++ b/plugins/elements/gstfakesrc.c @@ -31,12 +31,6 @@ #include "gstfakesrc.h" #include -#define DEFAULT_SIZEMIN 0 -#define DEFAULT_SIZEMAX 4096 -#define DEFAULT_PARENTSIZE 4096*10 -#define DEFAULT_DATARATE 0 -#define DEFAULT_SYNC FALSE - static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, @@ -60,10 +54,25 @@ enum LAST_SIGNAL }; +#define DEFAULT_OUTPUT FAKESRC_FIRST_LAST_LOOP +#define DEFAULT_DATA FAKESRC_DATA_ALLOCATE +#define DEFAULT_SIZETYPE FAKESRC_SIZETYPE_NULL +#define DEFAULT_SIZEMIN 0 +#define DEFAULT_SIZEMAX 4096 +#define DEFAULT_FILLTYPE FAKESRC_FILLTYPE_NULL +#define DEFAULT_DATARATE 0 +#define DEFAULT_SYNC FALSE +#define DEFAULT_PATTERN NULL +#define DEFAULT_NUM_BUFFERS -1 +#define DEFAULT_EOS FALSE +#define DEFAULT_SIGNAL_HANDOFFS FALSE +#define DEFAULT_SILENT FALSE +#define DEFAULT_DUMP FALSE +#define DEFAULT_PARENTSIZE 4096*10 + enum { ARG_0, - ARG_NUM_SOURCES, ARG_OUTPUT, ARG_DATA, ARG_SIZETYPE, @@ -176,7 +185,8 @@ static void gst_fakesrc_set_property (GObject * object, guint prop_id, static void gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstElementStateReturn gst_fakesrc_change_state (GstElement * element); +static gboolean gst_fakesrc_start (GstBaseSrc * basesrc); +static gboolean gst_fakesrc_stop (GstBaseSrc * basesrc); static gboolean gst_fakesrc_event_handler (GstBaseSrc * src, GstEvent * event); static GstFlowReturn gst_fakesrc_create (GstBaseSrc * src, guint64 offset, @@ -209,19 +219,16 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property); - g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SOURCES, - g_param_spec_int ("num-sources", "num-sources", "Number of sources", - 1, G_MAXINT, 1, G_PARAM_READABLE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_OUTPUT, g_param_spec_enum ("output", "output", "Output method (currently unused)", - GST_TYPE_FAKESRC_OUTPUT, FAKESRC_FIRST_LAST_LOOP, G_PARAM_READWRITE)); + GST_TYPE_FAKESRC_OUTPUT, DEFAULT_OUTPUT, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATA, g_param_spec_enum ("data", "data", "Data allocation method", - GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE)); + GST_TYPE_FAKESRC_DATA, DEFAULT_DATA, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZETYPE, g_param_spec_enum ("sizetype", "sizetype", "How to determine buffer sizes", GST_TYPE_FAKESRC_SIZETYPE, - FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE)); + DEFAULT_SIZETYPE, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN, g_param_spec_int ("sizemin", "sizemin", "Minimum buffer size", 0, G_MAXINT, DEFAULT_SIZEMIN, G_PARAM_READWRITE)); @@ -235,7 +242,7 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILLTYPE, g_param_spec_enum ("filltype", "filltype", "How to fill the buffer, if at all", GST_TYPE_FAKESRC_FILLTYPE, - FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE)); + DEFAULT_FILLTYPE, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATARATE, g_param_spec_int ("datarate", "Datarate", "Timestamps buffers with number of bytes per second (0 = none)", 0, @@ -244,27 +251,29 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) g_param_spec_boolean ("sync", "Sync", "Sync to the clock to the datarate", DEFAULT_SYNC, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PATTERN, - g_param_spec_string ("pattern", "pattern", "pattern", NULL, + g_param_spec_string ("pattern", "pattern", "pattern", DEFAULT_PATTERN, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_BUFFERS, g_param_spec_int ("num-buffers", "num-buffers", - "Number of buffers to output before sending EOS", -1, G_MAXINT, 0, - G_PARAM_READWRITE)); + "Number of buffers to output before sending EOS", -1, G_MAXINT, + DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EOS, - g_param_spec_boolean ("eos", "eos", "Send out the EOS event?", TRUE, - G_PARAM_READWRITE)); + g_param_spec_boolean ("eos", "eos", "Send out the EOS event?", + DEFAULT_EOS, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE, g_param_spec_string ("last-message", "last-message", "The last status message", NULL, G_PARAM_READABLE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT, g_param_spec_boolean ("silent", "Silent", - "Don't produce last_message events", FALSE, G_PARAM_READWRITE)); + "Don't produce last_message events", DEFAULT_SILENT, + G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_HANDOFFS, g_param_spec_boolean ("signal-handoffs", "Signal handoffs", - "Send a signal before pushing the buffer", FALSE, G_PARAM_READWRITE)); + "Send a signal before pushing the buffer", DEFAULT_SIGNAL_HANDOFFS, + G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP, g_param_spec_boolean ("dump", "Dump", "Dump produced bytes to stdout", - FALSE, G_PARAM_READWRITE)); + DEFAULT_DUMP, G_PARAM_READWRITE)); gst_fakesrc_signals[SIGNAL_HANDOFF] = g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, @@ -272,8 +281,8 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) gst_marshal_VOID__BOXED_OBJECT, G_TYPE_NONE, 1, GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE); - gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state); - + gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_fakesrc_start); + gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_fakesrc_stop); gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_fakesrc_event_handler); gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_fakesrc_create); } @@ -284,14 +293,13 @@ gst_fakesrc_init (GstFakeSrc * fakesrc) fakesrc->output = FAKESRC_FIRST_LAST_LOOP; fakesrc->segment_start = -1; fakesrc->segment_end = -1; - fakesrc->num_buffers = -1; + fakesrc->num_buffers = DEFAULT_NUM_BUFFERS; fakesrc->rt_num_buffers = -1; fakesrc->buffer_count = 0; - fakesrc->silent = FALSE; - fakesrc->signal_handoffs = FALSE; - fakesrc->dump = FALSE; + fakesrc->silent = DEFAULT_SILENT; + fakesrc->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS; + fakesrc->dump = DEFAULT_DUMP; fakesrc->pattern_byte = 0x00; - fakesrc->need_flush = FALSE; fakesrc->data = FAKESRC_DATA_ALLOCATE; fakesrc->sizetype = FAKESRC_SIZETYPE_NULL; fakesrc->filltype = FAKESRC_FILLTYPE_NOTHING; @@ -302,7 +310,6 @@ gst_fakesrc_init (GstFakeSrc * fakesrc) fakesrc->last_message = NULL; fakesrc->datarate = DEFAULT_DATARATE; fakesrc->sync = DEFAULT_SYNC; - fakesrc->pad_mode = GST_ACTIVATE_NONE; } static gboolean @@ -312,22 +319,16 @@ gst_fakesrc_event_handler (GstBaseSrc * basesrc, GstEvent * event) src = GST_FAKESRC (basesrc); - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEEK: - src->segment_start = GST_EVENT_SEEK_OFFSET (event); - src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event); - src->buffer_count = src->segment_start; - src->segment_loop = - GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_SEGMENT_LOOP; - src->need_flush = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH; - break; - case GST_EVENT_FLUSH: - src->need_flush = TRUE; - break; - default: - break; + if (!src->silent) { + g_free (src->last_message); + + src->last_message = + g_strdup_printf ("event ******* E (type: %d) %p", + GST_EVENT_TYPE (event), event); + + g_object_notify (G_OBJECT (src), "last_message"); } - gst_event_unref (event); + return TRUE; } @@ -427,9 +428,6 @@ gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value, src = GST_FAKESRC (object); switch (prop_id) { - case ARG_NUM_SOURCES: - g_value_set_int (value, GST_ELEMENT (src)->numsrcpads); - break; case ARG_OUTPUT: g_value_set_enum (value, src->output); break; @@ -632,6 +630,8 @@ gst_fakesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length, src = GST_FAKESRC (basesrc); if (src->buffer_count == src->segment_end) { + GST_INFO ("buffer_count reaches segment_end %d %d", src->buffer_count, + src->segment_end); return GST_FLOW_UNEXPECTED; } @@ -686,51 +686,35 @@ gst_fakesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length, return GST_FLOW_OK; } -static GstElementStateReturn -gst_fakesrc_change_state (GstElement * element) +static gboolean +gst_fakesrc_start (GstBaseSrc * basesrc) { - GstFakeSrc *fakesrc; - GstElementStateReturn result = GST_STATE_FAILURE; + GstFakeSrc *src; - g_return_val_if_fail (GST_IS_FAKESRC (element), result); + src = GST_FAKESRC (basesrc); - fakesrc = GST_FAKESRC (element); + src->buffer_count = 0; + src->pattern_byte = 0x00; + src->eos = FALSE; + src->bytes_sent = 0; + src->rt_num_buffers = src->num_buffers; - switch (GST_STATE_TRANSITION (element)) { - case GST_STATE_NULL_TO_READY: - break; - case GST_STATE_READY_TO_PAUSED: - { - fakesrc->buffer_count = 0; - fakesrc->pattern_byte = 0x00; - fakesrc->need_flush = FALSE; - fakesrc->eos = FALSE; - fakesrc->bytes_sent = 0; - fakesrc->rt_num_buffers = fakesrc->num_buffers; - break; - } - case GST_STATE_PAUSED_TO_PLAYING: - break; - } + return TRUE; +} - result = GST_ELEMENT_CLASS (parent_class)->change_state (element); +static gboolean +gst_fakesrc_stop (GstBaseSrc * basesrc) +{ + GstFakeSrc *src; - switch (GST_STATE_TRANSITION (element)) { - case GST_STATE_PLAYING_TO_PAUSED: - break; - case GST_STATE_PAUSED_TO_READY: - if (fakesrc->parent) { - gst_buffer_unref (fakesrc->parent); - fakesrc->parent = NULL; - } - g_free (fakesrc->last_message); - fakesrc->last_message = NULL; - break; - case GST_STATE_READY_TO_NULL: - break; - default: - break; + src = GST_FAKESRC (basesrc); + + if (src->parent) { + gst_buffer_unref (src->parent); + src->parent = NULL; } + g_free (src->last_message); + src->last_message = NULL; - return result; + return TRUE; } diff --git a/plugins/elements/gstfakesrc.h b/plugins/elements/gstfakesrc.h index 3cda131..af286fd 100644 --- a/plugins/elements/gstfakesrc.h +++ b/plugins/elements/gstfakesrc.h @@ -84,7 +84,6 @@ struct _GstFakeSrc { GstFakeSrcDataType data; GstFakeSrcSizeType sizetype; GstFakeSrcFillType filltype; - GstActivateMode pad_mode; guint sizemin; guint sizemax; @@ -106,7 +105,6 @@ struct _GstFakeSrc { gboolean silent; gboolean signal_handoffs; gboolean dump; - gboolean need_flush; guint64 bytes_sent; diff --git a/plugins/elements/gstfilesrc.c b/plugins/elements/gstfilesrc.c index 2c60acd..22f93d5 100644 --- a/plugins/elements/gstfilesrc.c +++ b/plugins/elements/gstfilesrc.c @@ -135,6 +135,7 @@ static void gst_filesrc_get_property (GObject * object, guint prop_id, static gboolean gst_filesrc_start (GstBaseSrc * basesrc); static gboolean gst_filesrc_stop (GstBaseSrc * basesrc); +static gboolean gst_filesrc_is_seekable (GstBaseSrc * src); static gboolean gst_filesrc_get_size (GstBaseSrc * src, guint64 * size); static GstFlowReturn gst_filesrc_create (GstBaseSrc * src, guint64 offset, guint length, GstBuffer ** buffer); @@ -203,6 +204,7 @@ gst_filesrc_class_init (GstFileSrcClass * klass) gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_filesrc_start); gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_filesrc_stop); + gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_filesrc_is_seekable); gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_filesrc_get_size); gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_filesrc_create); } @@ -713,6 +715,12 @@ gst_filesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length, } static gboolean +gst_filesrc_is_seekable (GstBaseSrc * src) +{ + return TRUE; +} + +static gboolean gst_filesrc_get_size (GstBaseSrc * basesrc, guint64 * size) { struct stat stat_results; diff --git a/plugins/elements/gsttypefindelement.c b/plugins/elements/gsttypefindelement.c index 9c7b162..a0e9ae9 100644 --- a/plugins/elements/gsttypefindelement.c +++ b/plugins/elements/gsttypefindelement.c @@ -32,6 +32,19 @@ * requests * 7) goto 2 * 8) take best available result and use its caps + * + * The element has two scheduling modes: + * + * 1) chain based, it will collect buffers and run the typefind function on + * the buffer until something is found. + * 2) getrange based, it will proxy the getrange function to the sinkpad. It + * is assumed that the peer element is happy with whatever format we + * eventually read. + * + * When the element has no connected srcpad, and the sinkpad can operate in + * getrange based mode, the element starts its own task to figure out the + * type of the stream. + * */ #ifdef HAVE_CONFIG_H @@ -41,6 +54,7 @@ #include "gsttypefindelement.h" #include "gst/gst_private.h" #include "gst/gst-i18n-lib.h" +#include "gst/base/gsttypefindhelper.h" #include #include @@ -84,8 +98,6 @@ enum enum { MODE_NORMAL, /* act as identity */ - MODE_TRANSITION, /* wait for the discont between the two - * other modes */ MODE_TYPEFIND /* do typefinding */ }; @@ -108,11 +120,19 @@ static gboolean gst_type_find_element_src_event (GstPad * pad, GstEvent * event); static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQueryType type, GstFormat * fmt, gint64 * value); -static void push_buffer_store (GstTypeFindElement * typefind); +static GstFlowReturn push_buffer_store (GstTypeFindElement * typefind); -static void gst_type_find_element_chain (GstPad * sinkpad, GstData * data); +static gboolean gst_type_find_element_handle_event (GstPad * pad, + GstEvent * event); +static GstFlowReturn gst_type_find_element_chain (GstPad * sinkpad, + GstBuffer * buffer); +static GstFlowReturn gst_type_find_element_getrange (GstPad * srcpad, + guint64 offset, guint length, GstBuffer ** buffer); +static gboolean gst_type_find_element_checkgetrange (GstPad * srcpad); static GstElementStateReturn gst_type_find_element_change_state (GstElement * element); +static gboolean +gst_type_find_element_activate (GstPad * pad, GstActivateMode mode); static guint gst_type_find_element_signals[LAST_SIGNAL] = { 0 }; @@ -125,8 +145,9 @@ gst_type_find_element_have_type (GstTypeFindElement * typefind, GST_INFO_OBJECT (typefind, "found caps %" GST_PTR_FORMAT, caps); typefind->caps = gst_caps_copy (caps); - gst_pad_set_explicit_caps (typefind->src, caps); + gst_pad_set_caps (typefind->src, (GstCaps *) caps); } + static void gst_type_find_element_base_init (gpointer g_class) { @@ -182,18 +203,26 @@ gst_type_find_element_init (GstTypeFindElement * typefind) typefind->sink = gst_pad_new_from_template (gst_static_pad_template_get (&type_find_element_sink_template), "sink"); + gst_pad_set_activate_function (typefind->sink, + gst_type_find_element_activate); gst_pad_set_chain_function (typefind->sink, gst_type_find_element_chain); + gst_pad_set_event_function (typefind->sink, + gst_type_find_element_handle_event); gst_element_add_pad (GST_ELEMENT (typefind), typefind->sink); /* srcpad */ typefind->src = gst_pad_new_from_template (gst_static_pad_template_get (&type_find_element_src_template), "src"); + gst_pad_set_activate_function (typefind->src, gst_type_find_element_activate); + gst_pad_set_checkgetrange_function (typefind->src, + gst_type_find_element_checkgetrange); + gst_pad_set_getrange_function (typefind->src, gst_type_find_element_getrange); gst_pad_set_event_function (typefind->src, gst_type_find_element_src_event); gst_pad_set_event_mask_function (typefind->src, gst_type_find_element_src_event_mask); gst_pad_set_query_function (typefind->src, GST_DEBUG_FUNCPTR (gst_type_find_handle_src_query)); - gst_pad_use_explicit_caps (typefind->src); + gst_pad_use_fixed_caps (typefind->src); gst_element_add_pad (GST_ELEMENT (typefind), typefind->src); typefind->caps = NULL; @@ -201,8 +230,6 @@ gst_type_find_element_init (GstTypeFindElement * typefind) typefind->max_probability = GST_TYPE_FIND_MAXIMUM; typefind->store = gst_buffer_store_new (); - - GST_FLAG_SET (typefind, GST_ELEMENT_EVENT_AWARE); } static void gst_type_find_element_dispose (GObject * object) @@ -359,7 +386,7 @@ start_typefinding (GstTypeFindElement * typefind) g_assert (typefind->possibilities == NULL); GST_DEBUG_OBJECT (typefind, "starting typefinding"); - gst_pad_unnegotiate (typefind->src); + gst_pad_set_caps (typefind->src, NULL); if (typefind->caps) { gst_caps_replace (&typefind->caps, NULL); } @@ -370,9 +397,14 @@ start_typefinding (GstTypeFindElement * typefind) static void stop_typefinding (GstTypeFindElement * typefind) { + GstElementState state; + /* stop all typefinding and set mode back to normal */ - gboolean push_cached_buffers = - gst_element_get_state (GST_ELEMENT (typefind)) == GST_STATE_PLAYING; + gboolean push_cached_buffers; + + gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, NULL); + + push_cached_buffers = (state >= GST_STATE_PAUSED); GST_DEBUG_OBJECT (typefind, "stopping typefinding%s", push_cached_buffers ? " and pushing cached buffers" : ""); @@ -384,47 +416,35 @@ stop_typefinding (GstTypeFindElement * typefind) g_list_free (typefind->possibilities); typefind->possibilities = NULL; } - - typefind->mode = MODE_TRANSITION; + //typefind->mode = MODE_TRANSITION; if (!push_cached_buffers) { gst_buffer_store_clear (typefind->store); } else { - guint size = gst_buffer_store_get_size (typefind->store, 0); - - GST_DEBUG_OBJECT (typefind, "seeking back to current position %u", size); - if (!gst_pad_send_event (GST_PAD_PEER (typefind->sink), - gst_event_new_seek (GST_SEEK_METHOD_SET | GST_FORMAT_BYTES, - size))) { - GST_WARNING_OBJECT (typefind, - "could not seek to required position %u, hope for the best", size); - typefind->mode = MODE_NORMAL; - /* push out our queued buffers here */ - push_buffer_store (typefind); - } else { - typefind->waiting_for_discont_offset = size; - } + typefind->mode = MODE_NORMAL; + /* push out our queued buffers here */ + push_buffer_store (typefind); } } -static void +static GstFlowReturn push_buffer_store (GstTypeFindElement * typefind) { guint size = gst_buffer_store_get_size (typefind->store, 0); GstBuffer *buffer; + GstFlowReturn ret; - gst_pad_push (typefind->src, GST_DATA (gst_event_new_discontinuous (TRUE, - GST_FORMAT_DEFAULT, (guint64) 0, GST_FORMAT_BYTES, (guint64) 0, - GST_FORMAT_UNDEFINED))); if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) { GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size); - gst_pad_push (typefind->src, GST_DATA (buffer)); + ret = gst_pad_push (typefind->src, buffer); } else { - /* FIXME: shouldn't we throw an error here? */ size = 0; + ret = GST_FLOW_ERROR; } gst_buffer_store_clear (typefind->store); + + return ret; } static guint64 @@ -460,9 +480,11 @@ find_element_get_length (gpointer data) return entry->self->stream_length; } -static void + +static gboolean gst_type_find_element_handle_event (GstPad * pad, GstEvent * event) { + gboolean res = FALSE; TypeFindEntry *entry; GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); @@ -485,9 +507,9 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event) 0, entry->probability, entry->caps); stop_typefinding (typefind); push_buffer_store (typefind); - gst_pad_event_default (pad, event); + res = gst_pad_event_default (pad, event); } else { - gst_pad_event_default (pad, event); + res = gst_pad_event_default (pad, event); GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL)); stop_typefinding (typefind); @@ -495,44 +517,23 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event) break; default: gst_data_unref (GST_DATA (event)); + res = TRUE; break; } break; - case MODE_TRANSITION: - if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS) { - if (GST_EVENT_DISCONT_NEW_MEDIA (event)) { - start_typefinding (typefind); - gst_event_unref (event); - } else { - guint64 off; - - if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &off) && - off == typefind->waiting_for_discont_offset) { - typefind->mode = MODE_NORMAL; - push_buffer_store (typefind); - } else { - gst_event_unref (event); - } - } - } else if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { - push_buffer_store (typefind); - gst_pad_event_default (pad, event); - } else { - gst_event_unref (event); - } - break; case MODE_NORMAL: - if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS && - GST_EVENT_DISCONT_NEW_MEDIA (event)) { + if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS) { start_typefinding (typefind); gst_event_unref (event); + res = TRUE; } else { - gst_pad_event_default (pad, event); + res = gst_pad_event_default (pad, event); } break; default: g_assert_not_reached (); } + return res; } static guint8 * find_peek (gpointer data, gint64 offset, guint size) @@ -583,6 +584,7 @@ find_suggest (gpointer data, guint probability, const GstCaps * caps) gst_caps_replace (&entry->caps, gst_caps_copy (caps)); } } + static gint compare_type_find_entry (gconstpointer a, gconstpointer b) { @@ -596,40 +598,37 @@ compare_type_find_entry (gconstpointer a, gconstpointer b) return two->probability - one->probability; } } + static gint compare_type_find_factory (gconstpointer fac1, gconstpointer fac2) { return GST_PLUGIN_FEATURE (fac1)->rank - GST_PLUGIN_FEATURE (fac2)->rank; } -static void -gst_type_find_element_chain (GstPad * pad, GstData * data) + +static GstFlowReturn +gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer) { GstTypeFindElement *typefind; GList *entries; TypeFindEntry *entry; GList *walk; + GstFlowReturn res = GST_FLOW_OK; GstTypeFind find = { find_peek, find_suggest, NULL, find_element_get_length }; typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); - if (GST_IS_EVENT (data)) { - gst_type_find_element_handle_event (pad, GST_EVENT (data)); - return; - } + switch (typefind->mode) { case MODE_NORMAL: - gst_pad_push (typefind->src, data); - return; - case MODE_TRANSITION: - gst_data_unref (data); - return; + return gst_pad_push (typefind->src, buffer); case MODE_TYPEFIND:{ guint64 current_offset; - gst_buffer_store_add_buffer (typefind->store, GST_BUFFER (data)); - current_offset = GST_BUFFER_OFFSET_IS_VALID (data) ? - GST_BUFFER_OFFSET (data) + GST_BUFFER_SIZE (data) : + gst_buffer_store_add_buffer (typefind->store, buffer); + current_offset = GST_BUFFER_OFFSET_IS_VALID (buffer) ? + GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer) : gst_buffer_store_get_size (typefind->store, 0); - gst_data_unref (data); + gst_buffer_unref (buffer); + if (typefind->possibilities == NULL) { /* not yet started, get all typefinding functions into our "queue" */ GList *all_factories = gst_type_find_factory_get_list (); @@ -800,27 +799,108 @@ gst_type_find_element_chain (GstPad * pad, GstData * data) } default: g_assert_not_reached (); - return; + return GST_FLOW_ERROR; } + + return res; } + +static gboolean +gst_type_find_element_checkgetrange (GstPad * srcpad) +{ + GstTypeFindElement *typefind; + + typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (srcpad)); + + return gst_pad_check_pull_range (typefind->sink); +} + +static GstFlowReturn +gst_type_find_element_getrange (GstPad * srcpad, + guint64 offset, guint length, GstBuffer ** buffer) +{ + GstTypeFindElement *typefind; + + typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (srcpad)); + + return gst_pad_pull_range (typefind->sink, offset, length, buffer); +} + +static gboolean +do_typefind (GstTypeFindElement * typefind) +{ + GstCaps *caps; + GstPad *peer; + + peer = gst_pad_get_peer (typefind->sink); + if (peer) { + gst_pad_peer_set_active (typefind->sink, GST_ACTIVATE_PULL); + + caps = gst_type_find_helper (peer, 0); + gst_pad_set_caps (typefind->src, caps); + + if (caps) { + g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], + 0, 100, caps); + } + + gst_object_unref (GST_OBJECT (peer)); + } + + return TRUE; +} + +static gboolean +gst_type_find_element_activate (GstPad * pad, GstActivateMode mode) +{ + gboolean result; + GstTypeFindElement *typefind; + + typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad)); + + switch (mode) { + case GST_ACTIVATE_PUSH: + case GST_ACTIVATE_PULL: + result = TRUE; + break; + default: + result = TRUE; + break; + } + + return result; +} + static GstElementStateReturn gst_type_find_element_change_state (GstElement * element) { + GstElementState transition; + GstElementStateReturn ret; GstTypeFindElement *typefind; typefind = GST_TYPE_FIND_ELEMENT (element); - switch (GST_STATE_TRANSITION (element)) { + transition = GST_STATE_TRANSITION (element); + switch (transition) { case GST_STATE_READY_TO_PAUSED: - start_typefinding (typefind); + do_typefind (typefind); + + //start_typefinding (typefind); break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { case GST_STATE_PAUSED_TO_READY: - stop_typefinding (typefind); + //stop_typefinding (typefind); gst_caps_replace (&typefind->caps, NULL); break; default: break; } - return GST_ELEMENT_CLASS (parent_class)->change_state (element); + return ret; } diff --git a/plugins/elements/gsttypefindelement.h b/plugins/elements/gsttypefindelement.h index 43debd5..03eeccd 100644 --- a/plugins/elements/gsttypefindelement.h +++ b/plugins/elements/gsttypefindelement.h @@ -53,7 +53,6 @@ struct _GstTypeFindElement { GstCaps * caps; guint mode; - guint64 waiting_for_discont_offset; GstBufferStore * store; guint64 stream_length; gboolean stream_length_available; -- 2.7.4