mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-16 04:54:12 +00:00
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:
parent
605ceb3edd
commit
499659f65f
28 changed files with 941 additions and 591 deletions
53
ChangeLog
53
ChangeLog
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
131
gst/base/gsttypefindhelper.c
Normal file
131
gst/base/gsttypefindhelper.c
Normal 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;
|
||||
}
|
34
gst/base/gsttypefindhelper.h
Normal file
34
gst/base/gsttypefindhelper.h
Normal 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__ */
|
|
@ -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)
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ struct _GstTypeFindElement {
|
|||
GstCaps * caps;
|
||||
|
||||
guint mode;
|
||||
guint64 waiting_for_discont_offset;
|
||||
GstBufferStore * store;
|
||||
guint64 stream_length;
|
||||
gboolean stream_length_available;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
131
libs/gst/base/gsttypefindhelper.c
Normal file
131
libs/gst/base/gsttypefindhelper.c
Normal 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;
|
||||
}
|
34
libs/gst/base/gsttypefindhelper.h
Normal file
34
libs/gst/base/gsttypefindhelper.h
Normal 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__ */
|
|
@ -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)
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ struct _GstTypeFindElement {
|
|||
GstCaps * caps;
|
||||
|
||||
guint mode;
|
||||
guint64 waiting_for_discont_offset;
|
||||
GstBufferStore * store;
|
||||
guint64 stream_length;
|
||||
gboolean stream_length_available;
|
||||
|
|
Loading…
Reference in a new issue