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.
This commit is contained in:
Wim Taymans 2005-04-12 10:52:55 +00:00
parent 605ceb3edd
commit 499659f65f
28 changed files with 941 additions and 591 deletions

View file

@ -1,4 +1,55 @@
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):

View file

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

View file

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

View file

@ -29,6 +29,7 @@
#endif
#include "gstbasesrc.h"
#include "gsttypefindhelper.h"
#include <gst/gstmarshal.h>
#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;
}

View file

@ -0,0 +1,131 @@
/* 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;
}

View file

@ -0,0 +1,34 @@
/* 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__ */

View file

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

View file

@ -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},
};

View file

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

View file

@ -31,12 +31,6 @@
#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,
@ -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;
}
result = GST_ELEMENT_CLASS (parent_class)->change_state (element);
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;
}
return result;
return TRUE;
}
static gboolean
gst_fakesrc_stop (GstBaseSrc * basesrc)
{
GstFakeSrc *src;
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 TRUE;
}

View file

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

View file

@ -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);
}
@ -712,6 +714,12 @@ gst_filesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length,
return ret;
}
static gboolean
gst_filesrc_is_seekable (GstBaseSrc * src)
{
return TRUE;
}
static gboolean
gst_filesrc_get_size (GstBaseSrc * basesrc, guint64 * size)
{

View file

@ -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 <gst/gsttypefind.h>
#include <gst/gstutils.h>
@ -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;
}

View file

@ -53,7 +53,6 @@ struct _GstTypeFindElement {
GstCaps * caps;
guint mode;
guint64 waiting_for_discont_offset;
GstBufferStore * store;
guint64 stream_length;
gboolean stream_length_available;

View file

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

View file

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

View file

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

View file

@ -29,6 +29,7 @@
#endif
#include "gstbasesrc.h"
#include "gsttypefindhelper.h"
#include <gst/gstmarshal.h>
#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;
}

View file

@ -0,0 +1,131 @@
/* 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;
}

View file

@ -0,0 +1,34 @@
/* 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__ */

View file

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

View file

@ -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},
};

View file

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

View file

@ -31,12 +31,6 @@
#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,
@ -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;
}
result = GST_ELEMENT_CLASS (parent_class)->change_state (element);
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;
}
return result;
return TRUE;
}
static gboolean
gst_fakesrc_stop (GstBaseSrc * basesrc)
{
GstFakeSrc *src;
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 TRUE;
}

View file

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

View file

@ -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);
}
@ -712,6 +714,12 @@ gst_filesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length,
return ret;
}
static gboolean
gst_filesrc_is_seekable (GstBaseSrc * src)
{
return TRUE;
}
static gboolean
gst_filesrc_get_size (GstBaseSrc * basesrc, guint64 * size)
{

View file

@ -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 <gst/gsttypefind.h>
#include <gst/gstutils.h>
@ -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;
}

View file

@ -53,7 +53,6 @@ struct _GstTypeFindElement {
GstCaps * caps;
guint mode;
guint64 waiting_for_discont_offset;
GstBufferStore * store;
guint64 stream_length;
gboolean stream_length_available;