-2005-04-11 set REAL_NAME environment variable <set EMAIL_ADDRESS environment variable>
+2005-04-12 Wim Taymans <wim@fluendo.com>
+
+ * 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 <wim@fluendo.com>
* check/gst/gstbus.c: (gstbus_suite):
* check/gst/gstdata.c: (thread_ref), (gst_data_suite):
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) \
$(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
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;
/* 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;
#endif
#include "gstbasesrc.h"
+#include "gsttypefindhelper.h"
#include <gst/gstmarshal.h>
#define DEFAULT_BLOCKSIZE 4096
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)
{
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:
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;
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 */
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;
-}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000,2005 Wim Taymans <wim@fluendo.com>
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#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;
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000,2005 Wim Taymans <wim@fluendo.com>
+ *
+ * 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 <gst/gst.h>
+
+G_BEGIN_DECLS
+
+GstCaps * gst_type_find_helper (GstPad *src, guint64 size);
+
+G_END_DECLS
+
+#endif /* __GST_TYPEFINDHELPER_H__ */
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 \
gstmultifilesrc.c \
gstpipefilter.c \
gstshaper.c \
- gststatistics.c \
- gsttypefindelement.c
+ gststatistics.c
libgstelements_la_CFLAGS = $(GST_OBJ_CFLAGS)
// {"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},
};
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");
#include "gstfakesrc.h"
#include <gst/gstmarshal.h>
-#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,
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,
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,
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));
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,
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,
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);
}
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;
fakesrc->last_message = NULL;
fakesrc->datarate = DEFAULT_DATARATE;
fakesrc->sync = DEFAULT_SYNC;
- fakesrc->pad_mode = GST_ACTIVATE_NONE;
}
static gboolean
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;
}
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;
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;
}
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;
}
GstFakeSrcDataType data;
GstFakeSrcSizeType sizetype;
GstFakeSrcFillType filltype;
- GstActivateMode pad_mode;
guint sizemin;
guint sizemax;
gboolean silent;
gboolean signal_handoffs;
gboolean dump;
- gboolean need_flush;
guint64 bytes_sent;
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);
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);
}
}
static gboolean
+gst_filesrc_is_seekable (GstBaseSrc * src)
+{
+ return TRUE;
+}
+
+static gboolean
gst_filesrc_get_size (GstBaseSrc * basesrc, guint64 * size)
{
struct stat stat_results;
* 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
#include "gsttypefindelement.h"
#include "gst/gst_private.h"
#include "gst/gst-i18n-lib.h"
+#include "gst/base/gsttypefindhelper.h"
#include <gst/gsttypefind.h>
#include <gst/gstutils.h>
enum
{
MODE_NORMAL, /* act as identity */
- MODE_TRANSITION, /* wait for the discont between the two
- * other modes */
MODE_TYPEFIND /* do typefinding */
};
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 };
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)
{
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;
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)
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);
}
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" : "");
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
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));
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);
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)
gst_caps_replace (&entry->caps, gst_caps_copy (caps));
}
}
+
static gint
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 ();
}
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;
}
GstCaps * caps;
guint mode;
- guint64 waiting_for_discont_offset;
GstBufferStore * store;
guint64 stream_length;
gboolean stream_length_available;
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));
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) \
$(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
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;
/* 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;
#endif
#include "gstbasesrc.h"
+#include "gsttypefindhelper.h"
#include <gst/gstmarshal.h>
#define DEFAULT_BLOCKSIZE 4096
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)
{
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:
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;
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 */
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;
-}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000,2005 Wim Taymans <wim@fluendo.com>
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#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;
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000,2005 Wim Taymans <wim@fluendo.com>
+ *
+ * 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 <gst/gst.h>
+
+G_BEGIN_DECLS
+
+GstCaps * gst_type_find_helper (GstPad *src, guint64 size);
+
+G_END_DECLS
+
+#endif /* __GST_TYPEFINDHELPER_H__ */
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 \
gstmultifilesrc.c \
gstpipefilter.c \
gstshaper.c \
- gststatistics.c \
- gsttypefindelement.c
+ gststatistics.c
libgstelements_la_CFLAGS = $(GST_OBJ_CFLAGS)
// {"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},
};
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");
#include "gstfakesrc.h"
#include <gst/gstmarshal.h>
-#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,
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,
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,
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));
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,
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,
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);
}
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;
fakesrc->last_message = NULL;
fakesrc->datarate = DEFAULT_DATARATE;
fakesrc->sync = DEFAULT_SYNC;
- fakesrc->pad_mode = GST_ACTIVATE_NONE;
}
static gboolean
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;
}
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;
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;
}
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;
}
GstFakeSrcDataType data;
GstFakeSrcSizeType sizetype;
GstFakeSrcFillType filltype;
- GstActivateMode pad_mode;
guint sizemin;
guint sizemax;
gboolean silent;
gboolean signal_handoffs;
gboolean dump;
- gboolean need_flush;
guint64 bytes_sent;
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);
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);
}
}
static gboolean
+gst_filesrc_is_seekable (GstBaseSrc * src)
+{
+ return TRUE;
+}
+
+static gboolean
gst_filesrc_get_size (GstBaseSrc * basesrc, guint64 * size)
{
struct stat stat_results;
* 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
#include "gsttypefindelement.h"
#include "gst/gst_private.h"
#include "gst/gst-i18n-lib.h"
+#include "gst/base/gsttypefindhelper.h"
#include <gst/gsttypefind.h>
#include <gst/gstutils.h>
enum
{
MODE_NORMAL, /* act as identity */
- MODE_TRANSITION, /* wait for the discont between the two
- * other modes */
MODE_TYPEFIND /* do typefinding */
};
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 };
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)
{
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;
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)
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);
}
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" : "");
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
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));
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);
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)
gst_caps_replace (&entry->caps, gst_caps_copy (caps));
}
}
+
static gint
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 ();
}
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;
}
GstCaps * caps;
guint mode;
- guint64 waiting_for_discont_offset;
GstBufferStore * store;
guint64 stream_length;
gboolean stream_length_available;