LCOV - code coverage report
Current view: top level - plugins/elements - gsttypefindelement.c (source / functions) Hit Total Coverage
Test: GStreamer 0.10.32.1 Lines: 102 427 23.9 %
Date: 2011-03-25 Functions: 9 25 36.0 %
Branches: 11 249 4.4 %

           Branch data     Line data    Source code
       1                 :            : /* GStreamer
       2                 :            :  * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
       3                 :            :  *
       4                 :            :  * gsttypefindelement.c: element that detects type of stream
       5                 :            :  *
       6                 :            :  * This library is free software; you can redistribute it and/or
       7                 :            :  * modify it under the terms of the GNU Library General Public
       8                 :            :  * License as published by the Free Software Foundation; either
       9                 :            :  * version 2 of the License, or (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This library is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14                 :            :  * Library General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU Library General Public
      17                 :            :  * License along with this library; if not, write to the
      18                 :            :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      19                 :            :  * Boston, MA 02111-1307, USA.
      20                 :            :  */
      21                 :            : /**
      22                 :            :  * SECTION:element-typefind
      23                 :            :  *
      24                 :            :  * Determines the media-type of a stream. It applies typefind functions in the
      25                 :            :  * order of their rank. One the type has been deteted it sets its src pad caps
      26                 :            :  * to the found media type.
      27                 :            :  *
      28                 :            :  * Whenever a type is found the #GstTypeFindElement::have-type signal is
      29                 :            :  * emitted, either from the streaming thread or the application thread
      30                 :            :  * (the latter may happen when typefinding is done pull-based from the
      31                 :            :  * state change function).
      32                 :            :  *
      33                 :            :  * Plugins can register custom typefinders by using #GstTypeFindFactory.
      34                 :            :  */
      35                 :            : 
      36                 :            : /* FIXME: need a better solution for non-seekable streams */
      37                 :            : 
      38                 :            : /* way of operation:
      39                 :            :  * 1) get a list of all typefind functions sorted best to worst
      40                 :            :  * 2) if all elements have been called with all requested data goto 8
      41                 :            :  * 3) call all functions once with all available data
      42                 :            :  * 4) if a function returns a value >= PROP_MAXIMUM goto 8
      43                 :            :  * 5) all functions with a result > PROP_MINIMUM or functions that did not get
      44                 :            :  *    all requested data (where peek returned NULL) stay in list
      45                 :            :  * 6) seek to requested offset of best function that still has open data
      46                 :            :  *    requests
      47                 :            :  * 7) goto 2
      48                 :            :  * 8) take best available result and use its caps
      49                 :            :  *
      50                 :            :  * The element has two scheduling modes:
      51                 :            :  *
      52                 :            :  * 1) chain based, it will collect buffers and run the typefind function on
      53                 :            :  *    the buffer until something is found.
      54                 :            :  * 2) getrange based, it will proxy the getrange function to the sinkpad. It
      55                 :            :  *    is assumed that the peer element is happy with whatever format we
      56                 :            :  *    eventually read.
      57                 :            :  *
      58                 :            :  * By default it tries to do pull based typefinding (this avoids joining
      59                 :            :  * received buffers and holding them back in store.)
      60                 :            :  *
      61                 :            :  * When the element has no connected srcpad, and the sinkpad can operate in
      62                 :            :  * getrange based mode, the element starts its own task to figure out the
      63                 :            :  * type of the stream.
      64                 :            :  *
      65                 :            :  * Most of the actual implementation is in libs/gst/base/gsttypefindhelper.c.
      66                 :            :  */
      67                 :            : 
      68                 :            : #ifdef HAVE_CONFIG_H
      69                 :            : #  include "config.h"
      70                 :            : #endif
      71                 :            : 
      72                 :            : #include "gst/gst_private.h"
      73                 :            : 
      74                 :            : #include "gsttypefindelement.h"
      75                 :            : #include "gst/gst-i18n-lib.h"
      76                 :            : #include "gst/base/gsttypefindhelper.h"
      77                 :            : 
      78                 :            : #include <gst/gsttypefind.h>
      79                 :            : #include <gst/gstutils.h>
      80                 :            : #include <gst/gsterror.h>
      81                 :            : 
      82                 :            : GST_DEBUG_CATEGORY_STATIC (gst_type_find_element_debug);
      83                 :            : #define GST_CAT_DEFAULT gst_type_find_element_debug
      84                 :            : 
      85                 :            : /* generic templates */
      86                 :            : static GstStaticPadTemplate type_find_element_sink_template =
      87                 :            : GST_STATIC_PAD_TEMPLATE ("sink",
      88                 :            :     GST_PAD_SINK,
      89                 :            :     GST_PAD_ALWAYS,
      90                 :            :     GST_STATIC_CAPS_ANY);
      91                 :            : 
      92                 :            : static GstStaticPadTemplate type_find_element_src_template =
      93                 :            : GST_STATIC_PAD_TEMPLATE ("src",
      94                 :            :     GST_PAD_SRC,
      95                 :            :     GST_PAD_ALWAYS,
      96                 :            :     GST_STATIC_CAPS_ANY);
      97                 :            : 
      98                 :            : /* Require at least 2kB of data before we attempt typefinding in chain-mode.
      99                 :            :  * 128kB is massive overkill for the maximum, but doesn't do any harm */
     100                 :            : #define TYPE_FIND_MIN_SIZE   (2*1024)
     101                 :            : #define TYPE_FIND_MAX_SIZE (128*1024)
     102                 :            : 
     103                 :            : /* TypeFind signals and args */
     104                 :            : enum
     105                 :            : {
     106                 :            :   HAVE_TYPE,
     107                 :            :   LAST_SIGNAL
     108                 :            : };
     109                 :            : enum
     110                 :            : {
     111                 :            :   PROP_0,
     112                 :            :   PROP_CAPS,
     113                 :            :   PROP_MINIMUM,
     114                 :            :   PROP_MAXIMUM,
     115                 :            :   PROP_FORCE_CAPS,
     116                 :            :   PROP_LAST
     117                 :            : };
     118                 :            : enum
     119                 :            : {
     120                 :            :   MODE_NORMAL,                  /* act as identity */
     121                 :            :   MODE_TYPEFIND,                /* do typefinding  */
     122                 :            :   MODE_ERROR                    /* had fatal error */
     123                 :            : };
     124                 :            : 
     125                 :            : 
     126                 :            : #define _do_init(bla) \
     127                 :            :     GST_DEBUG_CATEGORY_INIT (gst_type_find_element_debug, "typefind",           \
     128                 :            :         GST_DEBUG_BG_YELLOW | GST_DEBUG_FG_GREEN, "type finding element");
     129                 :            : 
     130 [ +  + ][ +  - ]:        205 : GST_BOILERPLATE_FULL (GstTypeFindElement, gst_type_find_element, GstElement,
     131                 :        205 :     GST_TYPE_ELEMENT, _do_init);
     132                 :            : 
     133                 :            : static void gst_type_find_element_dispose (GObject * object);
     134                 :            : static void gst_type_find_element_set_property (GObject * object,
     135                 :            :     guint prop_id, const GValue * value, GParamSpec * pspec);
     136                 :            : static void gst_type_find_element_get_property (GObject * object,
     137                 :            :     guint prop_id, GValue * value, GParamSpec * pspec);
     138                 :            : 
     139                 :            : #if 0
     140                 :            : static const GstEventMask *gst_type_find_element_src_event_mask (GstPad * pad);
     141                 :            : #endif
     142                 :            : 
     143                 :            : static gboolean gst_type_find_element_src_event (GstPad * pad,
     144                 :            :     GstEvent * event);
     145                 :            : static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQuery * query);
     146                 :            : 
     147                 :            : static gboolean gst_type_find_element_handle_event (GstPad * pad,
     148                 :            :     GstEvent * event);
     149                 :            : static gboolean gst_type_find_element_setcaps (GstPad * pad, GstCaps * caps);
     150                 :            : static GstFlowReturn gst_type_find_element_chain (GstPad * sinkpad,
     151                 :            :     GstBuffer * buffer);
     152                 :            : static GstFlowReturn gst_type_find_element_getrange (GstPad * srcpad,
     153                 :            :     guint64 offset, guint length, GstBuffer ** buffer);
     154                 :            : static gboolean gst_type_find_element_checkgetrange (GstPad * srcpad);
     155                 :            : 
     156                 :            : static GstStateChangeReturn
     157                 :            : gst_type_find_element_change_state (GstElement * element,
     158                 :            :     GstStateChange transition);
     159                 :            : static gboolean gst_type_find_element_activate (GstPad * pad);
     160                 :            : static gboolean
     161                 :            : gst_type_find_element_activate_src_pull (GstPad * pad, gboolean active);
     162                 :            : static GstFlowReturn
     163                 :            : gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind);
     164                 :            : static void
     165                 :            : gst_type_find_element_send_cached_events (GstTypeFindElement * typefind);
     166                 :            : 
     167                 :            : static guint gst_type_find_element_signals[LAST_SIGNAL] = { 0 };
     168                 :            : 
     169                 :            : static void
     170                 :          0 : gst_type_find_element_have_type (GstTypeFindElement * typefind,
     171                 :            :     guint probability, const GstCaps * caps)
     172                 :            : {
     173                 :            :   GstCaps *copy;
     174                 :            : 
     175         [ #  # ]:          0 :   g_assert (caps != NULL);
     176                 :            : 
     177         [ #  # ]:          0 :   GST_INFO_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", probability=%u",
     178                 :            :       caps, probability);
     179                 :            : 
     180                 :          0 :   GST_OBJECT_LOCK (typefind);
     181         [ #  # ]:          0 :   if (typefind->caps)
     182                 :          0 :     gst_caps_unref (typefind->caps);
     183                 :          0 :   typefind->caps = gst_caps_copy (caps);
     184                 :          0 :   copy = gst_caps_ref (typefind->caps);
     185                 :          0 :   GST_OBJECT_UNLOCK (typefind);
     186                 :            : 
     187                 :          0 :   gst_pad_set_caps (typefind->src, copy);
     188                 :          0 :   gst_caps_unref (copy);
     189                 :          0 : }
     190                 :            : 
     191                 :            : static void
     192                 :          8 : gst_type_find_element_base_init (gpointer g_class)
     193                 :            : {
     194                 :          8 :   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
     195                 :            : 
     196                 :          8 :   gst_element_class_set_details_simple (gstelement_class,
     197                 :            :       "TypeFind",
     198                 :            :       "Generic",
     199                 :            :       "Finds the media type of a stream",
     200                 :            :       "Benjamin Otte <in7y118@public.uni-hamburg.de>");
     201                 :          8 :   gst_element_class_add_pad_template (gstelement_class,
     202                 :            :       gst_static_pad_template_get (&type_find_element_src_template));
     203                 :          8 :   gst_element_class_add_pad_template (gstelement_class,
     204                 :            :       gst_static_pad_template_get (&type_find_element_sink_template));
     205                 :          8 : }
     206                 :            : 
     207                 :            : static void
     208                 :          8 : gst_type_find_element_class_init (GstTypeFindElementClass * typefind_class)
     209                 :            : {
     210                 :          8 :   GObjectClass *gobject_class = G_OBJECT_CLASS (typefind_class);
     211                 :          8 :   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (typefind_class);
     212                 :            : 
     213                 :          8 :   gobject_class->set_property = gst_type_find_element_set_property;
     214                 :          8 :   gobject_class->get_property = gst_type_find_element_get_property;
     215                 :          8 :   gobject_class->dispose = gst_type_find_element_dispose;
     216                 :            : 
     217                 :          8 :   g_object_class_install_property (gobject_class, PROP_CAPS,
     218                 :          8 :       g_param_spec_boxed ("caps", _("caps"),
     219                 :          8 :           _("detected capabilities in stream"), gst_caps_get_type (),
     220                 :            :           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
     221                 :          8 :   g_object_class_install_property (gobject_class, PROP_MINIMUM,
     222                 :          8 :       g_param_spec_uint ("minimum", _("minimum"),
     223                 :            :           "minimum probability required to accept caps", GST_TYPE_FIND_MINIMUM,
     224                 :            :           GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MINIMUM,
     225                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     226                 :          8 :   g_object_class_install_property (gobject_class, PROP_MAXIMUM,
     227                 :          8 :       g_param_spec_uint ("maximum", _("maximum"),
     228                 :            :           "probability to stop typefinding (deprecated; non-functional)",
     229                 :            :           GST_TYPE_FIND_MINIMUM, GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MAXIMUM,
     230                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     231                 :          8 :   g_object_class_install_property (gobject_class, PROP_FORCE_CAPS,
     232                 :          8 :       g_param_spec_boxed ("force-caps", _("force caps"),
     233                 :          8 :           _("force caps without doing a typefind"), gst_caps_get_type (),
     234                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     235                 :            :   /**
     236                 :            :    * GstTypeFindElement::have-type:
     237                 :            :    * @typefind: the typefind instance
     238                 :            :    * @probability: the probability of the type found
     239                 :            :    * @caps: the caps of the type found
     240                 :            :    *
     241                 :            :    * This signal gets emitted when the type and its probability has
     242                 :            :    * been found.
     243                 :            :    */
     244                 :          8 :   gst_type_find_element_signals[HAVE_TYPE] = g_signal_new ("have-type",
     245                 :            :       G_TYPE_FROM_CLASS (typefind_class), G_SIGNAL_RUN_FIRST,
     246                 :            :       G_STRUCT_OFFSET (GstTypeFindElementClass, have_type), NULL, NULL,
     247                 :            :       gst_marshal_VOID__UINT_BOXED, G_TYPE_NONE, 2,
     248                 :          8 :       G_TYPE_UINT, GST_TYPE_CAPS | G_SIGNAL_TYPE_STATIC_SCOPE);
     249                 :            : 
     250                 :          8 :   typefind_class->have_type =
     251                 :          8 :       GST_DEBUG_FUNCPTR (gst_type_find_element_have_type);
     252                 :            : 
     253                 :          8 :   gstelement_class->change_state =
     254                 :          8 :       GST_DEBUG_FUNCPTR (gst_type_find_element_change_state);
     255                 :          8 : }
     256                 :            : 
     257                 :            : static void
     258                 :          3 : gst_type_find_element_init (GstTypeFindElement * typefind,
     259                 :            :     GstTypeFindElementClass * g_class)
     260                 :            : {
     261                 :            :   /* sinkpad */
     262                 :          3 :   typefind->sink =
     263                 :          3 :       gst_pad_new_from_static_template (&type_find_element_sink_template,
     264                 :            :       "sink");
     265                 :            : 
     266                 :          3 :   gst_pad_set_activate_function (typefind->sink,
     267                 :          3 :       GST_DEBUG_FUNCPTR (gst_type_find_element_activate));
     268                 :          3 :   gst_pad_set_setcaps_function (typefind->sink,
     269                 :          3 :       GST_DEBUG_FUNCPTR (gst_type_find_element_setcaps));
     270                 :          3 :   gst_pad_set_chain_function (typefind->sink,
     271                 :          3 :       GST_DEBUG_FUNCPTR (gst_type_find_element_chain));
     272                 :          3 :   gst_pad_set_event_function (typefind->sink,
     273                 :          3 :       GST_DEBUG_FUNCPTR (gst_type_find_element_handle_event));
     274                 :          3 :   gst_element_add_pad (GST_ELEMENT (typefind), typefind->sink);
     275                 :            : 
     276                 :            :   /* srcpad */
     277                 :          3 :   typefind->src =
     278                 :          3 :       gst_pad_new_from_static_template (&type_find_element_src_template, "src");
     279                 :            : 
     280                 :          3 :   gst_pad_set_activatepull_function (typefind->src,
     281                 :          3 :       GST_DEBUG_FUNCPTR (gst_type_find_element_activate_src_pull));
     282                 :          3 :   gst_pad_set_checkgetrange_function (typefind->src,
     283                 :          3 :       GST_DEBUG_FUNCPTR (gst_type_find_element_checkgetrange));
     284                 :          3 :   gst_pad_set_getrange_function (typefind->src,
     285                 :          3 :       GST_DEBUG_FUNCPTR (gst_type_find_element_getrange));
     286                 :          3 :   gst_pad_set_event_function (typefind->src,
     287                 :          3 :       GST_DEBUG_FUNCPTR (gst_type_find_element_src_event));
     288                 :          3 :   gst_pad_set_query_function (typefind->src,
     289                 :          3 :       GST_DEBUG_FUNCPTR (gst_type_find_handle_src_query));
     290                 :          3 :   gst_pad_use_fixed_caps (typefind->src);
     291                 :          3 :   gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
     292                 :            : 
     293                 :          3 :   typefind->mode = MODE_TYPEFIND;
     294                 :          3 :   typefind->caps = NULL;
     295                 :          3 :   typefind->min_probability = 1;
     296                 :          3 :   typefind->max_probability = GST_TYPE_FIND_MAXIMUM;
     297                 :            : 
     298                 :          3 :   typefind->store = NULL;
     299                 :          3 : }
     300                 :            : 
     301                 :            : static void
     302                 :          3 : gst_type_find_element_dispose (GObject * object)
     303                 :            : {
     304                 :          3 :   GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (object);
     305                 :            : 
     306         [ -  + ]:          3 :   if (typefind->store) {
     307                 :          0 :     gst_buffer_unref (typefind->store);
     308                 :          0 :     typefind->store = NULL;
     309                 :            :   }
     310                 :            : 
     311         [ -  + ]:          3 :   if (typefind->force_caps) {
     312                 :          0 :     gst_caps_unref (typefind->force_caps);
     313                 :          0 :     typefind->force_caps = NULL;
     314                 :            :   }
     315                 :            : 
     316                 :          3 :   G_OBJECT_CLASS (parent_class)->dispose (object);
     317                 :          3 : }
     318                 :            : 
     319                 :            : static void
     320                 :          0 : gst_type_find_element_set_property (GObject * object, guint prop_id,
     321                 :            :     const GValue * value, GParamSpec * pspec)
     322                 :            : {
     323                 :            :   GstTypeFindElement *typefind;
     324                 :            : 
     325                 :          0 :   typefind = GST_TYPE_FIND_ELEMENT (object);
     326                 :            : 
     327   [ #  #  #  # ]:          0 :   switch (prop_id) {
     328                 :            :     case PROP_MINIMUM:
     329                 :          0 :       typefind->min_probability = g_value_get_uint (value);
     330                 :          0 :       break;
     331                 :            :     case PROP_MAXIMUM:
     332                 :          0 :       typefind->max_probability = g_value_get_uint (value);
     333                 :          0 :       break;
     334                 :            :     case PROP_FORCE_CAPS:
     335                 :          0 :       GST_OBJECT_LOCK (typefind);
     336         [ #  # ]:          0 :       if (typefind->force_caps)
     337                 :          0 :         gst_caps_unref (typefind->force_caps);
     338                 :          0 :       typefind->force_caps = g_value_dup_boxed (value);
     339                 :          0 :       GST_OBJECT_UNLOCK (typefind);
     340                 :          0 :       break;
     341                 :            :     default:
     342                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     343                 :          0 :       break;
     344                 :            :   }
     345                 :          0 : }
     346                 :            : 
     347                 :            : static void
     348                 :          0 : gst_type_find_element_get_property (GObject * object, guint prop_id,
     349                 :            :     GValue * value, GParamSpec * pspec)
     350                 :            : {
     351                 :            :   GstTypeFindElement *typefind;
     352                 :            : 
     353                 :          0 :   typefind = GST_TYPE_FIND_ELEMENT (object);
     354                 :            : 
     355   [ #  #  #  #  :          0 :   switch (prop_id) {
                      # ]
     356                 :            :     case PROP_CAPS:
     357                 :          0 :       GST_OBJECT_LOCK (typefind);
     358                 :          0 :       g_value_set_boxed (value, typefind->caps);
     359                 :          0 :       GST_OBJECT_UNLOCK (typefind);
     360                 :          0 :       break;
     361                 :            :     case PROP_MINIMUM:
     362                 :          0 :       g_value_set_uint (value, typefind->min_probability);
     363                 :          0 :       break;
     364                 :            :     case PROP_MAXIMUM:
     365                 :          0 :       g_value_set_uint (value, typefind->max_probability);
     366                 :          0 :       break;
     367                 :            :     case PROP_FORCE_CAPS:
     368                 :          0 :       GST_OBJECT_LOCK (typefind);
     369                 :          0 :       g_value_set_boxed (value, typefind->force_caps);
     370                 :          0 :       GST_OBJECT_UNLOCK (typefind);
     371                 :          0 :       break;
     372                 :            :     default:
     373                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     374                 :          0 :       break;
     375                 :            :   }
     376                 :          0 : }
     377                 :            : 
     378                 :            : static gboolean
     379                 :          0 : gst_type_find_handle_src_query (GstPad * pad, GstQuery * query)
     380                 :            : {
     381                 :            :   GstTypeFindElement *typefind;
     382                 :          0 :   gboolean res = FALSE;
     383                 :            :   GstPad *peer;
     384                 :            : 
     385                 :          0 :   typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
     386                 :            : 
     387                 :          0 :   peer = gst_pad_get_peer (typefind->sink);
     388         [ #  # ]:          0 :   if (peer == NULL)
     389                 :          0 :     return FALSE;
     390                 :            : 
     391                 :          0 :   res = gst_pad_query (peer, query);
     392         [ #  # ]:          0 :   if (!res)
     393                 :          0 :     goto out;
     394                 :            : 
     395         [ #  # ]:          0 :   switch (GST_QUERY_TYPE (query)) {
     396                 :            :     case GST_QUERY_POSITION:
     397                 :            :     {
     398                 :            :       gint64 peer_pos;
     399                 :            :       GstFormat format;
     400                 :            : 
     401                 :          0 :       GST_OBJECT_LOCK (typefind);
     402         [ #  # ]:          0 :       if (typefind->store == NULL) {
     403                 :          0 :         GST_OBJECT_UNLOCK (typefind);
     404                 :          0 :         goto out;
     405                 :            :       }
     406                 :            : 
     407                 :          0 :       gst_query_parse_position (query, &format, &peer_pos);
     408                 :            : 
     409                 :            :       /* FIXME: this code assumes that there's no discont in the queue */
     410         [ #  # ]:          0 :       switch (format) {
     411                 :            :         case GST_FORMAT_BYTES:
     412                 :          0 :           peer_pos -= GST_BUFFER_SIZE (typefind->store);
     413                 :          0 :           break;
     414                 :            :         default:
     415                 :            :           /* FIXME */
     416                 :          0 :           break;
     417                 :            :       }
     418                 :          0 :       GST_OBJECT_UNLOCK (typefind);
     419                 :          0 :       gst_query_set_position (query, format, peer_pos);
     420                 :          0 :       break;
     421                 :            :     }
     422                 :            :     default:
     423                 :          0 :       break;
     424                 :            :   }
     425                 :            : 
     426                 :            : out:
     427                 :          0 :   gst_object_unref (peer);
     428                 :          0 :   return res;
     429                 :            : }
     430                 :            : 
     431                 :            : #if 0
     432                 :            : static const GstEventMask *
     433                 :            : gst_type_find_element_src_event_mask (GstPad * pad)
     434                 :            : {
     435                 :            :   static const GstEventMask mask[] = {
     436                 :            :     {GST_EVENT_SEEK,
     437                 :            :         GST_SEEK_METHOD_SET | GST_SEEK_METHOD_CUR | GST_SEEK_METHOD_END |
     438                 :            :           GST_SEEK_FLAG_FLUSH},
     439                 :            :     /* add more if you want, event masks suck and need to die anyway */
     440                 :            :     {0,}
     441                 :            :   };
     442                 :            : 
     443                 :            :   return mask;
     444                 :            : }
     445                 :            : #endif
     446                 :            : 
     447                 :            : static gboolean
     448                 :          0 : gst_type_find_element_src_event (GstPad * pad, GstEvent * event)
     449                 :            : {
     450                 :          0 :   GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
     451                 :            : 
     452         [ #  # ]:          0 :   if (typefind->mode != MODE_NORMAL) {
     453                 :            :     /* need to do more? */
     454                 :          0 :     gst_mini_object_unref (GST_MINI_OBJECT (event));
     455                 :          0 :     return FALSE;
     456                 :            :   }
     457                 :          0 :   return gst_pad_push_event (typefind->sink, event);
     458                 :            : }
     459                 :            : 
     460                 :            : static void
     461                 :          7 : start_typefinding (GstTypeFindElement * typefind)
     462                 :            : {
     463         [ -  + ]:          7 :   GST_DEBUG_OBJECT (typefind, "starting typefinding");
     464                 :          7 :   gst_pad_set_caps (typefind->src, NULL);
     465                 :            : 
     466                 :          7 :   GST_OBJECT_LOCK (typefind);
     467         [ -  + ]:          7 :   if (typefind->caps)
     468                 :          0 :     gst_caps_replace (&typefind->caps, NULL);
     469                 :          7 :   GST_OBJECT_UNLOCK (typefind);
     470                 :            : 
     471                 :          7 :   typefind->mode = MODE_TYPEFIND;
     472                 :          7 : }
     473                 :            : 
     474                 :            : static void
     475                 :          0 : stop_typefinding (GstTypeFindElement * typefind)
     476                 :            : {
     477                 :            :   GstState state;
     478                 :            :   gboolean push_cached_buffers;
     479                 :            : 
     480                 :          0 :   gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, 0);
     481                 :            : 
     482                 :          0 :   push_cached_buffers = (state >= GST_STATE_PAUSED);
     483                 :            : 
     484 [ #  # ][ #  # ]:          0 :   GST_DEBUG_OBJECT (typefind, "stopping typefinding%s",
     485                 :            :       push_cached_buffers ? " and pushing cached buffers" : "");
     486                 :            : 
     487                 :          0 :   GST_OBJECT_LOCK (typefind);
     488         [ #  # ]:          0 :   if (typefind->store) {
     489                 :            :     GstBuffer *store;
     490                 :            : 
     491                 :          0 :     store = gst_buffer_make_metadata_writable (typefind->store);
     492                 :          0 :     typefind->store = NULL;
     493                 :          0 :     gst_buffer_set_caps (store, typefind->caps);
     494                 :          0 :     GST_OBJECT_UNLOCK (typefind);
     495                 :            : 
     496         [ #  # ]:          0 :     if (!push_cached_buffers) {
     497                 :          0 :       gst_buffer_unref (store);
     498                 :            :     } else {
     499                 :          0 :       GstPad *peer = gst_pad_get_peer (typefind->src);
     500                 :            : 
     501                 :          0 :       typefind->mode = MODE_NORMAL;
     502                 :            : 
     503                 :            :       /* make sure the user gets a meaningful error message in this case,
     504                 :            :        * which is not a core bug or bug of any kind (as the default error
     505                 :            :        * message emitted by gstpad.c otherwise would make you think) */
     506 [ #  # ][ #  # ]:          0 :       if (peer && GST_PAD_CHAINFUNC (peer) == NULL) {
     507         [ #  # ]:          0 :         GST_DEBUG_OBJECT (typefind, "upstream only supports push mode, while "
     508                 :            :             "downstream element only works in pull mode, erroring out");
     509 [ #  # ][ #  # ]:          0 :         GST_ELEMENT_ERROR (typefind, STREAM, FAILED,
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     510                 :            :             ("%s cannot work in push mode. The operation is not supported "
     511                 :            :                 "with this source element or protocol.",
     512                 :            :                 G_OBJECT_TYPE_NAME (GST_PAD_PARENT (peer))),
     513                 :            :             ("Downstream pad %s:%s has no chainfunction, and the upstream "
     514                 :            :                 "element does not support pull mode",
     515                 :            :                 GST_DEBUG_PAD_NAME (peer)));
     516                 :          0 :         typefind->mode = MODE_ERROR;    /* make the chain function error out */
     517                 :          0 :         gst_buffer_unref (store);
     518                 :            :       } else {
     519                 :          0 :         gst_type_find_element_send_cached_events (typefind);
     520                 :          0 :         gst_pad_push (typefind->src, store);
     521                 :            :       }
     522                 :            : 
     523         [ #  # ]:          0 :       if (peer)
     524                 :          0 :         gst_object_unref (peer);
     525                 :            :     }
     526                 :            :   } else {
     527                 :          0 :     GST_OBJECT_UNLOCK (typefind);
     528                 :            :   }
     529                 :          0 : }
     530                 :            : 
     531                 :            : static gboolean
     532                 :          0 : gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
     533                 :            : {
     534                 :          0 :   gboolean res = FALSE;
     535                 :          0 :   GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
     536                 :            : 
     537         [ #  # ]:          0 :   GST_DEBUG_OBJECT (typefind, "got %s event in mode %d",
     538                 :            :       GST_EVENT_TYPE_NAME (event), typefind->mode);
     539                 :            : 
     540   [ #  #  #  # ]:          0 :   switch (typefind->mode) {
     541                 :            :     case MODE_TYPEFIND:
     542   [ #  #  #  # ]:          0 :       switch (GST_EVENT_TYPE (event)) {
     543                 :            :         case GST_EVENT_EOS:{
     544                 :          0 :           GstTypeFindProbability prob = 0;
     545                 :          0 :           GstCaps *caps = NULL;
     546                 :            : 
     547         [ #  # ]:          0 :           GST_INFO_OBJECT (typefind, "Got EOS and no type found yet");
     548                 :            : 
     549                 :            :           /* we might not have started typefinding yet because there was not
     550                 :            :            * enough data so far; just give it a shot now and see what we get */
     551                 :          0 :           GST_OBJECT_LOCK (typefind);
     552         [ #  # ]:          0 :           if (typefind->store) {
     553                 :          0 :             caps = gst_type_find_helper_for_buffer (GST_OBJECT (typefind),
     554                 :            :                 typefind->store, &prob);
     555                 :          0 :             GST_OBJECT_UNLOCK (typefind);
     556                 :            : 
     557 [ #  # ][ #  # ]:          0 :             if (caps && prob >= typefind->min_probability) {
     558                 :          0 :               g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
     559                 :            :                   0, prob, caps);
     560                 :            :             } else {
     561 [ #  # ][ #  # ]:          0 :               GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
         [ #  # ][ #  # ]
     562                 :            :                   (NULL), (NULL));
     563                 :            :             }
     564                 :          0 :             gst_caps_replace (&caps, NULL);
     565                 :            :           } else {
     566                 :          0 :             GST_OBJECT_UNLOCK (typefind);
     567                 :            :             /* keep message in sync with the one in the pad activate function */
     568 [ #  # ][ #  # ]:          0 :             GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
         [ #  # ][ #  # ]
     569                 :            :                 (_("Stream contains no data.")),
     570                 :            :                 ("Can't typefind empty stream"));
     571                 :            :           }
     572                 :            : 
     573                 :          0 :           stop_typefinding (typefind);
     574                 :          0 :           res = gst_pad_push_event (typefind->src, event);
     575                 :          0 :           break;
     576                 :            :         }
     577                 :            :         case GST_EVENT_FLUSH_STOP:
     578                 :          0 :           GST_OBJECT_LOCK (typefind);
     579                 :          0 :           g_list_foreach (typefind->cached_events,
     580                 :            :               (GFunc) gst_mini_object_unref, NULL);
     581                 :          0 :           g_list_free (typefind->cached_events);
     582                 :          0 :           typefind->cached_events = NULL;
     583                 :          0 :           gst_buffer_replace (&typefind->store, NULL);
     584                 :          0 :           GST_OBJECT_UNLOCK (typefind);
     585                 :            :           /* fall through */
     586                 :            :         case GST_EVENT_FLUSH_START:
     587                 :          0 :           res = gst_pad_push_event (typefind->src, event);
     588                 :          0 :           break;
     589                 :            :         default:
     590         [ #  # ]:          0 :           GST_DEBUG_OBJECT (typefind, "Saving %s event to send later",
     591                 :            :               GST_EVENT_TYPE_NAME (event));
     592                 :          0 :           GST_OBJECT_LOCK (typefind);
     593                 :          0 :           typefind->cached_events =
     594                 :          0 :               g_list_append (typefind->cached_events, event);
     595                 :          0 :           GST_OBJECT_UNLOCK (typefind);
     596                 :          0 :           res = TRUE;
     597                 :          0 :           break;
     598                 :            :       }
     599                 :          0 :       break;
     600                 :            :     case MODE_NORMAL:
     601                 :          0 :       res = gst_pad_push_event (typefind->src, event);
     602                 :          0 :       break;
     603                 :            :     case MODE_ERROR:
     604                 :          0 :       break;
     605                 :            :     default:
     606                 :          0 :       g_assert_not_reached ();
     607                 :            :   }
     608                 :          0 :   return res;
     609                 :            : }
     610                 :            : 
     611                 :            : static void
     612                 :          0 : gst_type_find_element_send_cached_events (GstTypeFindElement * typefind)
     613                 :            : {
     614                 :            :   GList *l, *cached_events;
     615                 :            : 
     616                 :          0 :   GST_OBJECT_LOCK (typefind);
     617                 :          0 :   cached_events = typefind->cached_events;
     618                 :          0 :   typefind->cached_events = NULL;
     619                 :          0 :   GST_OBJECT_UNLOCK (typefind);
     620                 :            : 
     621         [ #  # ]:          0 :   for (l = cached_events; l != NULL; l = l->next) {
     622                 :          0 :     GstEvent *event = GST_EVENT (l->data);
     623                 :            : 
     624         [ #  # ]:          0 :     GST_DEBUG_OBJECT (typefind, "sending cached %s event",
     625                 :            :         GST_EVENT_TYPE_NAME (event));
     626                 :          0 :     gst_pad_push_event (typefind->src, event);
     627                 :            :   }
     628                 :          0 :   g_list_free (cached_events);
     629                 :          0 : }
     630                 :            : 
     631                 :            : static gboolean
     632                 :          0 : gst_type_find_element_setcaps (GstPad * pad, GstCaps * caps)
     633                 :            : {
     634                 :            :   GstTypeFindElement *typefind;
     635                 :            : 
     636                 :          0 :   typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
     637                 :            : 
     638                 :            :   /* don't operate on ANY caps */
     639         [ #  # ]:          0 :   if (gst_caps_is_any (caps))
     640                 :          0 :     return TRUE;
     641                 :            : 
     642                 :          0 :   g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
     643                 :            :       GST_TYPE_FIND_MAXIMUM, caps);
     644                 :            : 
     645                 :            :   /* Shortcircuit typefinding if we get caps */
     646         [ #  # ]:          0 :   if (typefind->mode == MODE_TYPEFIND) {
     647         [ #  # ]:          0 :     GST_DEBUG_OBJECT (typefind, "Skipping typefinding, using caps from "
     648                 :            :         "upstream buffer: %" GST_PTR_FORMAT, caps);
     649                 :          0 :     typefind->mode = MODE_NORMAL;
     650                 :            : 
     651                 :          0 :     gst_type_find_element_send_cached_events (typefind);
     652                 :          0 :     GST_OBJECT_LOCK (typefind);
     653         [ #  # ]:          0 :     if (typefind->store) {
     654                 :            :       GstBuffer *store;
     655                 :            : 
     656                 :          0 :       store = gst_buffer_make_metadata_writable (typefind->store);
     657                 :          0 :       typefind->store = NULL;
     658                 :          0 :       gst_buffer_set_caps (store, typefind->caps);
     659                 :          0 :       GST_OBJECT_UNLOCK (typefind);
     660                 :            : 
     661         [ #  # ]:          0 :       GST_DEBUG_OBJECT (typefind, "Pushing store: %d", GST_BUFFER_SIZE (store));
     662                 :          0 :       gst_pad_push (typefind->src, store);
     663                 :            :     } else {
     664                 :          0 :       GST_OBJECT_UNLOCK (typefind);
     665                 :            :     }
     666                 :            :   }
     667                 :            : 
     668                 :          0 :   return TRUE;
     669                 :            : }
     670                 :            : 
     671                 :            : static gchar *
     672                 :          0 : gst_type_find_get_extension (GstTypeFindElement * typefind, GstPad * pad)
     673                 :            : {
     674                 :            :   GstQuery *query;
     675                 :            :   gchar *uri, *result;
     676                 :            :   size_t len;
     677                 :            :   gint find;
     678                 :            : 
     679                 :          0 :   query = gst_query_new_uri ();
     680                 :            : 
     681                 :            :   /* try getting the caps with an uri query and from the extension */
     682         [ #  # ]:          0 :   if (!gst_pad_peer_query (pad, query))
     683                 :          0 :     goto peer_query_failed;
     684                 :            : 
     685                 :          0 :   gst_query_parse_uri (query, &uri);
     686         [ #  # ]:          0 :   if (uri == NULL)
     687                 :          0 :     goto no_uri;
     688                 :            : 
     689         [ #  # ]:          0 :   GST_DEBUG_OBJECT (typefind, "finding extension of %s", uri);
     690                 :            : 
     691                 :            :   /* find the extension on the uri, this is everything after a '.' */
     692                 :          0 :   len = strlen (uri);
     693                 :          0 :   find = len - 1;
     694                 :            : 
     695         [ #  # ]:          0 :   while (find >= 0) {
     696         [ #  # ]:          0 :     if (uri[find] == '.')
     697                 :          0 :       break;
     698                 :          0 :     find--;
     699                 :            :   }
     700         [ #  # ]:          0 :   if (find < 0)
     701                 :          0 :     goto no_extension;
     702                 :            : 
     703                 :          0 :   result = g_strdup (&uri[find + 1]);
     704                 :            : 
     705         [ #  # ]:          0 :   GST_DEBUG_OBJECT (typefind, "found extension %s", result);
     706                 :          0 :   gst_query_unref (query);
     707                 :          0 :   g_free (uri);
     708                 :            : 
     709                 :          0 :   return result;
     710                 :            : 
     711                 :            :   /* ERRORS */
     712                 :            : peer_query_failed:
     713                 :            :   {
     714         [ #  # ]:          0 :     GST_WARNING_OBJECT (typefind, "failed to query peer uri");
     715                 :          0 :     gst_query_unref (query);
     716                 :          0 :     return NULL;
     717                 :            :   }
     718                 :            : no_uri:
     719                 :            :   {
     720         [ #  # ]:          0 :     GST_WARNING_OBJECT (typefind, "could not parse the peer uri");
     721                 :          0 :     gst_query_unref (query);
     722                 :          0 :     return NULL;
     723                 :            :   }
     724                 :            : no_extension:
     725                 :            :   {
     726         [ #  # ]:          0 :     GST_WARNING_OBJECT (typefind, "could not find uri extension in %s", uri);
     727                 :          0 :     gst_query_unref (query);
     728                 :          0 :     g_free (uri);
     729                 :          0 :     return NULL;
     730                 :            :   }
     731                 :            : }
     732                 :            : 
     733                 :            : static GstCaps *
     734                 :          0 : gst_type_find_guess_by_extension (GstTypeFindElement * typefind, GstPad * pad,
     735                 :            :     GstTypeFindProbability * probability)
     736                 :            : {
     737                 :            :   gchar *ext;
     738                 :            :   GstCaps *caps;
     739                 :            : 
     740                 :          0 :   ext = gst_type_find_get_extension (typefind, pad);
     741         [ #  # ]:          0 :   if (!ext)
     742                 :          0 :     return NULL;
     743                 :            : 
     744                 :          0 :   caps = gst_type_find_helper_for_extension (GST_OBJECT_CAST (typefind), ext);
     745         [ #  # ]:          0 :   if (caps)
     746                 :          0 :     *probability = GST_TYPE_FIND_MAXIMUM;
     747                 :            : 
     748                 :          0 :   g_free (ext);
     749                 :            : 
     750                 :          0 :   return caps;
     751                 :            : }
     752                 :            : 
     753                 :            : static GstFlowReturn
     754                 :          0 : gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
     755                 :            : {
     756                 :            :   GstTypeFindElement *typefind;
     757                 :          0 :   GstFlowReturn res = GST_FLOW_OK;
     758                 :            : 
     759                 :          0 :   typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
     760                 :            : 
     761         [ #  # ]:          0 :   GST_LOG_OBJECT (typefind, "handling buffer in mode %d", typefind->mode);
     762                 :            : 
     763   [ #  #  #  # ]:          0 :   switch (typefind->mode) {
     764                 :            :     case MODE_ERROR:
     765                 :            :       /* we should already have called GST_ELEMENT_ERROR */
     766                 :          0 :       return GST_FLOW_ERROR;
     767                 :            :     case MODE_NORMAL:
     768                 :            :       /* don't take object lock as typefind->caps should not change anymore */
     769                 :          0 :       buffer = gst_buffer_make_metadata_writable (buffer);
     770                 :          0 :       gst_buffer_set_caps (buffer, typefind->caps);
     771                 :          0 :       return gst_pad_push (typefind->src, buffer);
     772                 :            :     case MODE_TYPEFIND:{
     773                 :          0 :       GST_OBJECT_LOCK (typefind);
     774         [ #  # ]:          0 :       if (typefind->store)
     775                 :          0 :         typefind->store = gst_buffer_join (typefind->store, buffer);
     776                 :            :       else
     777                 :          0 :         typefind->store = buffer;
     778                 :          0 :       GST_OBJECT_UNLOCK (typefind);
     779                 :            : 
     780                 :          0 :       res = gst_type_find_element_chain_do_typefinding (typefind);
     781                 :            : 
     782         [ #  # ]:          0 :       if (typefind->mode == MODE_ERROR)
     783                 :          0 :         res = GST_FLOW_ERROR;
     784                 :            : 
     785                 :          0 :       break;
     786                 :            :     }
     787                 :            :     default:
     788                 :          0 :       g_assert_not_reached ();
     789                 :            :       return GST_FLOW_ERROR;
     790                 :            :   }
     791                 :            : 
     792                 :          0 :   return res;
     793                 :            : }
     794                 :            : 
     795                 :            : static GstFlowReturn
     796                 :          0 : gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind)
     797                 :            : {
     798                 :            :   GstTypeFindProbability probability;
     799                 :            :   GstCaps *caps;
     800                 :            : 
     801                 :          0 :   GST_OBJECT_LOCK (typefind);
     802         [ #  # ]:          0 :   if (GST_BUFFER_SIZE (typefind->store) < TYPE_FIND_MIN_SIZE) {
     803         [ #  # ]:          0 :     GST_DEBUG_OBJECT (typefind, "not enough data for typefinding yet "
     804                 :            :         "(%u bytes)", GST_BUFFER_SIZE (typefind->store));
     805                 :          0 :     GST_OBJECT_UNLOCK (typefind);
     806                 :          0 :     return GST_FLOW_OK;
     807                 :            :   }
     808                 :            : 
     809                 :          0 :   caps = gst_type_find_helper_for_buffer (GST_OBJECT (typefind),
     810                 :            :       typefind->store, &probability);
     811 [ #  # ][ #  # ]:          0 :   if (caps == NULL && GST_BUFFER_SIZE (typefind->store) > TYPE_FIND_MAX_SIZE) {
     812                 :          0 :     GST_OBJECT_UNLOCK (typefind);
     813 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
         [ #  # ][ #  # ]
     814                 :          0 :     stop_typefinding (typefind);
     815                 :          0 :     return GST_FLOW_ERROR;
     816         [ #  # ]:          0 :   } else if (caps == NULL) {
     817                 :          0 :     GST_OBJECT_UNLOCK (typefind);
     818         [ #  # ]:          0 :     GST_DEBUG_OBJECT (typefind, "no caps found with %u bytes of data, "
     819                 :            :         "waiting for more data", GST_BUFFER_SIZE (typefind->store));
     820                 :          0 :     return GST_FLOW_OK;
     821                 :            :   }
     822                 :            : 
     823                 :            :   /* found a type */
     824         [ #  # ]:          0 :   if (probability < typefind->min_probability) {
     825         [ #  # ]:          0 :     GST_DEBUG_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", but "
     826                 :            :         "probability is %u which is lower than the required minimum of %u",
     827                 :            :         caps, probability, typefind->min_probability);
     828                 :            : 
     829                 :          0 :     gst_caps_replace (&caps, NULL);
     830                 :            : 
     831         [ #  # ]:          0 :     if (GST_BUFFER_SIZE (typefind->store) >= TYPE_FIND_MAX_SIZE) {
     832                 :          0 :       GST_OBJECT_UNLOCK (typefind);
     833 [ #  # ][ #  # ]:          0 :       GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
         [ #  # ][ #  # ]
     834                 :          0 :       stop_typefinding (typefind);
     835                 :          0 :       return GST_FLOW_ERROR;
     836                 :            :     }
     837                 :            : 
     838                 :          0 :     GST_OBJECT_UNLOCK (typefind);
     839         [ #  # ]:          0 :     GST_DEBUG_OBJECT (typefind, "waiting for more data to try again");
     840                 :          0 :     return GST_FLOW_OK;
     841                 :            :   }
     842                 :          0 :   GST_OBJECT_UNLOCK (typefind);
     843                 :            : 
     844                 :            :   /* probability is good enough too, so let's make it known ... */
     845                 :          0 :   g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
     846                 :            :       probability, caps);
     847                 :            : 
     848                 :            :   /* .. and send out the accumulated data */
     849                 :          0 :   stop_typefinding (typefind);
     850                 :          0 :   gst_caps_unref (caps);
     851                 :          0 :   return GST_FLOW_OK;
     852                 :            : }
     853                 :            : 
     854                 :            : static gboolean
     855                 :          0 : gst_type_find_element_checkgetrange (GstPad * srcpad)
     856                 :            : {
     857                 :            :   GstTypeFindElement *typefind;
     858                 :            : 
     859                 :          0 :   typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (srcpad));
     860                 :            : 
     861                 :          0 :   return gst_pad_check_pull_range (typefind->sink);
     862                 :            : }
     863                 :            : 
     864                 :            : static GstFlowReturn
     865                 :          0 : gst_type_find_element_getrange (GstPad * srcpad,
     866                 :            :     guint64 offset, guint length, GstBuffer ** buffer)
     867                 :            : {
     868                 :            :   GstTypeFindElement *typefind;
     869                 :            :   GstFlowReturn ret;
     870                 :            : 
     871                 :          0 :   typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (srcpad));
     872                 :            : 
     873                 :          0 :   ret = gst_pad_pull_range (typefind->sink, offset, length, buffer);
     874                 :            : 
     875 [ #  # ][ #  # ]:          0 :   if (ret == GST_FLOW_OK && buffer && *buffer) {
                 [ #  # ]
     876                 :            :     /* don't take object lock as typefind->caps should not change anymore */
     877                 :            :     /* we assume that pulled buffers are meta-data writable */
     878                 :          0 :     gst_buffer_set_caps (*buffer, typefind->caps);
     879                 :            :   }
     880                 :            : 
     881                 :          0 :   return ret;
     882                 :            : }
     883                 :            : 
     884                 :            : static gboolean
     885                 :          0 : gst_type_find_element_activate_src_pull (GstPad * pad, gboolean active)
     886                 :            : {
     887                 :            :   GstTypeFindElement *typefind;
     888                 :            : 
     889                 :          0 :   typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));
     890                 :            : 
     891                 :          0 :   return gst_pad_activate_pull (typefind->sink, active);
     892                 :            : }
     893                 :            : 
     894                 :            : static gboolean
     895                 :          7 : gst_type_find_element_activate (GstPad * pad)
     896                 :            : {
     897                 :          7 :   GstTypeFindProbability probability = 0;
     898                 :          7 :   GstCaps *found_caps = NULL;
     899                 :            :   GstTypeFindElement *typefind;
     900                 :            : 
     901                 :          7 :   typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));
     902                 :            : 
     903                 :            :   /* if we have force caps, use those */
     904                 :          7 :   GST_OBJECT_LOCK (typefind);
     905         [ -  + ]:          7 :   if (typefind->force_caps) {
     906                 :          0 :     found_caps = gst_caps_ref (typefind->force_caps);
     907                 :          0 :     probability = GST_TYPE_FIND_MAXIMUM;
     908                 :          0 :     GST_OBJECT_UNLOCK (typefind);
     909                 :          0 :     goto done;
     910                 :            :   }
     911                 :          7 :   GST_OBJECT_UNLOCK (typefind);
     912                 :            : 
     913                 :            :   /* 1. try to activate in pull mode. if not, switch to push and succeed.
     914                 :            :      2. try to pull type find.
     915                 :            :      3. deactivate pull mode.
     916                 :            :      4. src pad might have been activated push by the state change. deactivate.
     917                 :            :      5. if we didn't find any caps, try getting the uri extension by doing an uri
     918                 :            :      query.
     919                 :            :      6. if we didn't find any caps, fail.
     920                 :            :      7. emit have-type; maybe the app connected the source pad to something.
     921                 :            :      8. if the sink pad is activated, we are in pull mode. succeed.
     922                 :            :      otherwise activate both pads in push mode and succeed.
     923                 :            :    */
     924                 :            : 
     925                 :            :   /* 1 */
     926 [ -  + ][ #  # ]:          7 :   if (!gst_pad_check_pull_range (pad) || !gst_pad_activate_pull (pad, TRUE)) {
     927                 :          7 :     start_typefinding (typefind);
     928                 :          7 :     return gst_pad_activate_push (pad, TRUE);
     929                 :            :   }
     930                 :            : 
     931         [ #  # ]:          0 :   GST_DEBUG_OBJECT (typefind, "find type in pull mode");
     932                 :            : 
     933                 :            :   /* 2 */
     934                 :            :   {
     935                 :            :     GstPad *peer;
     936                 :            : 
     937                 :          0 :     peer = gst_pad_get_peer (pad);
     938         [ #  # ]:          0 :     if (peer) {
     939                 :            :       gint64 size;
     940                 :          0 :       GstFormat format = GST_FORMAT_BYTES;
     941                 :            :       gchar *ext;
     942                 :            : 
     943         [ #  # ]:          0 :       if (!gst_pad_query_duration (peer, &format, &size)) {
     944         [ #  # ]:          0 :         GST_WARNING_OBJECT (typefind, "Could not query upstream length!");
     945                 :          0 :         gst_object_unref (peer);
     946                 :          0 :         gst_pad_activate_pull (pad, FALSE);
     947                 :          0 :         return FALSE;
     948                 :            :       }
     949                 :            : 
     950                 :            :       /* the size if 0, we cannot continue */
     951         [ #  # ]:          0 :       if (size == 0) {
     952                 :            :         /* keep message in sync with message in sink event handler */
     953 [ #  # ][ #  # ]:          0 :         GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
         [ #  # ][ #  # ]
     954                 :            :             (_("Stream contains no data.")), ("Can't typefind empty stream"));
     955                 :          0 :         gst_object_unref (peer);
     956                 :          0 :         gst_pad_activate_pull (pad, FALSE);
     957                 :          0 :         return FALSE;
     958                 :            :       }
     959                 :          0 :       ext = gst_type_find_get_extension (typefind, pad);
     960                 :            : 
     961                 :          0 :       found_caps = gst_type_find_helper_get_range_ext (GST_OBJECT_CAST (peer),
     962                 :          0 :           (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)),
     963                 :            :           (guint64) size, ext, &probability);
     964                 :          0 :       g_free (ext);
     965                 :            : 
     966                 :          0 :       gst_object_unref (peer);
     967                 :            :     }
     968                 :            :   }
     969                 :            : 
     970                 :            :   /* the type find helpers might have triggered setcaps here (due to upstream)
     971                 :            :    * setting caps on buffers, which emits typefound signal and an element
     972                 :            :    * could have been linked and have its pads activated
     973                 :            :    *
     974                 :            :    * If we deactivate the pads in the following steps we might mess up
     975                 :            :    * downstream element. We should prevent that.
     976                 :            :    */
     977         [ #  # ]:          0 :   if (typefind->mode == MODE_NORMAL) {
     978                 :            :     /* this means we already emitted typefound */
     979         [ #  # ]:          0 :     GST_DEBUG ("Already managed to typefind !");
     980                 :          0 :     goto really_done;
     981                 :            :   }
     982                 :            : 
     983                 :            :   /* 3 */
     984                 :          0 :   gst_pad_activate_pull (pad, FALSE);
     985                 :            : 
     986                 :            :   /* 4 */
     987                 :          0 :   gst_pad_activate_push (typefind->src, FALSE);
     988                 :            : 
     989                 :            :   /* 5 */
     990 [ #  # ][ #  # ]:          0 :   if (!found_caps || probability < typefind->min_probability) {
     991                 :          0 :     found_caps = gst_type_find_guess_by_extension (typefind, pad, &probability);
     992                 :            :   }
     993                 :            : 
     994                 :            :   /* 6 */
     995 [ #  # ][ #  # ]:          0 :   if (!found_caps || probability < typefind->min_probability) {
     996 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
         [ #  # ][ #  # ]
     997                 :          0 :     gst_caps_replace (&found_caps, NULL);
     998                 :          0 :     return FALSE;
     999                 :            :   }
    1000                 :            : 
    1001                 :            : done:
    1002                 :            :   /* 7 */
    1003                 :          0 :   g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
    1004                 :            :       0, probability, found_caps);
    1005                 :          0 :   typefind->mode = MODE_NORMAL;
    1006                 :            : really_done:
    1007                 :          0 :   gst_caps_unref (found_caps);
    1008                 :            : 
    1009                 :            :   /* 8 */
    1010         [ #  # ]:          0 :   if (gst_pad_is_active (pad))
    1011                 :          0 :     return TRUE;
    1012                 :            :   else {
    1013                 :            :     gboolean ret;
    1014                 :            : 
    1015                 :          0 :     ret = gst_pad_activate_push (typefind->src, TRUE);
    1016                 :          0 :     ret &= gst_pad_activate_push (pad, TRUE);
    1017                 :          7 :     return ret;
    1018                 :            :   }
    1019                 :            : }
    1020                 :            : 
    1021                 :            : static GstStateChangeReturn
    1022                 :         34 : gst_type_find_element_change_state (GstElement * element,
    1023                 :            :     GstStateChange transition)
    1024                 :            : {
    1025                 :            :   GstStateChangeReturn ret;
    1026                 :            :   GstTypeFindElement *typefind;
    1027                 :            : 
    1028                 :         34 :   typefind = GST_TYPE_FIND_ELEMENT (element);
    1029                 :            : 
    1030                 :            : 
    1031                 :         34 :   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
    1032                 :            : 
    1033         [ +  + ]:         34 :   switch (transition) {
    1034                 :            :     case GST_STATE_CHANGE_PAUSED_TO_READY:
    1035                 :            :     case GST_STATE_CHANGE_READY_TO_NULL:
    1036                 :         11 :       GST_OBJECT_LOCK (typefind);
    1037                 :         11 :       gst_caps_replace (&typefind->caps, NULL);
    1038                 :            : 
    1039                 :         11 :       g_list_foreach (typefind->cached_events,
    1040                 :            :           (GFunc) gst_mini_object_unref, NULL);
    1041                 :         11 :       g_list_free (typefind->cached_events);
    1042                 :         11 :       typefind->cached_events = NULL;
    1043                 :         11 :       typefind->mode = MODE_TYPEFIND;
    1044                 :         11 :       GST_OBJECT_UNLOCK (typefind);
    1045                 :         11 :       break;
    1046                 :            :     default:
    1047                 :         23 :       break;
    1048                 :            :   }
    1049                 :            : 
    1050                 :         34 :   return ret;
    1051                 :            : }

Generated by: LCOV version 1.9