2003-10-28 20:25:30 +00:00
|
|
|
/* GStreamer
|
|
|
|
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
|
|
|
|
*
|
gst/: splitted gsttypefind into gsttypefind, gsttypefindfactory
Original commit message from CVS:
* gst/Makefile.am:
* gst/elements/gstbufferstore.h:
* gst/elements/gsttypefindelement.c:
* gst/elements/gsttypefindelement.h:
* gst/gst.h:
* gst/gsttypefind.c:
* gst/gsttypefind.h:
* gst/gsttypefindfactory.c: (gst_type_find_factory_get_type),
(gst_type_find_factory_class_init), (gst_type_find_factory_init),
(gst_type_find_factory_dispose),
(gst_type_find_factory_unload_thyself),
(gst_type_find_load_plugin), (gst_type_find_factory_get_list),
(gst_type_find_factory_get_caps),
(gst_type_find_factory_get_extensions),
(gst_type_find_factory_call_function):
* gst/gsttypefindfactory.h:
* gst/registries/gstlibxmlregistry.c:
* gst/registries/gstxmlregistry.c:
splitted gsttypefind into gsttypefind, gsttypefindfactory
2005-09-07 12:35:23 +00:00
|
|
|
* gsttypefindelement.c: element that detects type of stream
|
2003-10-28 20:25:30 +00:00
|
|
|
*
|
|
|
|
* 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
|
2012-11-03 20:44:48 +00:00
|
|
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
2003-10-28 20:25:30 +00:00
|
|
|
*/
|
2008-06-20 10:14:54 +00:00
|
|
|
/**
|
|
|
|
* SECTION:element-typefind
|
|
|
|
*
|
|
|
|
* Determines the media-type of a stream. It applies typefind functions in the
|
2013-12-07 14:38:19 +00:00
|
|
|
* order of their rank. Once the type has been detected it sets its src pad caps
|
2008-06-20 10:14:54 +00:00
|
|
|
* to the found media type.
|
|
|
|
*
|
2011-01-11 13:09:30 +00:00
|
|
|
* Whenever a type is found the #GstTypeFindElement::have-type signal is
|
2011-01-25 18:48:40 +00:00
|
|
|
* emitted, either from the streaming thread or the application thread
|
|
|
|
* (the latter may happen when typefinding is done pull-based from the
|
|
|
|
* state change function).
|
2011-01-11 13:09:30 +00:00
|
|
|
*
|
2008-06-20 10:14:54 +00:00
|
|
|
* Plugins can register custom typefinders by using #GstTypeFindFactory.
|
|
|
|
*/
|
2003-10-28 20:25:30 +00:00
|
|
|
|
|
|
|
/* FIXME: need a better solution for non-seekable streams */
|
|
|
|
|
|
|
|
/* way of operation:
|
|
|
|
* 1) get a list of all typefind functions sorted best to worst
|
|
|
|
* 2) if all elements have been called with all requested data goto 8
|
|
|
|
* 3) call all functions once with all available data
|
2012-07-06 09:13:28 +00:00
|
|
|
* 4) if a function returns a value >= PROP_MAXIMUM goto 8 (never implemented))
|
2008-04-02 17:21:40 +00:00
|
|
|
* 5) all functions with a result > PROP_MINIMUM or functions that did not get
|
2003-10-28 20:25:30 +00:00
|
|
|
* all requested data (where peek returned NULL) stay in list
|
2005-10-15 15:30:24 +00:00
|
|
|
* 6) seek to requested offset of best function that still has open data
|
2003-10-28 20:25:30 +00:00
|
|
|
* requests
|
|
|
|
* 7) goto 2
|
|
|
|
* 8) take best available result and use its caps
|
2005-04-12 10:52:55 +00:00
|
|
|
*
|
|
|
|
* 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
|
2005-10-15 15:30:24 +00:00
|
|
|
* is assumed that the peer element is happy with whatever format we
|
2005-04-12 10:52:55 +00:00
|
|
|
* eventually read.
|
|
|
|
*
|
2011-01-25 18:48:40 +00:00
|
|
|
* By default it tries to do pull based typefinding (this avoids joining
|
|
|
|
* received buffers and holding them back in store.)
|
2011-01-12 14:03:57 +00:00
|
|
|
*
|
2005-04-12 10:52:55 +00:00
|
|
|
* When the element has no connected srcpad, and the sinkpad can operate in
|
2005-10-15 15:30:24 +00:00
|
|
|
* getrange based mode, the element starts its own task to figure out the
|
2005-04-12 10:52:55 +00:00
|
|
|
* type of the stream.
|
2005-10-15 15:30:24 +00:00
|
|
|
*
|
2010-07-15 20:05:09 +00:00
|
|
|
* Most of the actual implementation is in libs/gst/base/gsttypefindhelper.c.
|
2003-10-28 20:25:30 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "gst/gst_private.h"
|
2010-01-20 01:09:55 +00:00
|
|
|
|
|
|
|
#include "gsttypefindelement.h"
|
2004-01-13 11:30:00 +00:00
|
|
|
#include "gst/gst-i18n-lib.h"
|
2005-04-12 10:52:55 +00:00
|
|
|
#include "gst/base/gsttypefindhelper.h"
|
2003-10-28 20:25:30 +00:00
|
|
|
|
|
|
|
#include <gst/gsttypefind.h>
|
2004-01-08 04:10:18 +00:00
|
|
|
#include <gst/gstutils.h>
|
2004-01-18 21:36:20 +00:00
|
|
|
#include <gst/gsterror.h>
|
2003-10-28 20:25:30 +00:00
|
|
|
|
2003-10-31 19:32:47 +00:00
|
|
|
GST_DEBUG_CATEGORY_STATIC (gst_type_find_element_debug);
|
2003-10-28 20:25:30 +00:00
|
|
|
#define GST_CAT_DEFAULT gst_type_find_element_debug
|
|
|
|
|
|
|
|
/* generic templates */
|
Correct all relevant warnings found by the sparse semantic code analyzer. This include marking several symbols static...
Original commit message from CVS:
* gst/gstconfig.h.in:
* libs/gst/base/gstcollectpads.c: (gst_collect_pads_read_buffer):
* libs/gst/check/gstcheck.c: (gst_check_log_message_func),
(gst_check_log_critical_func), (gst_check_drop_buffers),
(gst_check_element_push_buffer_list):
* libs/gst/controller/gstcontroller.c: (gst_controller_get),
(gst_controller_get_type):
* libs/gst/controller/gsthelper.c: (gst_object_control_properties),
(gst_object_get_controller), (gst_object_get_control_source):
* libs/gst/controller/gstinterpolationcontrolsource.c:
(gst_interpolation_control_source_new):
* libs/gst/controller/gstlfocontrolsource.c:
(gst_lfo_control_source_new):
* libs/gst/dataprotocol/dataprotocol.c:
(gst_dp_event_from_packet_0_2):
* plugins/elements/gstfdsrc.c:
* plugins/elements/gstmultiqueue.c:
* plugins/elements/gsttee.c:
* plugins/elements/gsttypefindelement.c:
* plugins/indexers/gstfileindex.c: (_file_index_id_save_xml),
(gst_file_index_add_association):
* plugins/indexers/gstmemindex.c:
* tests/benchmarks/gstpollstress.c: (mess_some_more):
* tests/check/elements/queue.c: (setup_queue):
* tests/check/gst/gstpipeline.c:
* tests/check/libs/collectpads.c: (setup), (teardown),
(gst_collect_pads_suite):
* tests/examples/adapter/adapter_test.c:
* tests/examples/metadata/read-metadata.c: (make_pipeline):
* tests/examples/xml/createxml.c:
* tests/examples/xml/runxml.c:
* tools/gst-inspect.c:
* tools/gst-run.c:
Correct all relevant warnings found by the sparse semantic code
analyzer. This include marking several symbols static, using
NULL instead of 0 for pointers, not using variable sized arrays
on the stack, moving variable declarations to the beginning of
a block and using "foo (void)" instead of "foo ()" for declarations.
2008-02-29 12:41:33 +00:00
|
|
|
static GstStaticPadTemplate type_find_element_sink_template =
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
|
|
|
GST_PAD_SINK,
|
|
|
|
GST_PAD_ALWAYS,
|
|
|
|
GST_STATIC_CAPS_ANY);
|
|
|
|
|
Correct all relevant warnings found by the sparse semantic code analyzer. This include marking several symbols static...
Original commit message from CVS:
* gst/gstconfig.h.in:
* libs/gst/base/gstcollectpads.c: (gst_collect_pads_read_buffer):
* libs/gst/check/gstcheck.c: (gst_check_log_message_func),
(gst_check_log_critical_func), (gst_check_drop_buffers),
(gst_check_element_push_buffer_list):
* libs/gst/controller/gstcontroller.c: (gst_controller_get),
(gst_controller_get_type):
* libs/gst/controller/gsthelper.c: (gst_object_control_properties),
(gst_object_get_controller), (gst_object_get_control_source):
* libs/gst/controller/gstinterpolationcontrolsource.c:
(gst_interpolation_control_source_new):
* libs/gst/controller/gstlfocontrolsource.c:
(gst_lfo_control_source_new):
* libs/gst/dataprotocol/dataprotocol.c:
(gst_dp_event_from_packet_0_2):
* plugins/elements/gstfdsrc.c:
* plugins/elements/gstmultiqueue.c:
* plugins/elements/gsttee.c:
* plugins/elements/gsttypefindelement.c:
* plugins/indexers/gstfileindex.c: (_file_index_id_save_xml),
(gst_file_index_add_association):
* plugins/indexers/gstmemindex.c:
* tests/benchmarks/gstpollstress.c: (mess_some_more):
* tests/check/elements/queue.c: (setup_queue):
* tests/check/gst/gstpipeline.c:
* tests/check/libs/collectpads.c: (setup), (teardown),
(gst_collect_pads_suite):
* tests/examples/adapter/adapter_test.c:
* tests/examples/metadata/read-metadata.c: (make_pipeline):
* tests/examples/xml/createxml.c:
* tests/examples/xml/runxml.c:
* tools/gst-inspect.c:
* tools/gst-run.c:
Correct all relevant warnings found by the sparse semantic code
analyzer. This include marking several symbols static, using
NULL instead of 0 for pointers, not using variable sized arrays
on the stack, moving variable declarations to the beginning of
a block and using "foo (void)" instead of "foo ()" for declarations.
2008-02-29 12:41:33 +00:00
|
|
|
static GstStaticPadTemplate type_find_element_src_template =
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_STATIC_PAD_TEMPLATE ("src",
|
|
|
|
GST_PAD_SRC,
|
|
|
|
GST_PAD_ALWAYS,
|
|
|
|
GST_STATIC_CAPS_ANY);
|
2003-10-28 20:25:30 +00:00
|
|
|
|
2006-02-14 20:57:31 +00:00
|
|
|
/* Require at least 2kB of data before we attempt typefinding in chain-mode.
|
|
|
|
* 128kB is massive overkill for the maximum, but doesn't do any harm */
|
|
|
|
#define TYPE_FIND_MIN_SIZE (2*1024)
|
|
|
|
#define TYPE_FIND_MAX_SIZE (128*1024)
|
|
|
|
|
2003-10-28 20:25:30 +00:00
|
|
|
/* TypeFind signals and args */
|
2004-03-13 15:27:01 +00:00
|
|
|
enum
|
|
|
|
{
|
2003-10-28 20:25:30 +00:00
|
|
|
HAVE_TYPE,
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
2004-03-13 15:27:01 +00:00
|
|
|
enum
|
|
|
|
{
|
2008-04-02 17:21:40 +00:00
|
|
|
PROP_0,
|
|
|
|
PROP_CAPS,
|
|
|
|
PROP_MINIMUM,
|
|
|
|
PROP_FORCE_CAPS,
|
|
|
|
PROP_LAST
|
2003-10-28 20:25:30 +00:00
|
|
|
};
|
2004-03-13 15:27:01 +00:00
|
|
|
enum
|
|
|
|
{
|
2004-03-15 19:27:17 +00:00
|
|
|
MODE_NORMAL, /* act as identity */
|
2005-12-12 17:09:04 +00:00
|
|
|
MODE_TYPEFIND, /* do typefinding */
|
|
|
|
MODE_ERROR /* had fatal error */
|
2003-10-28 20:25:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-04-18 16:07:06 +00:00
|
|
|
#define _do_init \
|
2005-12-06 19:29:15 +00:00
|
|
|
GST_DEBUG_CATEGORY_INIT (gst_type_find_element_debug, "typefind", \
|
|
|
|
GST_DEBUG_BG_YELLOW | GST_DEBUG_FG_GREEN, "type finding element");
|
2011-04-18 16:07:06 +00:00
|
|
|
#define gst_type_find_element_parent_class parent_class
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (GstTypeFindElement, gst_type_find_element,
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_TYPE_ELEMENT, _do_init);
|
2004-01-08 04:10:18 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static void gst_type_find_element_dispose (GObject * object);
|
|
|
|
static void gst_type_find_element_set_property (GObject * object,
|
|
|
|
guint prop_id, const GValue * value, GParamSpec * pspec);
|
|
|
|
static void gst_type_find_element_get_property (GObject * object,
|
|
|
|
guint prop_id, GValue * value, GParamSpec * pspec);
|
2003-10-28 20:25:30 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static gboolean gst_type_find_element_src_event (GstPad * pad,
|
2011-11-17 11:40:45 +00:00
|
|
|
GstObject * parent, GstEvent * event);
|
2011-11-16 16:22:56 +00:00
|
|
|
static gboolean gst_type_find_handle_src_query (GstPad * pad,
|
|
|
|
GstObject * parent, GstQuery * query);
|
2003-10-28 20:25:30 +00:00
|
|
|
|
2011-06-07 07:43:20 +00:00
|
|
|
static gboolean gst_type_find_element_sink_event (GstPad * pad,
|
2011-11-17 11:40:45 +00:00
|
|
|
GstObject * parent, GstEvent * event);
|
2011-06-07 07:43:20 +00:00
|
|
|
static gboolean gst_type_find_element_setcaps (GstTypeFindElement * typefind,
|
|
|
|
GstCaps * caps);
|
2005-04-12 10:52:55 +00:00
|
|
|
static GstFlowReturn gst_type_find_element_chain (GstPad * sinkpad,
|
2011-11-17 11:40:45 +00:00
|
|
|
GstObject * parent, GstBuffer * buffer);
|
2005-04-12 10:52:55 +00:00
|
|
|
static GstFlowReturn gst_type_find_element_getrange (GstPad * srcpad,
|
2011-11-17 11:40:45 +00:00
|
|
|
GstObject * parent, guint64 offset, guint length, GstBuffer ** buffer);
|
2005-05-05 21:45:54 +00:00
|
|
|
|
2005-09-02 15:42:00 +00:00
|
|
|
static GstStateChangeReturn
|
|
|
|
gst_type_find_element_change_state (GstElement * element,
|
|
|
|
GstStateChange transition);
|
2012-01-27 15:18:00 +00:00
|
|
|
static gboolean gst_type_find_element_activate_sink (GstPad * pad,
|
2011-11-18 12:46:46 +00:00
|
|
|
GstObject * parent);
|
2012-01-27 15:18:00 +00:00
|
|
|
static gboolean gst_type_find_element_activate_sink_mode (GstPad * pad,
|
|
|
|
GstObject * parent, GstPadMode mode, gboolean active);
|
2011-11-21 12:29:05 +00:00
|
|
|
static gboolean gst_type_find_element_activate_src_mode (GstPad * pad,
|
|
|
|
GstObject * parent, GstPadMode mode, gboolean active);
|
2006-03-03 14:18:01 +00:00
|
|
|
static GstFlowReturn
|
2011-03-21 17:13:55 +00:00
|
|
|
gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind,
|
2015-06-05 08:02:04 +00:00
|
|
|
gboolean check_avail, gboolean at_eos);
|
2011-03-21 17:13:55 +00:00
|
|
|
static void gst_type_find_element_send_cached_events (GstTypeFindElement *
|
|
|
|
typefind);
|
2003-10-28 20:25:30 +00:00
|
|
|
|
2012-01-27 15:18:00 +00:00
|
|
|
static void gst_type_find_element_loop (GstPad * pad);
|
|
|
|
|
2003-10-28 20:25:30 +00:00
|
|
|
static guint gst_type_find_element_signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_type_find_element_have_type (GstTypeFindElement * typefind,
|
2012-03-10 08:25:43 +00:00
|
|
|
guint probability, GstCaps * caps)
|
2003-10-28 20:25:30 +00:00
|
|
|
{
|
|
|
|
g_assert (caps != NULL);
|
|
|
|
|
2009-06-09 13:48:56 +00:00
|
|
|
GST_INFO_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", probability=%u",
|
|
|
|
caps, probability);
|
2010-02-04 20:11:25 +00:00
|
|
|
|
|
|
|
GST_OBJECT_LOCK (typefind);
|
2007-10-08 10:28:18 +00:00
|
|
|
if (typefind->caps)
|
|
|
|
gst_caps_unref (typefind->caps);
|
2012-03-10 08:25:43 +00:00
|
|
|
typefind->caps = gst_caps_ref (caps);
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
|
|
|
|
2012-06-08 13:45:38 +00:00
|
|
|
gst_pad_set_caps (typefind->src, caps);
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|
2005-04-12 10:52:55 +00:00
|
|
|
|
2003-10-31 19:32:47 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_type_find_element_class_init (GstTypeFindElementClass * typefind_class)
|
2003-10-28 20:25:30 +00:00
|
|
|
{
|
2004-01-08 04:10:18 +00:00
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (typefind_class);
|
|
|
|
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (typefind_class);
|
2003-10-28 20:25:30 +00:00
|
|
|
|
2009-10-28 00:29:30 +00:00
|
|
|
gobject_class->set_property = gst_type_find_element_set_property;
|
|
|
|
gobject_class->get_property = gst_type_find_element_get_property;
|
|
|
|
gobject_class->dispose = gst_type_find_element_dispose;
|
2003-10-28 20:25:30 +00:00
|
|
|
|
2008-04-02 17:21:40 +00:00
|
|
|
g_object_class_install_property (gobject_class, PROP_CAPS,
|
2004-03-13 15:27:01 +00:00
|
|
|
g_param_spec_boxed ("caps", _("caps"),
|
2010-11-02 12:31:25 +00:00
|
|
|
_("detected capabilities in stream"), GST_TYPE_CAPS,
|
2008-03-22 14:56:17 +00:00
|
|
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
2008-04-02 17:21:40 +00:00
|
|
|
g_object_class_install_property (gobject_class, PROP_MINIMUM,
|
2004-03-13 15:27:01 +00:00
|
|
|
g_param_spec_uint ("minimum", _("minimum"),
|
2004-03-15 19:27:17 +00:00
|
|
|
"minimum probability required to accept caps", GST_TYPE_FIND_MINIMUM,
|
2008-03-22 14:56:17 +00:00
|
|
|
GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MINIMUM,
|
|
|
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
2008-04-02 17:21:40 +00:00
|
|
|
g_object_class_install_property (gobject_class, PROP_FORCE_CAPS,
|
|
|
|
g_param_spec_boxed ("force-caps", _("force caps"),
|
2010-11-02 12:31:25 +00:00
|
|
|
_("force caps without doing a typefind"), GST_TYPE_CAPS,
|
2008-04-02 17:21:40 +00:00
|
|
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
2006-01-04 12:41:35 +00:00
|
|
|
/**
|
|
|
|
* GstTypeFindElement::have-type:
|
|
|
|
* @typefind: the typefind instance
|
|
|
|
* @probability: the probability of the type found
|
|
|
|
* @caps: the caps of the type found
|
|
|
|
*
|
2011-01-11 13:09:30 +00:00
|
|
|
* This signal gets emitted when the type and its probability has
|
2006-01-04 12:41:35 +00:00
|
|
|
* been found.
|
|
|
|
*/
|
2011-01-11 13:09:52 +00:00
|
|
|
gst_type_find_element_signals[HAVE_TYPE] = g_signal_new ("have-type",
|
2014-09-02 14:40:28 +00:00
|
|
|
G_TYPE_FROM_CLASS (typefind_class), G_SIGNAL_RUN_LAST,
|
2004-03-13 15:27:01 +00:00
|
|
|
G_STRUCT_OFFSET (GstTypeFindElementClass, have_type), NULL, NULL,
|
2012-03-02 10:05:48 +00:00
|
|
|
g_cclosure_marshal_generic, G_TYPE_NONE, 2,
|
2004-03-13 15:27:01 +00:00
|
|
|
G_TYPE_UINT, GST_TYPE_CAPS | G_SIGNAL_TYPE_STATIC_SCOPE);
|
|
|
|
|
2009-10-28 00:29:30 +00:00
|
|
|
typefind_class->have_type =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_type_find_element_have_type);
|
|
|
|
|
2012-04-09 12:05:07 +00:00
|
|
|
gst_element_class_set_static_metadata (gstelement_class,
|
2011-04-18 16:07:06 +00:00
|
|
|
"TypeFind",
|
|
|
|
"Generic",
|
|
|
|
"Finds the media type of a stream",
|
|
|
|
"Benjamin Otte <in7y118@public.uni-hamburg.de>");
|
|
|
|
gst_element_class_add_pad_template (gstelement_class,
|
|
|
|
gst_static_pad_template_get (&type_find_element_src_template));
|
|
|
|
gst_element_class_add_pad_template (gstelement_class,
|
|
|
|
gst_static_pad_template_get (&type_find_element_sink_template));
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
gstelement_class->change_state =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_type_find_element_change_state);
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|
2009-05-05 15:41:24 +00:00
|
|
|
|
2003-10-28 20:25:30 +00:00
|
|
|
static void
|
2011-04-18 16:07:06 +00:00
|
|
|
gst_type_find_element_init (GstTypeFindElement * typefind)
|
2003-10-28 20:25:30 +00:00
|
|
|
{
|
|
|
|
/* sinkpad */
|
2005-11-16 17:18:34 +00:00
|
|
|
typefind->sink =
|
|
|
|
gst_pad_new_from_static_template (&type_find_element_sink_template,
|
|
|
|
"sink");
|
2005-11-15 19:31:05 +00:00
|
|
|
|
2005-04-12 10:52:55 +00:00
|
|
|
gst_pad_set_activate_function (typefind->sink,
|
2012-01-27 15:18:00 +00:00
|
|
|
GST_DEBUG_FUNCPTR (gst_type_find_element_activate_sink));
|
|
|
|
gst_pad_set_activatemode_function (typefind->sink,
|
|
|
|
GST_DEBUG_FUNCPTR (gst_type_find_element_activate_sink_mode));
|
2005-11-09 17:55:13 +00:00
|
|
|
gst_pad_set_chain_function (typefind->sink,
|
|
|
|
GST_DEBUG_FUNCPTR (gst_type_find_element_chain));
|
2005-04-12 10:52:55 +00:00
|
|
|
gst_pad_set_event_function (typefind->sink,
|
2011-06-07 07:43:20 +00:00
|
|
|
GST_DEBUG_FUNCPTR (gst_type_find_element_sink_event));
|
2012-03-16 20:36:33 +00:00
|
|
|
GST_PAD_SET_PROXY_ALLOCATION (typefind->sink);
|
2003-10-28 20:25:30 +00:00
|
|
|
gst_element_add_pad (GST_ELEMENT (typefind), typefind->sink);
|
2005-11-15 19:31:05 +00:00
|
|
|
|
2003-10-28 20:25:30 +00:00
|
|
|
/* srcpad */
|
2005-11-16 17:18:34 +00:00
|
|
|
typefind->src =
|
|
|
|
gst_pad_new_from_static_template (&type_find_element_src_template, "src");
|
2005-11-15 19:31:05 +00:00
|
|
|
|
2011-11-21 12:29:05 +00:00
|
|
|
gst_pad_set_activatemode_function (typefind->src,
|
|
|
|
GST_DEBUG_FUNCPTR (gst_type_find_element_activate_src_mode));
|
2005-11-09 17:55:13 +00:00
|
|
|
gst_pad_set_getrange_function (typefind->src,
|
|
|
|
GST_DEBUG_FUNCPTR (gst_type_find_element_getrange));
|
|
|
|
gst_pad_set_event_function (typefind->src,
|
|
|
|
GST_DEBUG_FUNCPTR (gst_type_find_element_src_event));
|
2004-11-08 15:45:31 +00:00
|
|
|
gst_pad_set_query_function (typefind->src,
|
|
|
|
GST_DEBUG_FUNCPTR (gst_type_find_handle_src_query));
|
2005-04-12 10:52:55 +00:00
|
|
|
gst_pad_use_fixed_caps (typefind->src);
|
2003-10-28 20:25:30 +00:00
|
|
|
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
|
|
|
|
|
gst/base/gstbasesrc.c: Don't go in pull mode for non-seekable sources.
Original commit message from CVS:
* gst/base/gstbasesrc.c: (gst_basesrc_activate):
Don't go in pull mode for non-seekable sources.
* gst/elements/gsttypefindelement.c: (gst_type_find_element_init),
(gst_type_find_element_dispose), (gst_type_find_handle_src_query),
(free_entry), (stop_typefinding),
(gst_type_find_element_handle_event), (find_peek),
(gst_type_find_element_chain), (do_pull_typefind),
(gst_type_find_element_change_state):
Allow typefinding (w/o seeking) in push-mode, simplified version
of what was in 0.8.
* gst/gstutils.c: (gst_buffer_join):
* gst/gstutils.h:
gst_buffer_join() from 0.8.
2005-05-25 15:57:57 +00:00
|
|
|
typefind->mode = MODE_TYPEFIND;
|
2003-10-28 20:25:30 +00:00
|
|
|
typefind->caps = NULL;
|
|
|
|
typefind->min_probability = 1;
|
|
|
|
|
2011-03-21 17:13:55 +00:00
|
|
|
typefind->adapter = gst_adapter_new ();
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|
2009-05-05 15:41:24 +00:00
|
|
|
|
2003-10-28 20:25:30 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_type_find_element_dispose (GObject * object)
|
2003-10-28 20:25:30 +00:00
|
|
|
{
|
|
|
|
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (object);
|
|
|
|
|
2011-03-21 17:13:55 +00:00
|
|
|
if (typefind->adapter) {
|
|
|
|
g_object_unref (typefind->adapter);
|
|
|
|
typefind->adapter = NULL;
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|
2010-02-04 20:11:25 +00:00
|
|
|
|
2009-05-05 15:41:24 +00:00
|
|
|
if (typefind->force_caps) {
|
|
|
|
gst_caps_unref (typefind->force_caps);
|
|
|
|
typefind->force_caps = NULL;
|
|
|
|
}
|
2008-10-31 08:53:27 +00:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|
2008-10-31 08:53:27 +00:00
|
|
|
|
2003-10-28 20:25:30 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_type_find_element_set_property (GObject * object, guint prop_id,
|
|
|
|
const GValue * value, GParamSpec * pspec)
|
2003-10-28 20:25:30 +00:00
|
|
|
{
|
|
|
|
GstTypeFindElement *typefind;
|
|
|
|
|
|
|
|
typefind = GST_TYPE_FIND_ELEMENT (object);
|
|
|
|
|
|
|
|
switch (prop_id) {
|
2008-04-02 17:21:40 +00:00
|
|
|
case PROP_MINIMUM:
|
2003-10-28 20:25:30 +00:00
|
|
|
typefind->min_probability = g_value_get_uint (value);
|
|
|
|
break;
|
2008-04-02 17:21:40 +00:00
|
|
|
case PROP_FORCE_CAPS:
|
|
|
|
GST_OBJECT_LOCK (typefind);
|
|
|
|
if (typefind->force_caps)
|
|
|
|
gst_caps_unref (typefind->force_caps);
|
|
|
|
typefind->force_caps = g_value_dup_boxed (value);
|
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
|
|
|
break;
|
2003-10-28 20:25:30 +00:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-05-05 15:41:24 +00:00
|
|
|
|
2003-10-28 20:25:30 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_type_find_element_get_property (GObject * object, guint prop_id,
|
|
|
|
GValue * value, GParamSpec * pspec)
|
2003-10-28 20:25:30 +00:00
|
|
|
{
|
|
|
|
GstTypeFindElement *typefind;
|
|
|
|
|
|
|
|
typefind = GST_TYPE_FIND_ELEMENT (object);
|
|
|
|
|
|
|
|
switch (prop_id) {
|
2008-04-02 17:21:40 +00:00
|
|
|
case PROP_CAPS:
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_LOCK (typefind);
|
2003-10-28 20:25:30 +00:00
|
|
|
g_value_set_boxed (value, typefind->caps);
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
2003-10-28 20:25:30 +00:00
|
|
|
break;
|
2008-04-02 17:21:40 +00:00
|
|
|
case PROP_MINIMUM:
|
2003-10-28 20:25:30 +00:00
|
|
|
g_value_set_uint (value, typefind->min_probability);
|
|
|
|
break;
|
2008-04-02 17:21:40 +00:00
|
|
|
case PROP_FORCE_CAPS:
|
|
|
|
GST_OBJECT_LOCK (typefind);
|
|
|
|
g_value_set_boxed (value, typefind->force_caps);
|
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
|
|
|
break;
|
2003-10-28 20:25:30 +00:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-11-08 15:45:31 +00:00
|
|
|
|
|
|
|
static gboolean
|
2011-11-16 16:22:56 +00:00
|
|
|
gst_type_find_handle_src_query (GstPad * pad, GstObject * parent,
|
|
|
|
GstQuery * query)
|
2004-11-08 15:45:31 +00:00
|
|
|
{
|
2005-05-09 10:53:13 +00:00
|
|
|
GstTypeFindElement *typefind;
|
2005-12-14 10:09:35 +00:00
|
|
|
gboolean res = FALSE;
|
2004-11-08 15:45:31 +00:00
|
|
|
|
2011-11-16 16:22:56 +00:00
|
|
|
typefind = GST_TYPE_FIND_ELEMENT (parent);
|
2012-01-25 12:35:43 +00:00
|
|
|
GST_DEBUG_OBJECT (typefind, "Handling src query %s",
|
|
|
|
GST_QUERY_TYPE_NAME (query));
|
|
|
|
|
2011-05-17 09:20:05 +00:00
|
|
|
switch (GST_QUERY_TYPE (query)) {
|
2012-02-14 12:24:49 +00:00
|
|
|
case GST_QUERY_SCHEDULING:
|
|
|
|
/* FIXME, filter out the scheduling modes that we understand */
|
|
|
|
res = gst_pad_peer_query (typefind->sink, query);
|
|
|
|
break;
|
|
|
|
case GST_QUERY_CAPS:
|
|
|
|
{
|
|
|
|
GST_DEBUG_OBJECT (typefind,
|
|
|
|
"Got caps query, our caps are %" GST_PTR_FORMAT, typefind->caps);
|
|
|
|
|
|
|
|
/* We can hijack caps query if we typefind already */
|
|
|
|
if (typefind->caps) {
|
|
|
|
gst_query_set_caps_result (query, typefind->caps);
|
|
|
|
res = TRUE;
|
|
|
|
} else {
|
|
|
|
res = gst_pad_peer_query (typefind->sink, query);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2005-05-09 10:53:13 +00:00
|
|
|
case GST_QUERY_POSITION:
|
|
|
|
{
|
gst/: API change fix.
Original commit message from CVS:
* gst/base/gstbasesink.c: (gst_base_sink_commit_state),
(gst_base_sink_handle_object), (gst_base_sink_query), (do_playing):
* gst/base/gstbasesrc.c: (gst_base_src_query):
* gst/elements/gstfilesink.c: (gst_file_sink_query):
* gst/elements/gsttypefindelement.c:
(gst_type_find_handle_src_query), (find_element_get_length),
(gst_type_find_element_activate):
API change fix.
* gst/gstquery.c: (gst_query_new_position),
(gst_query_set_position), (gst_query_parse_position),
(gst_query_new_duration), (gst_query_set_duration),
(gst_query_parse_duration), (gst_query_set_segment),
(gst_query_parse_segment):
* gst/gstquery.h:
Bundling query position/duration is not a good idea since duration
does not change much and we don't want to recalculate it for every
position query, so they are separated again..
Base value in segment query is not needed.
* gst/gstqueue.c: (gst_queue_handle_src_query):
* gst/gstutils.c: (gst_element_query_position),
(gst_element_query_duration), (gst_pad_query_position),
(gst_pad_query_duration):
* gst/gstutils.h:
Updates for query API change.
Added some docs here and there.
2005-10-19 15:50:10 +00:00
|
|
|
gint64 peer_pos;
|
2005-05-09 10:53:13 +00:00
|
|
|
GstFormat format;
|
|
|
|
|
2012-02-14 12:24:49 +00:00
|
|
|
if (!(res = gst_pad_peer_query (typefind->sink, query)))
|
|
|
|
goto out;
|
|
|
|
|
2011-05-17 09:20:05 +00:00
|
|
|
gst_query_parse_position (query, &format, &peer_pos);
|
2005-05-09 10:53:13 +00:00
|
|
|
|
2011-03-21 17:13:55 +00:00
|
|
|
GST_OBJECT_LOCK (typefind);
|
2005-05-09 10:53:13 +00:00
|
|
|
/* FIXME: this code assumes that there's no discont in the queue */
|
|
|
|
switch (format) {
|
|
|
|
case GST_FORMAT_BYTES:
|
2011-03-21 17:13:55 +00:00
|
|
|
peer_pos -= gst_adapter_available (typefind->adapter);
|
2005-05-09 10:53:13 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* FIXME */
|
|
|
|
break;
|
|
|
|
}
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
2011-05-17 09:20:05 +00:00
|
|
|
gst_query_set_position (query, format, peer_pos);
|
2005-05-09 10:53:13 +00:00
|
|
|
break;
|
2004-11-08 15:45:31 +00:00
|
|
|
}
|
2005-05-09 10:53:13 +00:00
|
|
|
default:
|
2012-02-14 12:24:49 +00:00
|
|
|
res = gst_pad_query_default (pad, parent, query);
|
2005-05-09 10:53:13 +00:00
|
|
|
break;
|
2004-11-08 15:45:31 +00:00
|
|
|
}
|
2005-12-14 10:09:35 +00:00
|
|
|
out:
|
|
|
|
return res;
|
2004-11-08 15:45:31 +00:00
|
|
|
}
|
|
|
|
|
2012-01-27 15:18:00 +00:00
|
|
|
static gboolean
|
|
|
|
gst_type_find_element_seek (GstTypeFindElement * typefind, GstEvent * event)
|
2003-10-28 20:25:30 +00:00
|
|
|
{
|
2012-01-27 15:18:00 +00:00
|
|
|
GstSeekFlags flags;
|
2012-07-27 13:19:57 +00:00
|
|
|
GstSeekType start_type, stop_type;
|
2012-01-27 15:18:00 +00:00
|
|
|
GstFormat format;
|
|
|
|
gboolean flush;
|
|
|
|
gdouble rate;
|
2012-07-27 13:19:57 +00:00
|
|
|
gint64 start, stop;
|
2012-01-27 15:18:00 +00:00
|
|
|
GstSegment seeksegment = { 0, };
|
|
|
|
|
2012-07-27 13:19:57 +00:00
|
|
|
gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
|
2012-01-27 15:18:00 +00:00
|
|
|
&stop_type, &stop);
|
|
|
|
|
|
|
|
/* we can only seek on bytes */
|
|
|
|
if (format != GST_FORMAT_BYTES) {
|
|
|
|
GST_DEBUG_OBJECT (typefind, "Can only seek on BYTES");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy segment, we need this because we still need the old
|
|
|
|
* segment when we close the current segment. */
|
|
|
|
memcpy (&seeksegment, &typefind->segment, sizeof (GstSegment));
|
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (typefind, "configuring seek");
|
|
|
|
gst_segment_do_seek (&seeksegment, rate, format, flags,
|
2012-07-27 13:19:57 +00:00
|
|
|
start_type, start, stop_type, stop, NULL);
|
2012-01-27 15:18:00 +00:00
|
|
|
|
2012-06-20 08:31:49 +00:00
|
|
|
flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
|
2012-01-27 15:18:00 +00:00
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (typefind, "New segment %" GST_SEGMENT_FORMAT, &seeksegment);
|
|
|
|
|
|
|
|
if (flush) {
|
|
|
|
GST_DEBUG_OBJECT (typefind, "Starting flush");
|
|
|
|
gst_pad_push_event (typefind->sink, gst_event_new_flush_start ());
|
|
|
|
gst_pad_push_event (typefind->src, gst_event_new_flush_start ());
|
|
|
|
} else {
|
|
|
|
GST_DEBUG_OBJECT (typefind, "Non-flushing seek, pausing task");
|
|
|
|
gst_pad_pause_task (typefind->sink);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now grab the stream lock so that streaming cannot continue, for
|
|
|
|
* non flushing seeks when the element is in PAUSED this could block
|
|
|
|
* forever. */
|
|
|
|
GST_DEBUG_OBJECT (typefind, "Waiting for streaming to stop");
|
|
|
|
GST_PAD_STREAM_LOCK (typefind->sink);
|
|
|
|
|
|
|
|
if (flush) {
|
|
|
|
GST_DEBUG_OBJECT (typefind, "Stopping flush");
|
|
|
|
gst_pad_push_event (typefind->sink, gst_event_new_flush_stop (TRUE));
|
|
|
|
gst_pad_push_event (typefind->src, gst_event_new_flush_stop (TRUE));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now update the real segment info */
|
|
|
|
GST_DEBUG_OBJECT (typefind, "Committing new seek segment");
|
|
|
|
memcpy (&typefind->segment, &seeksegment, sizeof (GstSegment));
|
|
|
|
typefind->offset = typefind->segment.start;
|
|
|
|
|
|
|
|
/* notify start of new segment */
|
2012-07-09 20:51:07 +00:00
|
|
|
if (typefind->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
|
2012-01-27 15:18:00 +00:00
|
|
|
GstMessage *msg;
|
|
|
|
|
|
|
|
msg = gst_message_new_segment_start (GST_OBJECT (typefind),
|
|
|
|
GST_FORMAT_BYTES, typefind->segment.start);
|
|
|
|
gst_element_post_message (GST_ELEMENT (typefind), msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
typefind->need_segment = TRUE;
|
|
|
|
|
|
|
|
/* restart our task since it might have been stopped when we did the
|
|
|
|
* flush. */
|
|
|
|
gst_pad_start_task (typefind->sink,
|
2012-06-20 08:31:49 +00:00
|
|
|
(GstTaskFunction) gst_type_find_element_loop, typefind->sink, NULL);
|
2012-01-27 15:18:00 +00:00
|
|
|
|
|
|
|
/* streaming can continue now */
|
|
|
|
GST_PAD_STREAM_UNLOCK (typefind->sink);
|
|
|
|
|
|
|
|
return TRUE;
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|
2004-03-13 15:27:01 +00:00
|
|
|
|
|
|
|
static gboolean
|
2011-11-17 11:40:45 +00:00
|
|
|
gst_type_find_element_src_event (GstPad * pad, GstObject * parent,
|
|
|
|
GstEvent * event)
|
2003-10-28 20:25:30 +00:00
|
|
|
{
|
2011-11-17 11:40:45 +00:00
|
|
|
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (parent);
|
2015-04-13 12:40:22 +00:00
|
|
|
gboolean result;
|
2003-10-28 20:25:30 +00:00
|
|
|
|
2004-09-26 17:48:05 +00:00
|
|
|
if (typefind->mode != MODE_NORMAL) {
|
2003-10-28 20:25:30 +00:00
|
|
|
/* need to do more? */
|
2015-04-13 15:01:41 +00:00
|
|
|
gst_event_unref (event);
|
2003-10-28 20:25:30 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2012-01-27 15:18:00 +00:00
|
|
|
|
|
|
|
/* Only handle seeks here if driving the pipeline */
|
|
|
|
if (typefind->segment.format != GST_FORMAT_UNDEFINED &&
|
|
|
|
GST_EVENT_TYPE (event) == GST_EVENT_SEEK) {
|
2015-04-13 12:40:22 +00:00
|
|
|
result = gst_type_find_element_seek (typefind, event);
|
2015-04-13 15:01:41 +00:00
|
|
|
gst_event_unref (event);
|
2015-04-13 12:40:22 +00:00
|
|
|
return result;
|
2012-01-27 15:18:00 +00:00
|
|
|
} else {
|
|
|
|
return gst_pad_push_event (typefind->sink, event);
|
|
|
|
}
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|
2004-02-03 22:13:13 +00:00
|
|
|
|
2003-10-28 20:25:30 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
start_typefinding (GstTypeFindElement * typefind)
|
2003-10-28 20:25:30 +00:00
|
|
|
{
|
|
|
|
GST_DEBUG_OBJECT (typefind, "starting typefinding");
|
2010-02-04 20:11:25 +00:00
|
|
|
|
|
|
|
GST_OBJECT_LOCK (typefind);
|
|
|
|
if (typefind->caps)
|
2004-05-06 21:40:55 +00:00
|
|
|
gst_caps_replace (&typefind->caps, NULL);
|
2014-12-10 11:17:11 +00:00
|
|
|
typefind->initial_offset = GST_BUFFER_OFFSET_NONE;
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
typefind->mode = MODE_TYPEFIND;
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|
2005-12-12 17:09:04 +00:00
|
|
|
|
2003-10-28 20:25:30 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
stop_typefinding (GstTypeFindElement * typefind)
|
2003-10-28 20:25:30 +00:00
|
|
|
{
|
2005-09-02 15:42:00 +00:00
|
|
|
GstState state;
|
2005-04-12 10:52:55 +00:00
|
|
|
gboolean push_cached_buffers;
|
2011-03-21 17:13:55 +00:00
|
|
|
gsize avail;
|
|
|
|
GstBuffer *buffer;
|
2014-07-17 05:07:36 +00:00
|
|
|
GstClockTime pts, dts;
|
2005-04-12 10:52:55 +00:00
|
|
|
|
2006-02-26 19:20:51 +00:00
|
|
|
gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, 0);
|
2005-04-12 10:52:55 +00:00
|
|
|
|
2013-04-29 10:48:13 +00:00
|
|
|
push_cached_buffers = (state >= GST_STATE_PAUSED && typefind->caps);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (typefind, "stopping typefinding%s",
|
2013-04-29 10:58:07 +00:00
|
|
|
push_cached_buffers ? " and pushing cached events and buffers" : "");
|
2003-10-28 20:25:30 +00:00
|
|
|
|
2013-04-29 11:20:11 +00:00
|
|
|
typefind->mode = MODE_NORMAL;
|
2013-04-29 10:58:07 +00:00
|
|
|
if (push_cached_buffers)
|
|
|
|
gst_type_find_element_send_cached_events (typefind);
|
|
|
|
|
|
|
|
GST_OBJECT_LOCK (typefind);
|
2011-03-21 17:13:55 +00:00
|
|
|
avail = gst_adapter_available (typefind->adapter);
|
|
|
|
if (avail == 0)
|
|
|
|
goto no_data;
|
2010-02-04 20:11:25 +00:00
|
|
|
|
2014-07-17 05:07:36 +00:00
|
|
|
pts = gst_adapter_prev_pts (typefind->adapter, NULL);
|
|
|
|
dts = gst_adapter_prev_dts (typefind->adapter, NULL);
|
2011-03-21 17:13:55 +00:00
|
|
|
buffer = gst_adapter_take_buffer (typefind->adapter, avail);
|
2014-07-17 05:07:36 +00:00
|
|
|
GST_BUFFER_PTS (buffer) = pts;
|
|
|
|
GST_BUFFER_DTS (buffer) = dts;
|
2014-12-10 11:17:11 +00:00
|
|
|
GST_BUFFER_OFFSET (buffer) = typefind->initial_offset;
|
2011-03-21 17:13:55 +00:00
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
2005-12-12 17:09:04 +00:00
|
|
|
|
2011-03-21 17:13:55 +00:00
|
|
|
if (!push_cached_buffers) {
|
|
|
|
gst_buffer_unref (buffer);
|
2010-02-04 20:11:25 +00:00
|
|
|
} else {
|
2011-03-21 17:13:55 +00:00
|
|
|
GstPad *peer = gst_pad_get_peer (typefind->src);
|
|
|
|
|
|
|
|
/* make sure the user gets a meaningful error message in this case,
|
|
|
|
* which is not a core bug or bug of any kind (as the default error
|
|
|
|
* message emitted by gstpad.c otherwise would make you think) */
|
|
|
|
if (peer && GST_PAD_CHAINFUNC (peer) == NULL) {
|
|
|
|
GST_DEBUG_OBJECT (typefind, "upstream only supports push mode, while "
|
|
|
|
"downstream element only works in pull mode, erroring out");
|
|
|
|
GST_ELEMENT_ERROR (typefind, STREAM, FAILED,
|
|
|
|
("%s cannot work in push mode. The operation is not supported "
|
|
|
|
"with this source element or protocol.",
|
|
|
|
G_OBJECT_TYPE_NAME (GST_PAD_PARENT (peer))),
|
|
|
|
("Downstream pad %s:%s has no chainfunction, and the upstream "
|
|
|
|
"element does not support pull mode", GST_DEBUG_PAD_NAME (peer)));
|
|
|
|
typefind->mode = MODE_ERROR; /* make the chain function error out */
|
|
|
|
gst_buffer_unref (buffer);
|
|
|
|
} else {
|
|
|
|
gst_pad_push (typefind->src, buffer);
|
|
|
|
}
|
|
|
|
if (peer)
|
|
|
|
gst_object_unref (peer);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* ERRORS */
|
|
|
|
no_data:
|
|
|
|
{
|
|
|
|
GST_DEBUG_OBJECT (typefind, "we have no data to typefind");
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
2011-03-21 17:13:55 +00:00
|
|
|
return;
|
2004-09-26 17:48:05 +00:00
|
|
|
}
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2005-04-12 10:52:55 +00:00
|
|
|
static gboolean
|
2011-11-17 11:40:45 +00:00
|
|
|
gst_type_find_element_sink_event (GstPad * pad, GstObject * parent,
|
|
|
|
GstEvent * event)
|
2003-10-28 20:25:30 +00:00
|
|
|
{
|
2005-04-12 10:52:55 +00:00
|
|
|
gboolean res = FALSE;
|
2011-11-17 11:40:45 +00:00
|
|
|
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (parent);
|
2003-10-28 20:25:30 +00:00
|
|
|
|
2005-12-12 17:09:04 +00:00
|
|
|
GST_DEBUG_OBJECT (typefind, "got %s event in mode %d",
|
|
|
|
GST_EVENT_TYPE_NAME (event), typefind->mode);
|
2004-10-08 09:36:50 +00:00
|
|
|
|
2004-09-26 17:48:05 +00:00
|
|
|
switch (typefind->mode) {
|
|
|
|
case MODE_TYPEFIND:
|
|
|
|
switch (GST_EVENT_TYPE (event)) {
|
2011-06-07 07:43:20 +00:00
|
|
|
case GST_EVENT_CAPS:
|
|
|
|
{
|
|
|
|
GstCaps *caps;
|
|
|
|
|
2013-04-29 10:56:54 +00:00
|
|
|
/* Parse and push out our caps and data */
|
2011-06-07 07:43:20 +00:00
|
|
|
gst_event_parse_caps (event, &caps);
|
|
|
|
res = gst_type_find_element_setcaps (typefind, caps);
|
|
|
|
|
|
|
|
gst_event_unref (event);
|
|
|
|
break;
|
|
|
|
}
|
2013-04-29 10:52:46 +00:00
|
|
|
case GST_EVENT_GAP:
|
|
|
|
{
|
|
|
|
GST_FIXME_OBJECT (typefind,
|
|
|
|
"GAP events during typefinding not handled properly");
|
|
|
|
|
|
|
|
/* FIXME: These would need to be inserted in the stream at
|
|
|
|
* the right position between buffers, but we combine all
|
|
|
|
* buffers with a GstAdapter. Drop the GAP event for now,
|
|
|
|
* which will only cause an implicit GAP between buffers.
|
|
|
|
*/
|
|
|
|
gst_event_unref (event);
|
|
|
|
res = TRUE;
|
2013-09-04 12:40:57 +00:00
|
|
|
break;
|
2013-04-29 10:52:46 +00:00
|
|
|
}
|
2011-03-21 17:13:55 +00:00
|
|
|
case GST_EVENT_EOS:
|
|
|
|
{
|
2006-02-27 20:01:53 +00:00
|
|
|
GST_INFO_OBJECT (typefind, "Got EOS and no type found yet");
|
2015-06-05 08:02:04 +00:00
|
|
|
gst_type_find_element_chain_do_typefinding (typefind, FALSE, TRUE);
|
2005-12-12 17:09:04 +00:00
|
|
|
|
2008-05-27 10:57:11 +00:00
|
|
|
res = gst_pad_push_event (typefind->src, event);
|
2004-09-26 17:48:05 +00:00
|
|
|
break;
|
2005-12-12 17:09:04 +00:00
|
|
|
}
|
2014-05-31 15:35:52 +00:00
|
|
|
case GST_EVENT_FLUSH_STOP:{
|
|
|
|
GList *l;
|
|
|
|
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_LOCK (typefind);
|
2014-05-31 15:35:52 +00:00
|
|
|
|
|
|
|
for (l = typefind->cached_events; l; l = l->next) {
|
2014-09-17 15:17:10 +00:00
|
|
|
if (GST_EVENT_IS_STICKY (l->data) &&
|
|
|
|
GST_EVENT_TYPE (l->data) != GST_EVENT_SEGMENT &&
|
|
|
|
GST_EVENT_TYPE (l->data) != GST_EVENT_EOS) {
|
2014-05-31 15:35:52 +00:00
|
|
|
gst_pad_store_sticky_event (typefind->src, l->data);
|
|
|
|
}
|
2014-09-17 15:17:10 +00:00
|
|
|
gst_event_unref (l->data);
|
2014-05-31 15:35:52 +00:00
|
|
|
}
|
|
|
|
|
2008-05-13 11:45:24 +00:00
|
|
|
g_list_free (typefind->cached_events);
|
|
|
|
typefind->cached_events = NULL;
|
2011-03-21 17:13:55 +00:00
|
|
|
gst_adapter_clear (typefind->adapter);
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
2008-05-13 12:38:31 +00:00
|
|
|
/* fall through */
|
2014-05-31 15:35:52 +00:00
|
|
|
}
|
2008-05-13 12:38:31 +00:00
|
|
|
case GST_EVENT_FLUSH_START:
|
2008-05-27 10:57:11 +00:00
|
|
|
res = gst_pad_push_event (typefind->src, event);
|
2008-05-13 11:45:24 +00:00
|
|
|
break;
|
2004-09-26 17:48:05 +00:00
|
|
|
default:
|
2013-04-29 10:48:29 +00:00
|
|
|
/* Forward events that would happen before the caps event
|
|
|
|
* directly instead of storing them. There's no reason not
|
|
|
|
* to send them directly and we should only store events
|
|
|
|
* for later sending that would need to come after the caps
|
|
|
|
* event */
|
|
|
|
if (GST_EVENT_TYPE (event) < GST_EVENT_CAPS) {
|
|
|
|
res = gst_pad_push_event (typefind->src, event);
|
|
|
|
} else {
|
|
|
|
GST_DEBUG_OBJECT (typefind, "Saving %s event to send later",
|
|
|
|
GST_EVENT_TYPE_NAME (event));
|
|
|
|
GST_OBJECT_LOCK (typefind);
|
|
|
|
typefind->cached_events =
|
|
|
|
g_list_append (typefind->cached_events, event);
|
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
|
|
|
res = TRUE;
|
|
|
|
}
|
2004-09-26 17:48:05 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MODE_NORMAL:
|
2008-05-27 10:57:11 +00:00
|
|
|
res = gst_pad_push_event (typefind->src, event);
|
2004-09-26 17:48:05 +00:00
|
|
|
break;
|
2005-12-12 17:09:04 +00:00
|
|
|
case MODE_ERROR:
|
|
|
|
break;
|
2004-09-26 17:48:05 +00:00
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|
2005-04-12 10:52:55 +00:00
|
|
|
return res;
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|
2005-04-12 10:52:55 +00:00
|
|
|
|
2006-03-29 10:33:19 +00:00
|
|
|
static void
|
|
|
|
gst_type_find_element_send_cached_events (GstTypeFindElement * typefind)
|
|
|
|
{
|
2010-02-04 20:11:25 +00:00
|
|
|
GList *l, *cached_events;
|
2006-03-29 10:33:19 +00:00
|
|
|
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_LOCK (typefind);
|
|
|
|
cached_events = typefind->cached_events;
|
|
|
|
typefind->cached_events = NULL;
|
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
|
|
|
|
|
|
|
for (l = cached_events; l != NULL; l = l->next) {
|
2006-03-29 10:33:19 +00:00
|
|
|
GstEvent *event = GST_EVENT (l->data);
|
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (typefind, "sending cached %s event",
|
|
|
|
GST_EVENT_TYPE_NAME (event));
|
|
|
|
gst_pad_push_event (typefind->src, event);
|
|
|
|
}
|
2010-02-04 20:11:25 +00:00
|
|
|
g_list_free (cached_events);
|
2006-03-29 10:33:19 +00:00
|
|
|
}
|
|
|
|
|
2007-10-08 10:28:18 +00:00
|
|
|
static gboolean
|
2011-06-07 07:43:20 +00:00
|
|
|
gst_type_find_element_setcaps (GstTypeFindElement * typefind, GstCaps * caps)
|
2003-10-28 20:25:30 +00:00
|
|
|
{
|
2007-10-08 10:28:18 +00:00
|
|
|
/* don't operate on ANY caps */
|
|
|
|
if (gst_caps_is_any (caps))
|
|
|
|
return TRUE;
|
2006-03-31 15:26:04 +00:00
|
|
|
|
2007-10-08 10:28:18 +00:00
|
|
|
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
|
|
|
|
GST_TYPE_FIND_MAXIMUM, caps);
|
|
|
|
|
|
|
|
/* Shortcircuit typefinding if we get caps */
|
2013-04-29 11:03:24 +00:00
|
|
|
GST_DEBUG_OBJECT (typefind, "Skipping typefinding, using caps from "
|
|
|
|
"upstream: %" GST_PTR_FORMAT, caps);
|
2010-02-04 20:11:25 +00:00
|
|
|
|
2013-04-29 11:03:24 +00:00
|
|
|
stop_typefinding (typefind);
|
2006-03-31 15:26:04 +00:00
|
|
|
|
2007-10-08 10:28:18 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-01-12 16:38:32 +00:00
|
|
|
static gchar *
|
|
|
|
gst_type_find_get_extension (GstTypeFindElement * typefind, GstPad * pad)
|
2009-01-21 11:50:29 +00:00
|
|
|
{
|
|
|
|
GstQuery *query;
|
2010-01-12 16:38:32 +00:00
|
|
|
gchar *uri, *result;
|
2009-01-21 11:50:29 +00:00
|
|
|
size_t len;
|
|
|
|
gint find;
|
|
|
|
|
|
|
|
query = gst_query_new_uri ();
|
|
|
|
|
|
|
|
/* try getting the caps with an uri query and from the extension */
|
2011-05-17 09:20:05 +00:00
|
|
|
if (!gst_pad_peer_query (pad, query))
|
2009-01-21 11:50:29 +00:00
|
|
|
goto peer_query_failed;
|
|
|
|
|
|
|
|
gst_query_parse_uri (query, &uri);
|
|
|
|
if (uri == NULL)
|
|
|
|
goto no_uri;
|
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (typefind, "finding extension of %s", uri);
|
|
|
|
|
|
|
|
/* find the extension on the uri, this is everything after a '.' */
|
|
|
|
len = strlen (uri);
|
|
|
|
find = len - 1;
|
|
|
|
|
|
|
|
while (find >= 0) {
|
|
|
|
if (uri[find] == '.')
|
|
|
|
break;
|
|
|
|
find--;
|
|
|
|
}
|
2009-05-05 15:41:24 +00:00
|
|
|
if (find < 0)
|
2009-01-21 11:50:29 +00:00
|
|
|
goto no_extension;
|
|
|
|
|
2010-01-12 16:38:32 +00:00
|
|
|
result = g_strdup (&uri[find + 1]);
|
2009-01-21 11:50:29 +00:00
|
|
|
|
2010-01-12 16:38:32 +00:00
|
|
|
GST_DEBUG_OBJECT (typefind, "found extension %s", result);
|
2009-01-21 11:50:29 +00:00
|
|
|
gst_query_unref (query);
|
2010-01-22 02:02:01 +00:00
|
|
|
g_free (uri);
|
2009-01-21 11:50:29 +00:00
|
|
|
|
2010-01-12 16:38:32 +00:00
|
|
|
return result;
|
2009-01-21 11:50:29 +00:00
|
|
|
|
|
|
|
/* ERRORS */
|
|
|
|
peer_query_failed:
|
|
|
|
{
|
|
|
|
GST_WARNING_OBJECT (typefind, "failed to query peer uri");
|
|
|
|
gst_query_unref (query);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
no_uri:
|
|
|
|
{
|
|
|
|
GST_WARNING_OBJECT (typefind, "could not parse the peer uri");
|
|
|
|
gst_query_unref (query);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
no_extension:
|
|
|
|
{
|
|
|
|
GST_WARNING_OBJECT (typefind, "could not find uri extension in %s", uri);
|
|
|
|
gst_query_unref (query);
|
2010-01-22 02:02:01 +00:00
|
|
|
g_free (uri);
|
2009-01-21 11:50:29 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-12 16:38:32 +00:00
|
|
|
static GstCaps *
|
|
|
|
gst_type_find_guess_by_extension (GstTypeFindElement * typefind, GstPad * pad,
|
|
|
|
GstTypeFindProbability * probability)
|
|
|
|
{
|
|
|
|
gchar *ext;
|
|
|
|
GstCaps *caps;
|
|
|
|
|
|
|
|
ext = gst_type_find_get_extension (typefind, pad);
|
|
|
|
if (!ext)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
caps = gst_type_find_helper_for_extension (GST_OBJECT_CAST (typefind), ext);
|
|
|
|
if (caps)
|
|
|
|
*probability = GST_TYPE_FIND_MAXIMUM;
|
|
|
|
|
|
|
|
g_free (ext);
|
|
|
|
|
|
|
|
return caps;
|
|
|
|
}
|
|
|
|
|
2007-10-08 10:28:18 +00:00
|
|
|
static GstFlowReturn
|
2011-11-17 11:40:45 +00:00
|
|
|
gst_type_find_element_chain (GstPad * pad, GstObject * parent,
|
|
|
|
GstBuffer * buffer)
|
2007-10-08 10:28:18 +00:00
|
|
|
{
|
|
|
|
GstTypeFindElement *typefind;
|
|
|
|
GstFlowReturn res = GST_FLOW_OK;
|
|
|
|
|
2011-11-17 11:40:45 +00:00
|
|
|
typefind = GST_TYPE_FIND_ELEMENT (parent);
|
2007-10-08 10:28:18 +00:00
|
|
|
|
2010-07-15 20:05:09 +00:00
|
|
|
GST_LOG_OBJECT (typefind, "handling buffer in mode %d", typefind->mode);
|
|
|
|
|
2003-10-28 20:25:30 +00:00
|
|
|
switch (typefind->mode) {
|
2005-12-12 17:09:04 +00:00
|
|
|
case MODE_ERROR:
|
|
|
|
/* we should already have called GST_ELEMENT_ERROR */
|
|
|
|
return GST_FLOW_ERROR;
|
2003-10-28 20:25:30 +00:00
|
|
|
case MODE_NORMAL:
|
2011-05-05 08:37:19 +00:00
|
|
|
/* don't take object lock as typefind->caps should not change anymore */
|
2005-04-12 10:52:55 +00:00
|
|
|
return gst_pad_push (typefind->src, buffer);
|
2011-03-21 17:13:55 +00:00
|
|
|
case MODE_TYPEFIND:
|
|
|
|
{
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_LOCK (typefind);
|
2014-12-10 11:17:11 +00:00
|
|
|
if (typefind->initial_offset == GST_BUFFER_OFFSET_NONE)
|
|
|
|
typefind->initial_offset = GST_BUFFER_OFFSET (buffer);
|
2011-03-21 17:13:55 +00:00
|
|
|
gst_adapter_push (typefind->adapter, buffer);
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
2005-04-12 10:52:55 +00:00
|
|
|
|
2015-06-05 08:02:04 +00:00
|
|
|
res = gst_type_find_element_chain_do_typefinding (typefind, TRUE, FALSE);
|
2005-12-12 17:09:04 +00:00
|
|
|
|
|
|
|
if (typefind->mode == MODE_ERROR)
|
|
|
|
res = GST_FLOW_ERROR;
|
|
|
|
|
2003-10-28 20:25:30 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
2005-04-12 10:52:55 +00:00
|
|
|
return GST_FLOW_ERROR;
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|
2005-04-12 10:52:55 +00:00
|
|
|
|
|
|
|
return res;
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|
2005-04-12 10:52:55 +00:00
|
|
|
|
2006-03-03 14:18:01 +00:00
|
|
|
static GstFlowReturn
|
2011-03-21 17:13:55 +00:00
|
|
|
gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind,
|
2015-06-05 08:02:04 +00:00
|
|
|
gboolean check_avail, gboolean at_eos)
|
2006-03-03 14:18:01 +00:00
|
|
|
{
|
|
|
|
GstTypeFindProbability probability;
|
2013-05-15 11:22:04 +00:00
|
|
|
GstCaps *caps = NULL;
|
2011-03-21 17:13:55 +00:00
|
|
|
gsize avail;
|
|
|
|
const guint8 *data;
|
|
|
|
gboolean have_min, have_max;
|
2006-03-03 14:18:01 +00:00
|
|
|
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_LOCK (typefind);
|
2013-05-15 11:22:04 +00:00
|
|
|
if (typefind->force_caps) {
|
|
|
|
caps = gst_caps_ref (typefind->force_caps);
|
|
|
|
probability = GST_TYPE_FIND_MAXIMUM;
|
2011-03-21 17:13:55 +00:00
|
|
|
}
|
|
|
|
|
2013-05-15 11:22:04 +00:00
|
|
|
if (!caps) {
|
|
|
|
avail = gst_adapter_available (typefind->adapter);
|
|
|
|
|
|
|
|
if (check_avail) {
|
|
|
|
have_min = avail >= TYPE_FIND_MIN_SIZE;
|
|
|
|
have_max = avail >= TYPE_FIND_MAX_SIZE;
|
|
|
|
} else {
|
|
|
|
have_min = avail > 0;
|
|
|
|
have_max = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!have_min)
|
|
|
|
goto not_enough_data;
|
|
|
|
|
|
|
|
/* map all available data */
|
|
|
|
data = gst_adapter_map (typefind->adapter, avail);
|
|
|
|
caps = gst_type_find_helper_for_data (GST_OBJECT (typefind),
|
|
|
|
data, avail, &probability);
|
|
|
|
gst_adapter_unmap (typefind->adapter);
|
2011-03-21 17:13:55 +00:00
|
|
|
|
2013-05-15 11:22:04 +00:00
|
|
|
if (caps == NULL && have_max)
|
|
|
|
goto no_type_found;
|
|
|
|
else if (caps == NULL)
|
|
|
|
goto wait_for_data;
|
2011-03-21 17:13:55 +00:00
|
|
|
|
2013-05-15 11:22:04 +00:00
|
|
|
/* found a type */
|
|
|
|
if (probability < typefind->min_probability)
|
|
|
|
goto low_probability;
|
|
|
|
}
|
2011-03-21 17:13:55 +00:00
|
|
|
|
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
|
|
|
|
|
|
|
/* probability is good enough too, so let's make it known ... emiting this
|
|
|
|
* signal calls our object handler which sets the caps. */
|
|
|
|
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
|
|
|
|
probability, caps);
|
|
|
|
|
|
|
|
/* .. and send out the accumulated data */
|
|
|
|
stop_typefinding (typefind);
|
|
|
|
gst_caps_unref (caps);
|
|
|
|
|
|
|
|
return GST_FLOW_OK;
|
|
|
|
|
|
|
|
not_enough_data:
|
|
|
|
{
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
2015-06-05 08:02:04 +00:00
|
|
|
|
|
|
|
if (at_eos) {
|
|
|
|
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
|
|
|
|
(_("Stream contains not enough data.")), ("Can't typefind stream"));
|
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
} else {
|
|
|
|
GST_DEBUG_OBJECT (typefind, "not enough data for typefinding yet "
|
|
|
|
"(%" G_GSIZE_FORMAT " bytes)", avail);
|
|
|
|
return GST_FLOW_OK;
|
|
|
|
}
|
2006-03-03 14:18:01 +00:00
|
|
|
}
|
2011-03-21 17:13:55 +00:00
|
|
|
no_type_found:
|
|
|
|
{
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
2006-03-03 14:18:01 +00:00
|
|
|
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
|
|
|
|
stop_typefinding (typefind);
|
|
|
|
return GST_FLOW_ERROR;
|
2011-03-21 17:13:55 +00:00
|
|
|
}
|
|
|
|
wait_for_data:
|
|
|
|
{
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
2015-06-05 08:02:04 +00:00
|
|
|
|
|
|
|
if (at_eos) {
|
|
|
|
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
|
|
|
|
(_("Stream contains not enough data.")), ("Can't typefind stream"));
|
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
} else {
|
|
|
|
GST_DEBUG_OBJECT (typefind,
|
|
|
|
"no caps found with %" G_GSIZE_FORMAT " bytes of data, "
|
|
|
|
"waiting for more data", avail);
|
|
|
|
return GST_FLOW_OK;
|
|
|
|
}
|
2006-03-03 14:18:01 +00:00
|
|
|
}
|
2011-03-21 17:13:55 +00:00
|
|
|
low_probability:
|
|
|
|
{
|
2006-03-03 14:18:01 +00:00
|
|
|
GST_DEBUG_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", but "
|
|
|
|
"probability is %u which is lower than the required minimum of %u",
|
|
|
|
caps, probability, typefind->min_probability);
|
|
|
|
|
2011-03-21 17:13:55 +00:00
|
|
|
gst_caps_unref (caps);
|
2007-01-30 19:12:54 +00:00
|
|
|
|
2011-03-21 17:13:55 +00:00
|
|
|
if (have_max)
|
|
|
|
goto no_type_found;
|
2006-03-03 14:18:01 +00:00
|
|
|
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
2006-03-03 14:18:01 +00:00
|
|
|
GST_DEBUG_OBJECT (typefind, "waiting for more data to try again");
|
|
|
|
return GST_FLOW_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-12 10:52:55 +00:00
|
|
|
static GstFlowReturn
|
2011-11-17 11:40:45 +00:00
|
|
|
gst_type_find_element_getrange (GstPad * srcpad, GstObject * parent,
|
2005-04-12 10:52:55 +00:00
|
|
|
guint64 offset, guint length, GstBuffer ** buffer)
|
|
|
|
{
|
|
|
|
GstTypeFindElement *typefind;
|
2005-08-01 09:10:01 +00:00
|
|
|
GstFlowReturn ret;
|
2005-04-12 10:52:55 +00:00
|
|
|
|
2011-11-17 11:40:45 +00:00
|
|
|
typefind = GST_TYPE_FIND_ELEMENT (parent);
|
2005-04-12 10:52:55 +00:00
|
|
|
|
2005-08-01 09:10:01 +00:00
|
|
|
ret = gst_pad_pull_range (typefind->sink, offset, length, buffer);
|
|
|
|
|
|
|
|
return ret;
|
2005-04-12 10:52:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2011-11-21 12:29:05 +00:00
|
|
|
gst_type_find_element_activate_src_mode (GstPad * pad, GstObject * parent,
|
|
|
|
GstPadMode mode, gboolean active)
|
2005-04-12 10:52:55 +00:00
|
|
|
{
|
2011-11-21 12:29:05 +00:00
|
|
|
gboolean res;
|
gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any remaining buffer.
Original commit message from CVS:
2005-06-27 Andy Wingo <wingo@pobox.com>
* gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any
remaining buffer.
* gst/gsttrace.c (gst_alloc_trace_list_sorted): New helper,
returns a sorted copy of the trace list.
(gst_alloc_trace_print_live): New API, only prints traces with
live objects. Sort the list.
(gst_alloc_trace_print_all): Sort the list.
(gst_alloc_trace_print): Align columns.
* gst/elements/gstttypefindelement.c:
* gst/elements/gsttee.c:
* gst/base/gstbasesrc.c:
* gst/base/gstbasesink.c:
* gst/base/gstbasetransform.c:
* gst/gstqueue.c: Adapt for pad activation changes.
* gst/gstpipeline.c (gst_pipeline_init): Unref after parenting
sched.
(gst_pipeline_dispose): Drop ref on sched.
* gst/gstpad.c (gst_pad_init): Set the default activate func.
(gst_pad_activate_default): Push mode by default.
(pre_activate_switch, post_activate_switch): New stubs, things to
do before and after switching activation modes on pads.
(gst_pad_set_active): Take a boolean and not a mode, dispatch to
the pad's activate function to choose which mode to activate.
Shortcut on deactivation and call the right function directly.
(gst_pad_activate_pull): New API, (de)activates a pad in pull
mode.
(gst_pad_activate_push): New API, same for push mode.
(gst_pad_set_activate_function)
(gst_pad_set_activatepull_function)
(gst_pad_set_activatepush_function): Setters for new API.
* gst/gstminiobject.c (gst_mini_object_new, gst_mini_object_free):
Trace all miniobjects.
(gst_mini_object_make_writable): Unref the arg if we copy, like
gst_caps_make_writable.
* gst/gstmessage.c (_gst_message_initialize): No trace init.
* gst/gstghostpad.c (gst_proxy_pad_do_activate)
(gst_proxy_pad_do_activatepull, gst_proxy_pad_do_activatepush):
Adapt for new pad API.
* gst/gstevent.c (_gst_event_initialize): Don't initialize trace.
* gst/gstelement.h:
* gst/gstelement.c (gst_element_iterate_src_pads)
(gst_element_iterate_sink_pads): New API functions.
* gst/gstelement.c (iterator_fold_with_resync): New utility,
should fold into gstiterator.c in some form.
(gst_element_pads_activate): Simplified via use of fold and
delegation of decisions to gstpad->activate.
* gst/gstbus.c (gst_bus_source_finalize): Set the bus to NULL,
help in debugging.
* gst/gstbuffer.c (_gst_buffer_initialize): Ref the buffer type
class once in init, like gstmessage. Didn't run into this issue
but it seems correct. Don't initialize a trace, gstminiobject does
that.
* check/pipelines/simple_launch_lines.c (test_stop_from_app): New
test, runs fakesrc ! fakesink, stopping on ::handoff via a message
to the bus.
(assert_live_count): New util function, uses alloc traces to check
cleanup.
* check/gst/gstghostpad.c (test_ghost_pads): More refcount checks.
To be modified when unlink drops the internal pad.
2005-06-27 18:35:05 +00:00
|
|
|
GstTypeFindElement *typefind;
|
2005-04-12 10:52:55 +00:00
|
|
|
|
2011-11-18 12:46:46 +00:00
|
|
|
typefind = GST_TYPE_FIND_ELEMENT (parent);
|
2005-04-12 10:52:55 +00:00
|
|
|
|
2011-11-21 12:29:05 +00:00
|
|
|
switch (mode) {
|
|
|
|
case GST_PAD_MODE_PULL:
|
2012-02-08 13:32:01 +00:00
|
|
|
/* make sure our task stops pushing, we can't call _stop here because this
|
|
|
|
* activation might happen from the streaming thread. */
|
|
|
|
gst_pad_pause_task (typefind->sink);
|
2011-11-21 12:29:05 +00:00
|
|
|
res = gst_pad_activate_mode (typefind->sink, mode, active);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
res = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return res;
|
2005-04-12 10:52:55 +00:00
|
|
|
}
|
|
|
|
|
2012-01-27 15:18:00 +00:00
|
|
|
static void
|
|
|
|
gst_type_find_element_loop (GstPad * pad)
|
2005-04-12 10:52:55 +00:00
|
|
|
{
|
|
|
|
GstTypeFindElement *typefind;
|
2012-01-27 15:18:00 +00:00
|
|
|
GstFlowReturn ret = GST_FLOW_OK;
|
2005-04-12 10:52:55 +00:00
|
|
|
|
2012-01-27 15:18:00 +00:00
|
|
|
typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
|
2005-04-12 10:52:55 +00:00
|
|
|
|
2013-05-06 22:47:44 +00:00
|
|
|
if (typefind->need_stream_start) {
|
|
|
|
gchar *stream_id;
|
2013-07-22 10:06:29 +00:00
|
|
|
GstEvent *event;
|
2013-05-06 22:47:44 +00:00
|
|
|
|
|
|
|
stream_id = gst_pad_create_stream_id (typefind->src,
|
|
|
|
GST_ELEMENT_CAST (typefind), NULL);
|
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (typefind, "Pushing STREAM_START");
|
2013-07-22 10:06:29 +00:00
|
|
|
event = gst_event_new_stream_start (stream_id);
|
|
|
|
gst_event_set_group_id (event, gst_util_group_id_next ());
|
|
|
|
gst_pad_push_event (typefind->src, event);
|
2013-05-06 22:47:44 +00:00
|
|
|
|
|
|
|
typefind->need_stream_start = FALSE;
|
|
|
|
g_free (stream_id);
|
|
|
|
}
|
|
|
|
|
2012-01-27 15:18:00 +00:00
|
|
|
if (typefind->mode == MODE_TYPEFIND) {
|
2013-05-15 11:22:04 +00:00
|
|
|
GstPad *peer = NULL;
|
2012-01-27 15:18:00 +00:00
|
|
|
GstCaps *found_caps = NULL;
|
|
|
|
GstTypeFindProbability probability = GST_TYPE_FIND_NONE;
|
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (typefind, "find type in pull mode");
|
gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any remaining buffer.
Original commit message from CVS:
2005-06-27 Andy Wingo <wingo@pobox.com>
* gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any
remaining buffer.
* gst/gsttrace.c (gst_alloc_trace_list_sorted): New helper,
returns a sorted copy of the trace list.
(gst_alloc_trace_print_live): New API, only prints traces with
live objects. Sort the list.
(gst_alloc_trace_print_all): Sort the list.
(gst_alloc_trace_print): Align columns.
* gst/elements/gstttypefindelement.c:
* gst/elements/gsttee.c:
* gst/base/gstbasesrc.c:
* gst/base/gstbasesink.c:
* gst/base/gstbasetransform.c:
* gst/gstqueue.c: Adapt for pad activation changes.
* gst/gstpipeline.c (gst_pipeline_init): Unref after parenting
sched.
(gst_pipeline_dispose): Drop ref on sched.
* gst/gstpad.c (gst_pad_init): Set the default activate func.
(gst_pad_activate_default): Push mode by default.
(pre_activate_switch, post_activate_switch): New stubs, things to
do before and after switching activation modes on pads.
(gst_pad_set_active): Take a boolean and not a mode, dispatch to
the pad's activate function to choose which mode to activate.
Shortcut on deactivation and call the right function directly.
(gst_pad_activate_pull): New API, (de)activates a pad in pull
mode.
(gst_pad_activate_push): New API, same for push mode.
(gst_pad_set_activate_function)
(gst_pad_set_activatepull_function)
(gst_pad_set_activatepush_function): Setters for new API.
* gst/gstminiobject.c (gst_mini_object_new, gst_mini_object_free):
Trace all miniobjects.
(gst_mini_object_make_writable): Unref the arg if we copy, like
gst_caps_make_writable.
* gst/gstmessage.c (_gst_message_initialize): No trace init.
* gst/gstghostpad.c (gst_proxy_pad_do_activate)
(gst_proxy_pad_do_activatepull, gst_proxy_pad_do_activatepush):
Adapt for new pad API.
* gst/gstevent.c (_gst_event_initialize): Don't initialize trace.
* gst/gstelement.h:
* gst/gstelement.c (gst_element_iterate_src_pads)
(gst_element_iterate_sink_pads): New API functions.
* gst/gstelement.c (iterator_fold_with_resync): New utility,
should fold into gstiterator.c in some form.
(gst_element_pads_activate): Simplified via use of fold and
delegation of decisions to gstpad->activate.
* gst/gstbus.c (gst_bus_source_finalize): Set the bus to NULL,
help in debugging.
* gst/gstbuffer.c (_gst_buffer_initialize): Ref the buffer type
class once in init, like gstmessage. Didn't run into this issue
but it seems correct. Don't initialize a trace, gstminiobject does
that.
* check/pipelines/simple_launch_lines.c (test_stop_from_app): New
test, runs fakesrc ! fakesink, stopping on ::handoff via a message
to the bus.
(assert_live_count): New util function, uses alloc traces to check
cleanup.
* check/gst/gstghostpad.c (test_ghost_pads): More refcount checks.
To be modified when unlink drops the internal pad.
2005-06-27 18:35:05 +00:00
|
|
|
|
2013-05-15 11:22:04 +00:00
|
|
|
GST_OBJECT_LOCK (typefind);
|
|
|
|
if (typefind->force_caps) {
|
|
|
|
found_caps = gst_caps_ref (typefind->force_caps);
|
|
|
|
probability = GST_TYPE_FIND_MAXIMUM;
|
|
|
|
}
|
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any remaining buffer.
Original commit message from CVS:
2005-06-27 Andy Wingo <wingo@pobox.com>
* gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any
remaining buffer.
* gst/gsttrace.c (gst_alloc_trace_list_sorted): New helper,
returns a sorted copy of the trace list.
(gst_alloc_trace_print_live): New API, only prints traces with
live objects. Sort the list.
(gst_alloc_trace_print_all): Sort the list.
(gst_alloc_trace_print): Align columns.
* gst/elements/gstttypefindelement.c:
* gst/elements/gsttee.c:
* gst/base/gstbasesrc.c:
* gst/base/gstbasesink.c:
* gst/base/gstbasetransform.c:
* gst/gstqueue.c: Adapt for pad activation changes.
* gst/gstpipeline.c (gst_pipeline_init): Unref after parenting
sched.
(gst_pipeline_dispose): Drop ref on sched.
* gst/gstpad.c (gst_pad_init): Set the default activate func.
(gst_pad_activate_default): Push mode by default.
(pre_activate_switch, post_activate_switch): New stubs, things to
do before and after switching activation modes on pads.
(gst_pad_set_active): Take a boolean and not a mode, dispatch to
the pad's activate function to choose which mode to activate.
Shortcut on deactivation and call the right function directly.
(gst_pad_activate_pull): New API, (de)activates a pad in pull
mode.
(gst_pad_activate_push): New API, same for push mode.
(gst_pad_set_activate_function)
(gst_pad_set_activatepull_function)
(gst_pad_set_activatepush_function): Setters for new API.
* gst/gstminiobject.c (gst_mini_object_new, gst_mini_object_free):
Trace all miniobjects.
(gst_mini_object_make_writable): Unref the arg if we copy, like
gst_caps_make_writable.
* gst/gstmessage.c (_gst_message_initialize): No trace init.
* gst/gstghostpad.c (gst_proxy_pad_do_activate)
(gst_proxy_pad_do_activatepull, gst_proxy_pad_do_activatepush):
Adapt for new pad API.
* gst/gstevent.c (_gst_event_initialize): Don't initialize trace.
* gst/gstelement.h:
* gst/gstelement.c (gst_element_iterate_src_pads)
(gst_element_iterate_sink_pads): New API functions.
* gst/gstelement.c (iterator_fold_with_resync): New utility,
should fold into gstiterator.c in some form.
(gst_element_pads_activate): Simplified via use of fold and
delegation of decisions to gstpad->activate.
* gst/gstbus.c (gst_bus_source_finalize): Set the bus to NULL,
help in debugging.
* gst/gstbuffer.c (_gst_buffer_initialize): Ref the buffer type
class once in init, like gstmessage. Didn't run into this issue
but it seems correct. Don't initialize a trace, gstminiobject does
that.
* check/pipelines/simple_launch_lines.c (test_stop_from_app): New
test, runs fakesrc ! fakesink, stopping on ::handoff via a message
to the bus.
(assert_live_count): New util function, uses alloc traces to check
cleanup.
* check/gst/gstghostpad.c (test_ghost_pads): More refcount checks.
To be modified when unlink drops the internal pad.
2005-06-27 18:35:05 +00:00
|
|
|
|
2013-05-15 11:22:04 +00:00
|
|
|
if (!found_caps) {
|
|
|
|
peer = gst_pad_get_peer (pad);
|
|
|
|
if (peer) {
|
|
|
|
gint64 size;
|
|
|
|
gchar *ext;
|
2012-01-27 15:18:00 +00:00
|
|
|
|
2013-05-15 11:22:04 +00:00
|
|
|
if (!gst_pad_query_duration (peer, GST_FORMAT_BYTES, &size)) {
|
|
|
|
GST_WARNING_OBJECT (typefind, "Could not query upstream length!");
|
|
|
|
gst_object_unref (peer);
|
2006-03-03 11:27:02 +00:00
|
|
|
|
2013-05-15 11:22:04 +00:00
|
|
|
ret = GST_FLOW_ERROR;
|
|
|
|
goto pause;
|
|
|
|
}
|
2006-03-03 11:27:02 +00:00
|
|
|
|
2013-05-15 11:22:04 +00:00
|
|
|
/* the size if 0, we cannot continue */
|
|
|
|
if (size == 0) {
|
|
|
|
/* keep message in sync with message in sink event handler */
|
|
|
|
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
|
|
|
|
(_("Stream contains no data.")), ("Can't typefind empty stream"));
|
|
|
|
gst_object_unref (peer);
|
|
|
|
ret = GST_FLOW_ERROR;
|
|
|
|
goto pause;
|
|
|
|
}
|
|
|
|
ext = gst_type_find_get_extension (typefind, pad);
|
2008-04-02 17:21:40 +00:00
|
|
|
|
2013-05-15 11:22:04 +00:00
|
|
|
found_caps =
|
|
|
|
gst_type_find_helper_get_range (GST_OBJECT_CAST (peer),
|
|
|
|
GST_OBJECT_PARENT (peer),
|
|
|
|
(GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)),
|
|
|
|
(guint64) size, ext, &probability);
|
|
|
|
g_free (ext);
|
2011-11-09 16:25:30 +00:00
|
|
|
|
2013-05-15 11:22:04 +00:00
|
|
|
GST_DEBUG ("Found caps %" GST_PTR_FORMAT, found_caps);
|
|
|
|
|
|
|
|
gst_object_unref (peer);
|
|
|
|
}
|
gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any remaining buffer.
Original commit message from CVS:
2005-06-27 Andy Wingo <wingo@pobox.com>
* gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any
remaining buffer.
* gst/gsttrace.c (gst_alloc_trace_list_sorted): New helper,
returns a sorted copy of the trace list.
(gst_alloc_trace_print_live): New API, only prints traces with
live objects. Sort the list.
(gst_alloc_trace_print_all): Sort the list.
(gst_alloc_trace_print): Align columns.
* gst/elements/gstttypefindelement.c:
* gst/elements/gsttee.c:
* gst/base/gstbasesrc.c:
* gst/base/gstbasesink.c:
* gst/base/gstbasetransform.c:
* gst/gstqueue.c: Adapt for pad activation changes.
* gst/gstpipeline.c (gst_pipeline_init): Unref after parenting
sched.
(gst_pipeline_dispose): Drop ref on sched.
* gst/gstpad.c (gst_pad_init): Set the default activate func.
(gst_pad_activate_default): Push mode by default.
(pre_activate_switch, post_activate_switch): New stubs, things to
do before and after switching activation modes on pads.
(gst_pad_set_active): Take a boolean and not a mode, dispatch to
the pad's activate function to choose which mode to activate.
Shortcut on deactivation and call the right function directly.
(gst_pad_activate_pull): New API, (de)activates a pad in pull
mode.
(gst_pad_activate_push): New API, same for push mode.
(gst_pad_set_activate_function)
(gst_pad_set_activatepull_function)
(gst_pad_set_activatepush_function): Setters for new API.
* gst/gstminiobject.c (gst_mini_object_new, gst_mini_object_free):
Trace all miniobjects.
(gst_mini_object_make_writable): Unref the arg if we copy, like
gst_caps_make_writable.
* gst/gstmessage.c (_gst_message_initialize): No trace init.
* gst/gstghostpad.c (gst_proxy_pad_do_activate)
(gst_proxy_pad_do_activatepull, gst_proxy_pad_do_activatepush):
Adapt for new pad API.
* gst/gstevent.c (_gst_event_initialize): Don't initialize trace.
* gst/gstelement.h:
* gst/gstelement.c (gst_element_iterate_src_pads)
(gst_element_iterate_sink_pads): New API functions.
* gst/gstelement.c (iterator_fold_with_resync): New utility,
should fold into gstiterator.c in some form.
(gst_element_pads_activate): Simplified via use of fold and
delegation of decisions to gstpad->activate.
* gst/gstbus.c (gst_bus_source_finalize): Set the bus to NULL,
help in debugging.
* gst/gstbuffer.c (_gst_buffer_initialize): Ref the buffer type
class once in init, like gstmessage. Didn't run into this issue
but it seems correct. Don't initialize a trace, gstminiobject does
that.
* check/pipelines/simple_launch_lines.c (test_stop_from_app): New
test, runs fakesrc ! fakesink, stopping on ::handoff via a message
to the bus.
(assert_live_count): New util function, uses alloc traces to check
cleanup.
* check/gst/gstghostpad.c (test_ghost_pads): More refcount checks.
To be modified when unlink drops the internal pad.
2005-06-27 18:35:05 +00:00
|
|
|
}
|
|
|
|
|
2012-01-27 15:18:00 +00:00
|
|
|
if (!found_caps || probability < typefind->min_probability) {
|
|
|
|
GST_DEBUG ("Trying to guess using extension");
|
2012-03-30 14:53:09 +00:00
|
|
|
gst_caps_replace (&found_caps, NULL);
|
2012-01-27 15:18:00 +00:00
|
|
|
found_caps =
|
|
|
|
gst_type_find_guess_by_extension (typefind, pad, &probability);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found_caps || probability < typefind->min_probability) {
|
|
|
|
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
|
|
|
|
gst_caps_replace (&found_caps, NULL);
|
|
|
|
ret = GST_FLOW_ERROR;
|
|
|
|
goto pause;
|
|
|
|
}
|
|
|
|
|
|
|
|
GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps);
|
|
|
|
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
|
|
|
0, probability, found_caps);
|
|
|
|
typefind->mode = MODE_NORMAL;
|
2012-03-30 14:53:09 +00:00
|
|
|
gst_caps_unref (found_caps);
|
2012-01-27 15:18:00 +00:00
|
|
|
} else if (typefind->mode == MODE_NORMAL) {
|
2012-03-16 20:37:10 +00:00
|
|
|
GstBuffer *outbuf = NULL;
|
2012-01-27 15:18:00 +00:00
|
|
|
|
|
|
|
if (typefind->need_segment) {
|
|
|
|
typefind->need_segment = FALSE;
|
|
|
|
gst_pad_push_event (typefind->src,
|
|
|
|
gst_event_new_segment (&typefind->segment));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Pull 4k blocks and send downstream */
|
|
|
|
ret = gst_pad_pull_range (typefind->sink, typefind->offset, 4096, &outbuf);
|
|
|
|
if (ret != GST_FLOW_OK)
|
|
|
|
goto pause;
|
|
|
|
|
2013-07-29 09:05:09 +00:00
|
|
|
typefind->offset += gst_buffer_get_size (outbuf);
|
2012-01-27 15:18:00 +00:00
|
|
|
|
|
|
|
ret = gst_pad_push (typefind->src, outbuf);
|
|
|
|
if (ret != GST_FLOW_OK)
|
|
|
|
goto pause;
|
|
|
|
} else {
|
|
|
|
/* Error out */
|
|
|
|
ret = GST_FLOW_ERROR;
|
|
|
|
goto pause;
|
2010-01-28 14:57:33 +00:00
|
|
|
}
|
|
|
|
|
2012-01-27 15:18:00 +00:00
|
|
|
return;
|
gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any remaining buffer.
Original commit message from CVS:
2005-06-27 Andy Wingo <wingo@pobox.com>
* gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any
remaining buffer.
* gst/gsttrace.c (gst_alloc_trace_list_sorted): New helper,
returns a sorted copy of the trace list.
(gst_alloc_trace_print_live): New API, only prints traces with
live objects. Sort the list.
(gst_alloc_trace_print_all): Sort the list.
(gst_alloc_trace_print): Align columns.
* gst/elements/gstttypefindelement.c:
* gst/elements/gsttee.c:
* gst/base/gstbasesrc.c:
* gst/base/gstbasesink.c:
* gst/base/gstbasetransform.c:
* gst/gstqueue.c: Adapt for pad activation changes.
* gst/gstpipeline.c (gst_pipeline_init): Unref after parenting
sched.
(gst_pipeline_dispose): Drop ref on sched.
* gst/gstpad.c (gst_pad_init): Set the default activate func.
(gst_pad_activate_default): Push mode by default.
(pre_activate_switch, post_activate_switch): New stubs, things to
do before and after switching activation modes on pads.
(gst_pad_set_active): Take a boolean and not a mode, dispatch to
the pad's activate function to choose which mode to activate.
Shortcut on deactivation and call the right function directly.
(gst_pad_activate_pull): New API, (de)activates a pad in pull
mode.
(gst_pad_activate_push): New API, same for push mode.
(gst_pad_set_activate_function)
(gst_pad_set_activatepull_function)
(gst_pad_set_activatepush_function): Setters for new API.
* gst/gstminiobject.c (gst_mini_object_new, gst_mini_object_free):
Trace all miniobjects.
(gst_mini_object_make_writable): Unref the arg if we copy, like
gst_caps_make_writable.
* gst/gstmessage.c (_gst_message_initialize): No trace init.
* gst/gstghostpad.c (gst_proxy_pad_do_activate)
(gst_proxy_pad_do_activatepull, gst_proxy_pad_do_activatepush):
Adapt for new pad API.
* gst/gstevent.c (_gst_event_initialize): Don't initialize trace.
* gst/gstelement.h:
* gst/gstelement.c (gst_element_iterate_src_pads)
(gst_element_iterate_sink_pads): New API functions.
* gst/gstelement.c (iterator_fold_with_resync): New utility,
should fold into gstiterator.c in some form.
(gst_element_pads_activate): Simplified via use of fold and
delegation of decisions to gstpad->activate.
* gst/gstbus.c (gst_bus_source_finalize): Set the bus to NULL,
help in debugging.
* gst/gstbuffer.c (_gst_buffer_initialize): Ref the buffer type
class once in init, like gstmessage. Didn't run into this issue
but it seems correct. Don't initialize a trace, gstminiobject does
that.
* check/pipelines/simple_launch_lines.c (test_stop_from_app): New
test, runs fakesrc ! fakesink, stopping on ::handoff via a message
to the bus.
(assert_live_count): New util function, uses alloc traces to check
cleanup.
* check/gst/gstghostpad.c (test_ghost_pads): More refcount checks.
To be modified when unlink drops the internal pad.
2005-06-27 18:35:05 +00:00
|
|
|
|
2012-01-27 15:18:00 +00:00
|
|
|
pause:
|
|
|
|
{
|
|
|
|
const gchar *reason = gst_flow_get_name (ret);
|
|
|
|
gboolean push_eos = FALSE;
|
|
|
|
|
|
|
|
GST_LOG_OBJECT (typefind, "pausing task, reason %s", reason);
|
|
|
|
gst_pad_pause_task (typefind->sink);
|
|
|
|
|
|
|
|
if (ret == GST_FLOW_EOS) {
|
|
|
|
/* perform EOS logic */
|
|
|
|
|
2012-07-09 20:51:07 +00:00
|
|
|
if (typefind->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
|
2012-01-27 15:18:00 +00:00
|
|
|
gint64 stop;
|
gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any remaining buffer.
Original commit message from CVS:
2005-06-27 Andy Wingo <wingo@pobox.com>
* gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any
remaining buffer.
* gst/gsttrace.c (gst_alloc_trace_list_sorted): New helper,
returns a sorted copy of the trace list.
(gst_alloc_trace_print_live): New API, only prints traces with
live objects. Sort the list.
(gst_alloc_trace_print_all): Sort the list.
(gst_alloc_trace_print): Align columns.
* gst/elements/gstttypefindelement.c:
* gst/elements/gsttee.c:
* gst/base/gstbasesrc.c:
* gst/base/gstbasesink.c:
* gst/base/gstbasetransform.c:
* gst/gstqueue.c: Adapt for pad activation changes.
* gst/gstpipeline.c (gst_pipeline_init): Unref after parenting
sched.
(gst_pipeline_dispose): Drop ref on sched.
* gst/gstpad.c (gst_pad_init): Set the default activate func.
(gst_pad_activate_default): Push mode by default.
(pre_activate_switch, post_activate_switch): New stubs, things to
do before and after switching activation modes on pads.
(gst_pad_set_active): Take a boolean and not a mode, dispatch to
the pad's activate function to choose which mode to activate.
Shortcut on deactivation and call the right function directly.
(gst_pad_activate_pull): New API, (de)activates a pad in pull
mode.
(gst_pad_activate_push): New API, same for push mode.
(gst_pad_set_activate_function)
(gst_pad_set_activatepull_function)
(gst_pad_set_activatepush_function): Setters for new API.
* gst/gstminiobject.c (gst_mini_object_new, gst_mini_object_free):
Trace all miniobjects.
(gst_mini_object_make_writable): Unref the arg if we copy, like
gst_caps_make_writable.
* gst/gstmessage.c (_gst_message_initialize): No trace init.
* gst/gstghostpad.c (gst_proxy_pad_do_activate)
(gst_proxy_pad_do_activatepull, gst_proxy_pad_do_activatepush):
Adapt for new pad API.
* gst/gstevent.c (_gst_event_initialize): Don't initialize trace.
* gst/gstelement.h:
* gst/gstelement.c (gst_element_iterate_src_pads)
(gst_element_iterate_sink_pads): New API functions.
* gst/gstelement.c (iterator_fold_with_resync): New utility,
should fold into gstiterator.c in some form.
(gst_element_pads_activate): Simplified via use of fold and
delegation of decisions to gstpad->activate.
* gst/gstbus.c (gst_bus_source_finalize): Set the bus to NULL,
help in debugging.
* gst/gstbuffer.c (_gst_buffer_initialize): Ref the buffer type
class once in init, like gstmessage. Didn't run into this issue
but it seems correct. Don't initialize a trace, gstminiobject does
that.
* check/pipelines/simple_launch_lines.c (test_stop_from_app): New
test, runs fakesrc ! fakesink, stopping on ::handoff via a message
to the bus.
(assert_live_count): New util function, uses alloc traces to check
cleanup.
* check/gst/gstghostpad.c (test_ghost_pads): More refcount checks.
To be modified when unlink drops the internal pad.
2005-06-27 18:35:05 +00:00
|
|
|
|
2012-01-27 15:18:00 +00:00
|
|
|
/* for segment playback we need to post when (in stream time)
|
|
|
|
* we stopped, this is either stop (when set) or the duration. */
|
|
|
|
if ((stop = typefind->segment.stop) == -1)
|
|
|
|
stop = typefind->offset;
|
|
|
|
|
|
|
|
GST_LOG_OBJECT (typefind, "Sending segment done, at end of segment");
|
|
|
|
gst_element_post_message (GST_ELEMENT (typefind),
|
|
|
|
gst_message_new_segment_done (GST_OBJECT (typefind),
|
|
|
|
GST_FORMAT_BYTES, stop));
|
2012-08-01 10:58:55 +00:00
|
|
|
gst_pad_push_event (typefind->src,
|
|
|
|
gst_event_new_segment_done (GST_FORMAT_BYTES, stop));
|
2012-01-27 15:18:00 +00:00
|
|
|
} else {
|
|
|
|
push_eos = TRUE;
|
|
|
|
}
|
|
|
|
} else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
|
|
|
|
/* for fatal errors we post an error message */
|
|
|
|
GST_ELEMENT_ERROR (typefind, STREAM, FAILED, (NULL),
|
|
|
|
("stream stopped, reason %s", reason));
|
|
|
|
push_eos = TRUE;
|
|
|
|
}
|
|
|
|
if (push_eos) {
|
|
|
|
/* send EOS, and prevent hanging if no streams yet */
|
|
|
|
GST_LOG_OBJECT (typefind, "Sending EOS, at end of stream");
|
|
|
|
gst_pad_push_event (typefind->src, gst_event_new_eos ());
|
|
|
|
}
|
|
|
|
return;
|
2009-01-21 11:50:29 +00:00
|
|
|
}
|
2012-01-27 15:18:00 +00:00
|
|
|
}
|
2009-01-21 11:50:29 +00:00
|
|
|
|
2012-01-27 15:18:00 +00:00
|
|
|
static gboolean
|
|
|
|
gst_type_find_element_activate_sink_mode (GstPad * pad, GstObject * parent,
|
|
|
|
GstPadMode mode, gboolean active)
|
|
|
|
{
|
2012-02-14 11:57:14 +00:00
|
|
|
gboolean res;
|
2012-01-27 15:18:00 +00:00
|
|
|
GstTypeFindElement *typefind;
|
|
|
|
|
|
|
|
typefind = GST_TYPE_FIND_ELEMENT (parent);
|
|
|
|
|
|
|
|
switch (mode) {
|
|
|
|
case GST_PAD_MODE_PULL:
|
|
|
|
if (active) {
|
|
|
|
gst_segment_init (&typefind->segment, GST_FORMAT_BYTES);
|
|
|
|
typefind->need_segment = TRUE;
|
2012-09-26 11:19:13 +00:00
|
|
|
typefind->need_stream_start = TRUE;
|
2012-01-27 15:18:00 +00:00
|
|
|
typefind->offset = 0;
|
2012-02-14 11:57:14 +00:00
|
|
|
res = TRUE;
|
2012-01-27 15:18:00 +00:00
|
|
|
} else {
|
2012-02-14 11:57:14 +00:00
|
|
|
res = gst_pad_stop_task (pad);
|
2015-06-14 19:48:29 +00:00
|
|
|
gst_segment_init (&typefind->segment, GST_FORMAT_UNDEFINED);
|
2012-01-27 15:18:00 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GST_PAD_MODE_PUSH:
|
2015-06-14 19:48:29 +00:00
|
|
|
if (active) {
|
|
|
|
gst_segment_init (&typefind->segment, GST_FORMAT_UNDEFINED);
|
2012-01-27 15:18:00 +00:00
|
|
|
start_typefinding (typefind);
|
2015-06-14 19:48:29 +00:00
|
|
|
} else {
|
2012-01-27 15:18:00 +00:00
|
|
|
stop_typefinding (typefind);
|
2015-06-14 19:48:29 +00:00
|
|
|
gst_segment_init (&typefind->segment, GST_FORMAT_UNDEFINED);
|
|
|
|
}
|
2012-02-14 11:57:14 +00:00
|
|
|
res = TRUE;
|
2012-01-27 15:18:00 +00:00
|
|
|
break;
|
|
|
|
default:
|
2012-02-14 11:57:14 +00:00
|
|
|
res = FALSE;
|
|
|
|
break;
|
2006-02-03 21:14:57 +00:00
|
|
|
}
|
2012-02-14 11:57:14 +00:00
|
|
|
return res;
|
2012-01-27 15:18:00 +00:00
|
|
|
}
|
gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any remaining buffer.
Original commit message from CVS:
2005-06-27 Andy Wingo <wingo@pobox.com>
* gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any
remaining buffer.
* gst/gsttrace.c (gst_alloc_trace_list_sorted): New helper,
returns a sorted copy of the trace list.
(gst_alloc_trace_print_live): New API, only prints traces with
live objects. Sort the list.
(gst_alloc_trace_print_all): Sort the list.
(gst_alloc_trace_print): Align columns.
* gst/elements/gstttypefindelement.c:
* gst/elements/gsttee.c:
* gst/base/gstbasesrc.c:
* gst/base/gstbasesink.c:
* gst/base/gstbasetransform.c:
* gst/gstqueue.c: Adapt for pad activation changes.
* gst/gstpipeline.c (gst_pipeline_init): Unref after parenting
sched.
(gst_pipeline_dispose): Drop ref on sched.
* gst/gstpad.c (gst_pad_init): Set the default activate func.
(gst_pad_activate_default): Push mode by default.
(pre_activate_switch, post_activate_switch): New stubs, things to
do before and after switching activation modes on pads.
(gst_pad_set_active): Take a boolean and not a mode, dispatch to
the pad's activate function to choose which mode to activate.
Shortcut on deactivation and call the right function directly.
(gst_pad_activate_pull): New API, (de)activates a pad in pull
mode.
(gst_pad_activate_push): New API, same for push mode.
(gst_pad_set_activate_function)
(gst_pad_set_activatepull_function)
(gst_pad_set_activatepush_function): Setters for new API.
* gst/gstminiobject.c (gst_mini_object_new, gst_mini_object_free):
Trace all miniobjects.
(gst_mini_object_make_writable): Unref the arg if we copy, like
gst_caps_make_writable.
* gst/gstmessage.c (_gst_message_initialize): No trace init.
* gst/gstghostpad.c (gst_proxy_pad_do_activate)
(gst_proxy_pad_do_activatepull, gst_proxy_pad_do_activatepush):
Adapt for new pad API.
* gst/gstevent.c (_gst_event_initialize): Don't initialize trace.
* gst/gstelement.h:
* gst/gstelement.c (gst_element_iterate_src_pads)
(gst_element_iterate_sink_pads): New API functions.
* gst/gstelement.c (iterator_fold_with_resync): New utility,
should fold into gstiterator.c in some form.
(gst_element_pads_activate): Simplified via use of fold and
delegation of decisions to gstpad->activate.
* gst/gstbus.c (gst_bus_source_finalize): Set the bus to NULL,
help in debugging.
* gst/gstbuffer.c (_gst_buffer_initialize): Ref the buffer type
class once in init, like gstmessage. Didn't run into this issue
but it seems correct. Don't initialize a trace, gstminiobject does
that.
* check/pipelines/simple_launch_lines.c (test_stop_from_app): New
test, runs fakesrc ! fakesink, stopping on ::handoff via a message
to the bus.
(assert_live_count): New util function, uses alloc traces to check
cleanup.
* check/gst/gstghostpad.c (test_ghost_pads): More refcount checks.
To be modified when unlink drops the internal pad.
2005-06-27 18:35:05 +00:00
|
|
|
|
2012-01-27 15:18:00 +00:00
|
|
|
static gboolean
|
|
|
|
gst_type_find_element_activate_sink (GstPad * pad, GstObject * parent)
|
|
|
|
{
|
|
|
|
GstQuery *query;
|
|
|
|
gboolean pull_mode;
|
2012-09-10 20:39:32 +00:00
|
|
|
GstSchedulingFlags sched_flags;
|
2011-11-09 16:25:30 +00:00
|
|
|
|
2012-01-27 15:18:00 +00:00
|
|
|
query = gst_query_new_scheduling ();
|
|
|
|
|
|
|
|
if (!gst_pad_peer_query (pad, query)) {
|
|
|
|
gst_query_unref (query);
|
|
|
|
goto typefind_push;
|
|
|
|
}
|
|
|
|
|
2012-09-10 20:39:32 +00:00
|
|
|
gst_query_parse_scheduling (query, &sched_flags, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL)
|
|
|
|
&& ((sched_flags & GST_SCHEDULING_FLAG_SEEKABLE) != 0);
|
|
|
|
|
2012-01-27 15:18:00 +00:00
|
|
|
gst_query_unref (query);
|
|
|
|
|
|
|
|
if (!pull_mode)
|
|
|
|
goto typefind_push;
|
|
|
|
|
|
|
|
if (!gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE))
|
|
|
|
goto typefind_push;
|
|
|
|
|
2012-02-08 13:32:01 +00:00
|
|
|
/* only start our task if we ourselves decide to start in pull mode */
|
2012-02-15 09:10:53 +00:00
|
|
|
return gst_pad_start_task (pad, (GstTaskFunction) gst_type_find_element_loop,
|
2012-06-20 08:31:49 +00:00
|
|
|
pad, NULL);
|
2012-01-27 15:18:00 +00:00
|
|
|
|
2011-05-24 15:36:24 +00:00
|
|
|
typefind_push:
|
|
|
|
{
|
2011-11-21 12:29:05 +00:00
|
|
|
return gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE);
|
2011-05-24 15:36:24 +00:00
|
|
|
}
|
2005-04-12 10:52:55 +00:00
|
|
|
}
|
|
|
|
|
2005-09-02 15:42:00 +00:00
|
|
|
static GstStateChangeReturn
|
|
|
|
gst_type_find_element_change_state (GstElement * element,
|
|
|
|
GstStateChange transition)
|
2003-10-28 20:25:30 +00:00
|
|
|
{
|
2005-09-02 15:42:00 +00:00
|
|
|
GstStateChangeReturn ret;
|
2003-10-28 20:25:30 +00:00
|
|
|
GstTypeFindElement *typefind;
|
|
|
|
|
|
|
|
typefind = GST_TYPE_FIND_ELEMENT (element);
|
|
|
|
|
2005-04-12 10:52:55 +00:00
|
|
|
|
2005-09-02 15:42:00 +00:00
|
|
|
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
2005-04-12 10:52:55 +00:00
|
|
|
|
|
|
|
switch (transition) {
|
2005-09-02 15:42:00 +00:00
|
|
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
2007-01-30 19:12:54 +00:00
|
|
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_LOCK (typefind);
|
2004-01-11 18:23:48 +00:00
|
|
|
gst_caps_replace (&typefind->caps, NULL);
|
2008-05-13 11:45:24 +00:00
|
|
|
|
2006-03-29 10:33:19 +00:00
|
|
|
g_list_foreach (typefind->cached_events,
|
|
|
|
(GFunc) gst_mini_object_unref, NULL);
|
|
|
|
g_list_free (typefind->cached_events);
|
|
|
|
typefind->cached_events = NULL;
|
2010-02-13 14:18:05 +00:00
|
|
|
typefind->mode = MODE_TYPEFIND;
|
2010-02-04 20:11:25 +00:00
|
|
|
GST_OBJECT_UNLOCK (typefind);
|
2003-10-28 20:25:30 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2005-04-12 10:52:55 +00:00
|
|
|
return ret;
|
2003-10-28 20:25:30 +00:00
|
|
|
}
|