LCOV - code coverage report
Current view: top level - libs/gst/base - gsttypefindhelper.c (source / functions) Hit Total Coverage
Test: GStreamer 0.10.32.1 Lines: 47 185 25.4 %
Date: 2011-03-25 Functions: 3 10 30.0 %
Branches: 24 164 14.6 %

           Branch data     Line data    Source code
       1                 :            : /* GStreamer
       2                 :            :  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
       3                 :            :  * Copyright (C) 2000,2005 Wim Taymans <wim@fluendo.com>
       4                 :            :  * Copyright (C) 2006      Tim-Philipp Müller <tim centricular net>
       5                 :            :  *
       6                 :            :  * gsttypefindhelper.c:
       7                 :            :  *
       8                 :            :  * This library is free software; you can redistribute it and/or
       9                 :            :  * modify it under the terms of the GNU Library General Public
      10                 :            :  * License as published by the Free Software Foundation; either
      11                 :            :  * version 2 of the License, or (at your option) any later version.
      12                 :            :  *
      13                 :            :  * This library is distributed in the hope that it will be useful,
      14                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16                 :            :  * Library General Public License for more details.
      17                 :            :  *
      18                 :            :  * You should have received a copy of the GNU Library General Public
      19                 :            :  * License along with this library; if not, write to the
      20                 :            :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      21                 :            :  * Boston, MA 02111-1307, USA.
      22                 :            :  */
      23                 :            : 
      24                 :            : /**
      25                 :            :  * SECTION:gsttypefindhelper
      26                 :            :  * @short_description: Utility functions for typefinding 
      27                 :            :  *
      28                 :            :  * Utility functions for elements doing typefinding:
      29                 :            :  * gst_type_find_helper() does typefinding in pull mode, while
      30                 :            :  * gst_type_find_helper_for_buffer() is useful for elements needing to do
      31                 :            :  * typefinding in push mode from a chain function.
      32                 :            :  */
      33                 :            : 
      34                 :            : #ifdef HAVE_CONFIG_H
      35                 :            : #  include "config.h"
      36                 :            : #endif
      37                 :            : 
      38                 :            : #include <stdlib.h>
      39                 :            : #include <string.h>
      40                 :            : 
      41                 :            : #include "gsttypefindhelper.h"
      42                 :            : 
      43                 :            : /* ********************** typefinding in pull mode ************************ */
      44                 :            : 
      45                 :            : static void
      46                 :            : helper_find_suggest (gpointer data, guint probability, const GstCaps * caps);
      47                 :            : 
      48                 :            : typedef struct
      49                 :            : {
      50                 :            :   GSList *buffers;              /* buffer cache */
      51                 :            :   guint64 size;
      52                 :            :   guint64 last_offset;
      53                 :            :   GstTypeFindHelperGetRangeFunction func;
      54                 :            :   guint best_probability;
      55                 :            :   GstCaps *caps;
      56                 :            :   GstTypeFindFactory *factory;  /* for logging */
      57                 :            :   GstObject *obj;               /* for logging */
      58                 :            : } GstTypeFindHelper;
      59                 :            : 
      60                 :            : /*
      61                 :            :  * helper_find_peek:
      62                 :            :  * @data: helper data struct
      63                 :            :  * @off: stream offset
      64                 :            :  * @size: block size
      65                 :            :  *
      66                 :            :  * Get data pointer within a stream. Keeps a cache of read buffers (partly
      67                 :            :  * for performance reasons, but mostly because pointers returned by us need
      68                 :            :  * to stay valid until typefinding has finished)
      69                 :            :  *
      70                 :            :  * Returns: address of the data or %NULL if buffer does not cover the
      71                 :            :  * requested range.
      72                 :            :  */
      73                 :            : static guint8 *
      74                 :          0 : helper_find_peek (gpointer data, gint64 offset, guint size)
      75                 :            : {
      76                 :            :   GstTypeFindHelper *helper;
      77                 :            :   GstBuffer *buffer;
      78                 :            :   GstFlowReturn ret;
      79                 :          0 :   GSList *insert_pos = NULL;
      80                 :            :   guint buf_size;
      81                 :            :   guint64 buf_offset;
      82                 :            :   GstCaps *caps;
      83                 :            : 
      84                 :          0 :   helper = (GstTypeFindHelper *) data;
      85                 :            : 
      86         [ #  # ]:          0 :   GST_LOG_OBJECT (helper->obj, "'%s' called peek (%" G_GINT64_FORMAT
      87                 :            :       ", %u)", GST_PLUGIN_FEATURE_NAME (helper->factory), offset, size);
      88                 :            : 
      89         [ #  # ]:          0 :   if (size == 0)
      90                 :          0 :     return NULL;
      91                 :            : 
      92         [ #  # ]:          0 :   if (offset < 0) {
      93 [ #  # ][ #  # ]:          0 :     if (helper->size == -1 || helper->size < -offset)
      94                 :          0 :       return NULL;
      95                 :            : 
      96                 :          0 :     offset += helper->size;
      97                 :            :   }
      98                 :            : 
      99                 :            :   /* see if we have a matching buffer already in our list */
     100 [ #  # ][ #  # ]:          0 :   if (size > 0 && offset <= helper->last_offset) {
     101                 :            :     GSList *walk;
     102                 :            : 
     103         [ #  # ]:          0 :     for (walk = helper->buffers; walk; walk = walk->next) {
     104                 :          0 :       GstBuffer *buf = GST_BUFFER_CAST (walk->data);
     105                 :          0 :       guint64 buf_offset = GST_BUFFER_OFFSET (buf);
     106                 :          0 :       guint buf_size = GST_BUFFER_SIZE (buf);
     107                 :            : 
     108                 :            :       /* buffers are kept sorted by end offset (highest first) in the list, so
     109                 :            :        * at this point we save the current position and stop searching if 
     110                 :            :        * we're after the searched end offset */
     111         [ #  # ]:          0 :       if (buf_offset <= offset) {
     112         [ #  # ]:          0 :         if ((offset + size) < (buf_offset + buf_size)) {
     113                 :          0 :           return GST_BUFFER_DATA (buf) + (offset - buf_offset);
     114                 :            :         }
     115         [ #  # ]:          0 :       } else if (offset + size >= buf_offset + buf_size) {
     116                 :          0 :         insert_pos = walk;
     117                 :          0 :         break;
     118                 :            :       }
     119                 :            :     }
     120                 :            :   }
     121                 :            : 
     122                 :          0 :   buffer = NULL;
     123                 :            :   /* some typefinders go in 1 byte steps over 1k of data and request
     124                 :            :    * small buffers. It is really inefficient to pull each time, and pulling
     125                 :            :    * a larger chunk is almost free. Trying to pull a larger chunk at the end
     126                 :            :    * of the file is also not a problem here, we'll just get a truncated buffer
     127                 :            :    * in that case (and we'll have to double-check the size we actually get
     128                 :            :    * anyway, see below) */
     129                 :          0 :   ret = helper->func (helper->obj, offset, MAX (size, 4096), &buffer);
     130                 :            : 
     131         [ #  # ]:          0 :   if (ret != GST_FLOW_OK)
     132                 :          0 :     goto error;
     133                 :            : 
     134                 :          0 :   caps = GST_BUFFER_CAPS (buffer);
     135                 :            : 
     136 [ #  # ][ #  # ]:          0 :   if (caps && !gst_caps_is_empty (caps) && !gst_caps_is_any (caps)) {
                 [ #  # ]
     137         [ #  # ]:          0 :     GST_DEBUG ("buffer has caps %" GST_PTR_FORMAT ", suggest max probability",
     138                 :            :         caps);
     139                 :            : 
     140                 :          0 :     gst_caps_replace (&helper->caps, caps);
     141                 :          0 :     helper->best_probability = GST_TYPE_FIND_MAXIMUM;
     142                 :            : 
     143                 :          0 :     gst_buffer_unref (buffer);
     144                 :          0 :     return NULL;
     145                 :            :   }
     146                 :            : 
     147                 :            :   /* getrange might silently return shortened buffers at the end of a file,
     148                 :            :    * we must, however, always return either the full requested data or NULL */
     149                 :          0 :   buf_offset = GST_BUFFER_OFFSET (buffer);
     150                 :          0 :   buf_size = GST_BUFFER_SIZE (buffer);
     151                 :            : 
     152 [ #  # ][ #  # ]:          0 :   if ((buf_offset != -1 && buf_offset != offset) || buf_size < size) {
                 [ #  # ]
     153         [ #  # ]:          0 :     GST_DEBUG ("droping short buffer: %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT
     154                 :            :         " instead of %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT,
     155                 :            :         buf_offset, buf_offset + buf_size - 1, offset, offset + size - 1);
     156                 :          0 :     gst_buffer_unref (buffer);
     157                 :          0 :     return NULL;
     158                 :            :   }
     159                 :            : 
     160         [ #  # ]:          0 :   if (insert_pos) {
     161                 :          0 :     helper->buffers =
     162                 :          0 :         g_slist_insert_before (helper->buffers, insert_pos, buffer);
     163                 :            :   } else {
     164                 :            :     /* if insert_pos is not set, our offset is bigger than the largest offset
     165                 :            :      * we have so far; since we keep the list sorted with highest offsets
     166                 :            :      * first, we need to prepend the buffer to the list */
     167                 :          0 :     helper->last_offset = GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer);
     168                 :          0 :     helper->buffers = g_slist_prepend (helper->buffers, buffer);
     169                 :            :   }
     170                 :          0 :   return GST_BUFFER_DATA (buffer);
     171                 :            : 
     172                 :            : error:
     173                 :            :   {
     174         [ #  # ]:          0 :     GST_INFO ("typefind function returned: %s", gst_flow_get_name (ret));
     175                 :          0 :     return NULL;
     176                 :            :   }
     177                 :            : }
     178                 :            : 
     179                 :            : /*
     180                 :            :  * helper_find_suggest:
     181                 :            :  * @data: helper data struct
     182                 :            :  * @probability: probability of the match
     183                 :            :  * @caps: caps of the type
     184                 :            :  *
     185                 :            :  * If given @probability is higher, replace previously store caps.
     186                 :            :  */
     187                 :            : static void
     188                 :          0 : helper_find_suggest (gpointer data, guint probability, const GstCaps * caps)
     189                 :            : {
     190                 :          0 :   GstTypeFindHelper *helper = (GstTypeFindHelper *) data;
     191                 :            : 
     192         [ #  # ]:          0 :   GST_LOG_OBJECT (helper->obj,
     193                 :            :       "'%s' called called suggest (%u, %" GST_PTR_FORMAT ")",
     194                 :            :       GST_PLUGIN_FEATURE_NAME (helper->factory), probability, caps);
     195                 :            : 
     196         [ #  # ]:          0 :   if (probability > helper->best_probability) {
     197                 :          0 :     GstCaps *copy = gst_caps_copy (caps);
     198                 :            : 
     199                 :          0 :     gst_caps_replace (&helper->caps, copy);
     200                 :          0 :     gst_caps_unref (copy);
     201                 :          0 :     helper->best_probability = probability;
     202                 :            :   }
     203                 :          0 : }
     204                 :            : 
     205                 :            : static guint64
     206                 :          0 : helper_find_get_length (gpointer data)
     207                 :            : {
     208                 :          0 :   GstTypeFindHelper *helper = (GstTypeFindHelper *) data;
     209                 :            : 
     210         [ #  # ]:          0 :   GST_LOG_OBJECT (helper->obj, "'%s' called called get_length, returning %"
     211                 :            :       G_GUINT64_FORMAT, GST_PLUGIN_FEATURE_NAME (helper->factory),
     212                 :            :       helper->size);
     213                 :            : 
     214                 :          0 :   return helper->size;
     215                 :            : }
     216                 :            : 
     217                 :            : /**
     218                 :            :  * gst_type_find_helper_get_range_ext:
     219                 :            :  * @obj: A #GstObject that will be passed as first argument to @func
     220                 :            :  * @func: (scope call): A generic #GstTypeFindHelperGetRangeFunction that will
     221                 :            :  *        be used to access data at random offsets when doing the typefinding
     222                 :            :  * @size: The length in bytes
     223                 :            :  * @extension: extension of the media
     224                 :            :  * @prob: (out) (allow-none): location to store the probability of the found
     225                 :            :  *     caps, or #NULL
     226                 :            :  *
     227                 :            :  * Utility function to do pull-based typefinding. Unlike gst_type_find_helper()
     228                 :            :  * however, this function will use the specified function @func to obtain the
     229                 :            :  * data needed by the typefind functions, rather than operating on a given
     230                 :            :  * source pad. This is useful mostly for elements like tag demuxers which
     231                 :            :  * strip off data at the beginning and/or end of a file and want to typefind
     232                 :            :  * the stripped data stream before adding their own source pad (the specified
     233                 :            :  * callback can then call the upstream peer pad with offsets adjusted for the
     234                 :            :  * tag size, for example).
     235                 :            :  *
     236                 :            :  * When @extension is not NULL, this function will first try the typefind
     237                 :            :  * functions for the given extension, which might speed up the typefinding
     238                 :            :  * in many cases.
     239                 :            :  *
     240                 :            :  * Free-function: gst_caps_unref
     241                 :            :  *
     242                 :            :  * Returns: (transfer full): the #GstCaps corresponding to the data stream.
     243                 :            :  *     Returns #NULL if no #GstCaps matches the data stream.
     244                 :            :  *
     245                 :            :  * Since: 0.10.26
     246                 :            :  */
     247                 :            : GstCaps *
     248                 :          0 : gst_type_find_helper_get_range_ext (GstObject * obj,
     249                 :            :     GstTypeFindHelperGetRangeFunction func, guint64 size,
     250                 :            :     const gchar * extension, GstTypeFindProbability * prob)
     251                 :            : {
     252                 :            :   GstTypeFindHelper helper;
     253                 :            :   GstTypeFind find;
     254                 :            :   GSList *walk;
     255                 :            :   GList *l, *type_list;
     256                 :          0 :   GstCaps *result = NULL;
     257                 :          0 :   gint pos = 0;
     258                 :            : 
     259 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_OBJECT (obj), NULL);
         [ #  # ][ #  # ]
     260         [ #  # ]:          0 :   g_return_val_if_fail (func != NULL, NULL);
     261                 :            : 
     262                 :          0 :   helper.buffers = NULL;
     263                 :          0 :   helper.size = size;
     264                 :          0 :   helper.last_offset = 0;
     265                 :          0 :   helper.func = func;
     266                 :          0 :   helper.best_probability = 0;
     267                 :          0 :   helper.caps = NULL;
     268                 :          0 :   helper.obj = obj;
     269                 :            : 
     270                 :          0 :   find.data = &helper;
     271                 :          0 :   find.peek = helper_find_peek;
     272                 :          0 :   find.suggest = helper_find_suggest;
     273                 :            : 
     274 [ #  # ][ #  # ]:          0 :   if (size == 0 || size == (guint64) - 1) {
     275                 :          0 :     find.get_length = NULL;
     276                 :            :   } else {
     277                 :          0 :     find.get_length = helper_find_get_length;
     278                 :            :   }
     279                 :            : 
     280                 :          0 :   type_list = gst_type_find_factory_get_list ();
     281                 :            : 
     282                 :            :   /* move the typefinders for the extension first in the list. The idea is that
     283                 :            :    * when one of them returns MAX we don't need to search further as there is a
     284                 :            :    * very high chance we got the right type. */
     285         [ #  # ]:          0 :   if (extension) {
     286                 :            :     GList *next;
     287                 :            : 
     288         [ #  # ]:          0 :     GST_LOG_OBJECT (obj, "sorting typefind for extension %s to head",
     289                 :            :         extension);
     290                 :            : 
     291         [ #  # ]:          0 :     for (l = type_list; l; l = next) {
     292                 :            :       GstTypeFindFactory *factory;
     293                 :            :       gint i;
     294                 :            :       gchar **ext;
     295                 :            : 
     296                 :          0 :       next = l->next;
     297                 :            : 
     298                 :          0 :       factory = GST_TYPE_FIND_FACTORY (l->data);
     299                 :            : 
     300                 :          0 :       ext = gst_type_find_factory_get_extensions (factory);
     301         [ #  # ]:          0 :       if (ext == NULL)
     302                 :          0 :         continue;
     303                 :            : 
     304         [ #  # ]:          0 :       GST_LOG_OBJECT (obj, "testing factory %s for extension %s",
     305                 :            :           GST_PLUGIN_FEATURE_NAME (factory), extension);
     306                 :            : 
     307         [ #  # ]:          0 :       for (i = 0; ext[i]; i++) {
     308         [ #  # ]:          0 :         if (strcmp (ext[i], extension) == 0) {
     309                 :            :           /* found extension, move in front */
     310         [ #  # ]:          0 :           GST_LOG_OBJECT (obj, "moving typefind for extension %s to head",
     311                 :            :               extension);
     312                 :            :           /* remove entry from list */
     313                 :          0 :           type_list = g_list_delete_link (type_list, l);
     314                 :            :           /* insert at the position */
     315                 :          0 :           type_list = g_list_insert (type_list, factory, pos);
     316                 :            :           /* next element will be inserted after this one */
     317                 :          0 :           pos++;
     318                 :          0 :           break;
     319                 :            :         }
     320                 :            :       }
     321                 :            :     }
     322                 :            :   }
     323                 :            : 
     324         [ #  # ]:          0 :   for (l = type_list; l; l = l->next) {
     325                 :          0 :     helper.factory = GST_TYPE_FIND_FACTORY (l->data);
     326                 :          0 :     gst_type_find_factory_call_function (helper.factory, &find);
     327         [ #  # ]:          0 :     if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM)
     328                 :          0 :       break;
     329                 :            :   }
     330                 :          0 :   gst_plugin_feature_list_free (type_list);
     331                 :            : 
     332         [ #  # ]:          0 :   for (walk = helper.buffers; walk; walk = walk->next)
     333                 :          0 :     gst_buffer_unref (GST_BUFFER_CAST (walk->data));
     334                 :          0 :   g_slist_free (helper.buffers);
     335                 :            : 
     336         [ #  # ]:          0 :   if (helper.best_probability > 0)
     337                 :          0 :     result = helper.caps;
     338                 :            : 
     339         [ #  # ]:          0 :   if (prob)
     340                 :          0 :     *prob = helper.best_probability;
     341                 :            : 
     342         [ #  # ]:          0 :   GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT " (probability = %u)",
     343                 :            :       result, (guint) helper.best_probability);
     344                 :            : 
     345                 :          0 :   return result;
     346                 :            : }
     347                 :            : 
     348                 :            : /**
     349                 :            :  * gst_type_find_helper_get_range:
     350                 :            :  * @obj: A #GstObject that will be passed as first argument to @func
     351                 :            :  * @func: (scope call): A generic #GstTypeFindHelperGetRangeFunction that will
     352                 :            :  *        be used to access data at random offsets when doing the typefinding
     353                 :            :  * @size: The length in bytes
     354                 :            :  * @prob: (out) (allow-none): location to store the probability of the found
     355                 :            :  *     caps, or #NULL
     356                 :            :  *
     357                 :            :  * Utility function to do pull-based typefinding. Unlike gst_type_find_helper()
     358                 :            :  * however, this function will use the specified function @func to obtain the
     359                 :            :  * data needed by the typefind functions, rather than operating on a given
     360                 :            :  * source pad. This is useful mostly for elements like tag demuxers which
     361                 :            :  * strip off data at the beginning and/or end of a file and want to typefind
     362                 :            :  * the stripped data stream before adding their own source pad (the specified
     363                 :            :  * callback can then call the upstream peer pad with offsets adjusted for the
     364                 :            :  * tag size, for example).
     365                 :            :  *
     366                 :            :  * Free-function: gst_caps_unref
     367                 :            :  *
     368                 :            :  * Returns: (transfer full): the #GstCaps corresponding to the data stream.
     369                 :            :  *     Returns #NULL if no #GstCaps matches the data stream.
     370                 :            :  */
     371                 :            : GstCaps *
     372                 :          0 : gst_type_find_helper_get_range (GstObject * obj,
     373                 :            :     GstTypeFindHelperGetRangeFunction func, guint64 size,
     374                 :            :     GstTypeFindProbability * prob)
     375                 :            : {
     376                 :          0 :   return gst_type_find_helper_get_range_ext (obj, func, size, NULL, prob);
     377                 :            : }
     378                 :            : 
     379                 :            : /**
     380                 :            :  * gst_type_find_helper:
     381                 :            :  * @src: A source #GstPad
     382                 :            :  * @size: The length in bytes
     383                 :            :  *
     384                 :            :  * Tries to find what type of data is flowing from the given source #GstPad.
     385                 :            :  *
     386                 :            :  * Free-function: gst_caps_unref
     387                 :            :  *
     388                 :            :  * Returns: (transfer full): the #GstCaps corresponding to the data stream.
     389                 :            :  *     Returns #NULL if no #GstCaps matches the data stream.
     390                 :            :  */
     391                 :            : 
     392                 :            : GstCaps *
     393                 :          0 : gst_type_find_helper (GstPad * src, guint64 size)
     394                 :            : {
     395                 :            :   GstTypeFindHelperGetRangeFunction func;
     396                 :            : 
     397 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_OBJECT (src), NULL);
         [ #  # ][ #  # ]
     398         [ #  # ]:          0 :   g_return_val_if_fail (GST_PAD_GETRANGEFUNC (src) != NULL, NULL);
     399                 :            : 
     400                 :          0 :   func = (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (src));
     401                 :            : 
     402                 :          0 :   return gst_type_find_helper_get_range (GST_OBJECT (src), func, size, NULL);
     403                 :            : }
     404                 :            : 
     405                 :            : /* ********************** typefinding for buffers ************************* */
     406                 :            : 
     407                 :            : typedef struct
     408                 :            : {
     409                 :            :   guint8 *data;                 /* buffer data */
     410                 :            :   guint size;
     411                 :            :   guint best_probability;
     412                 :            :   GstCaps *caps;
     413                 :            :   GstTypeFindFactory *factory;  /* for logging */
     414                 :            :   GstObject *obj;               /* for logging */
     415                 :            : } GstTypeFindBufHelper;
     416                 :            : 
     417                 :            : /*
     418                 :            :  * buf_helper_find_peek:
     419                 :            :  * @data: helper data struct
     420                 :            :  * @off: stream offset
     421                 :            :  * @size: block size
     422                 :            :  *
     423                 :            :  * Get data pointer within a buffer.
     424                 :            :  *
     425                 :            :  * Returns: address inside the buffer or %NULL if buffer does not cover the
     426                 :            :  * requested range.
     427                 :            :  */
     428                 :            : static guint8 *
     429                 :         11 : buf_helper_find_peek (gpointer data, gint64 off, guint size)
     430                 :            : {
     431                 :            :   GstTypeFindBufHelper *helper;
     432                 :            : 
     433                 :         11 :   helper = (GstTypeFindBufHelper *) data;
     434         [ -  + ]:         11 :   GST_LOG_OBJECT (helper->obj, "'%s' called peek (%" G_GINT64_FORMAT ", %u)",
     435                 :            :       GST_PLUGIN_FEATURE_NAME (helper->factory), off, size);
     436                 :            : 
     437         [ +  + ]:         11 :   if (size == 0)
     438                 :          1 :     return NULL;
     439                 :            : 
     440         [ +  + ]:         10 :   if (off < 0) {
     441         [ -  + ]:          2 :     GST_LOG_OBJECT (helper->obj, "'%s' wanted to peek at end; not supported",
     442                 :            :         GST_PLUGIN_FEATURE_NAME (helper->factory));
     443                 :          2 :     return NULL;
     444                 :            :   }
     445                 :            : 
     446         [ +  + ]:          8 :   if ((off + size) <= helper->size)
     447                 :          5 :     return helper->data + off;
     448                 :            : 
     449                 :         11 :   return NULL;
     450                 :            : }
     451                 :            : 
     452                 :            : /*
     453                 :            :  * buf_helper_find_suggest:
     454                 :            :  * @data: helper data struct
     455                 :            :  * @probability: probability of the match
     456                 :            :  * @caps: caps of the type
     457                 :            :  *
     458                 :            :  * If given @probability is higher, replace previously store caps.
     459                 :            :  */
     460                 :            : static void
     461                 :          1 : buf_helper_find_suggest (gpointer data, guint probability, const GstCaps * caps)
     462                 :            : {
     463                 :          1 :   GstTypeFindBufHelper *helper = (GstTypeFindBufHelper *) data;
     464                 :            : 
     465         [ -  + ]:          1 :   GST_LOG_OBJECT (helper->obj,
     466                 :            :       "'%s' called called suggest (%u, %" GST_PTR_FORMAT ")",
     467                 :            :       GST_PLUGIN_FEATURE_NAME (helper->factory), probability, caps);
     468                 :            : 
     469                 :            :   /* Note: not >= as we call typefinders in order of rank, highest first */
     470         [ +  - ]:          1 :   if (probability > helper->best_probability) {
     471                 :          1 :     GstCaps *copy = gst_caps_copy (caps);
     472                 :            : 
     473                 :          1 :     gst_caps_replace (&helper->caps, copy);
     474                 :          1 :     gst_caps_unref (copy);
     475                 :          1 :     helper->best_probability = probability;
     476                 :            :   }
     477                 :          1 : }
     478                 :            : 
     479                 :            : /**
     480                 :            :  * gst_type_find_helper_for_buffer:
     481                 :            :  * @obj: object doing the typefinding, or NULL (used for logging)
     482                 :            :  * @buf: (in) (transfer none): a #GstBuffer with data to typefind
     483                 :            :  * @prob: (out) (allow-none): location to store the probability of the found
     484                 :            :  *     caps, or #NULL
     485                 :            :  *
     486                 :            :  * Tries to find what type of data is contained in the given #GstBuffer, the
     487                 :            :  * assumption being that the buffer represents the beginning of the stream or
     488                 :            :  * file.
     489                 :            :  *
     490                 :            :  * All available typefinders will be called on the data in order of rank. If
     491                 :            :  * a typefinding function returns a probability of #GST_TYPE_FIND_MAXIMUM,
     492                 :            :  * typefinding is stopped immediately and the found caps will be returned
     493                 :            :  * right away. Otherwise, all available typefind functions will the tried,
     494                 :            :  * and the caps with the highest probability will be returned, or #NULL if
     495                 :            :  * the content of the buffer could not be identified.
     496                 :            :  *
     497                 :            :  * Free-function: gst_caps_unref
     498                 :            :  *
     499                 :            :  * Returns: (transfer full): the #GstCaps corresponding to the data, or #NULL
     500                 :            :  *     if no type could be found. The caller should free the caps returned
     501                 :            :  *     with gst_caps_unref().
     502                 :            :  */
     503                 :            : GstCaps *
     504                 :          1 : gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf,
     505                 :            :     GstTypeFindProbability * prob)
     506                 :            : {
     507                 :            :   GstTypeFindBufHelper helper;
     508                 :            :   GstTypeFind find;
     509                 :            :   GList *l, *type_list;
     510                 :          1 :   GstCaps *result = NULL;
     511                 :            : 
     512         [ -  + ]:          1 :   g_return_val_if_fail (buf != NULL, NULL);
     513 [ -  + ][ +  - ]:          1 :   g_return_val_if_fail (GST_IS_BUFFER (buf), NULL);
         [ +  - ][ -  + ]
     514 [ +  - ][ -  + ]:          1 :   g_return_val_if_fail (GST_BUFFER_OFFSET (buf) == 0 ||
     515                 :            :       GST_BUFFER_OFFSET (buf) == GST_BUFFER_OFFSET_NONE, NULL);
     516                 :            : 
     517                 :          1 :   helper.data = GST_BUFFER_DATA (buf);
     518                 :          1 :   helper.size = GST_BUFFER_SIZE (buf);
     519                 :          1 :   helper.best_probability = 0;
     520                 :          1 :   helper.caps = NULL;
     521                 :          1 :   helper.obj = obj;
     522                 :            : 
     523 [ +  - ][ -  + ]:          1 :   if (helper.data == NULL || helper.size == 0)
     524                 :          0 :     return NULL;
     525                 :            : 
     526                 :          1 :   find.data = &helper;
     527                 :          1 :   find.peek = buf_helper_find_peek;
     528                 :          1 :   find.suggest = buf_helper_find_suggest;
     529                 :          1 :   find.get_length = NULL;
     530                 :            : 
     531                 :          1 :   type_list = gst_type_find_factory_get_list ();
     532                 :            : 
     533         [ +  - ]:          1 :   for (l = type_list; l; l = l->next) {
     534                 :          1 :     helper.factory = GST_TYPE_FIND_FACTORY (l->data);
     535                 :          1 :     gst_type_find_factory_call_function (helper.factory, &find);
     536         [ +  - ]:          1 :     if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM)
     537                 :          1 :       break;
     538                 :            :   }
     539                 :          1 :   gst_plugin_feature_list_free (type_list);
     540                 :            : 
     541         [ +  - ]:          1 :   if (helper.best_probability > 0)
     542                 :          1 :     result = helper.caps;
     543                 :            : 
     544         [ -  + ]:          1 :   if (prob)
     545                 :          0 :     *prob = helper.best_probability;
     546                 :            : 
     547         [ -  + ]:          1 :   GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT " (probability = %u)",
     548                 :            :       result, (guint) helper.best_probability);
     549                 :            : 
     550                 :          1 :   return result;
     551                 :            : }
     552                 :            : 
     553                 :            : /**
     554                 :            :  * gst_type_find_helper_for_extension:
     555                 :            :  * @obj: (allow-none): object doing the typefinding, or NULL (used for logging)
     556                 :            :  * @extension: an extension
     557                 :            :  *
     558                 :            :  * Tries to find the best #GstCaps associated with @extension.
     559                 :            :  *
     560                 :            :  * All available typefinders will be checked against the extension in order
     561                 :            :  * of rank. The caps of the first typefinder that can handle @extension will be
     562                 :            :  * returned.
     563                 :            :  *
     564                 :            :  * Free-function: gst_caps_unref
     565                 :            :  *
     566                 :            :  * Returns: (transfer full): the #GstCaps corresponding to @extension, or
     567                 :            :  *     #NULL if no type could be found. The caller should free the caps
     568                 :            :  *     returned with gst_caps_unref().
     569                 :            :  * 
     570                 :            :  * Since: 0.10.23
     571                 :            :  */
     572                 :            : GstCaps *
     573                 :          0 : gst_type_find_helper_for_extension (GstObject * obj, const gchar * extension)
     574                 :            : {
     575                 :            :   GList *l, *type_list;
     576                 :          0 :   GstCaps *result = NULL;
     577                 :            : 
     578         [ #  # ]:          0 :   g_return_val_if_fail (extension != NULL, NULL);
     579                 :            : 
     580         [ #  # ]:          0 :   GST_LOG_OBJECT (obj, "finding caps for extension %s", extension);
     581                 :            : 
     582                 :          0 :   type_list = gst_type_find_factory_get_list ();
     583                 :            : 
     584 [ #  # ][ #  # ]:          0 :   for (l = type_list; l; l = g_list_next (l)) {
     585                 :            :     GstTypeFindFactory *factory;
     586                 :            :     gchar **ext;
     587                 :            :     gint i;
     588                 :            : 
     589                 :          0 :     factory = GST_TYPE_FIND_FACTORY (l->data);
     590                 :            : 
     591                 :            :     /* we only want to check those factories without a function */
     592         [ #  # ]:          0 :     if (factory->function != NULL)
     593                 :          0 :       continue;
     594                 :            : 
     595                 :            :     /* get the extension that this typefind factory can handle */
     596                 :          0 :     ext = gst_type_find_factory_get_extensions (factory);
     597         [ #  # ]:          0 :     if (ext == NULL)
     598                 :          0 :       continue;
     599                 :            : 
     600                 :            :     /* there are extension, see if one of them matches the requested
     601                 :            :      * extension */
     602         [ #  # ]:          0 :     for (i = 0; ext[i]; i++) {
     603         [ #  # ]:          0 :       if (strcmp (ext[i], extension) == 0) {
     604                 :            :         /* we found a matching extension, take the caps */
     605         [ #  # ]:          0 :         if ((result = gst_type_find_factory_get_caps (factory))) {
     606                 :          0 :           gst_caps_ref (result);
     607                 :          0 :           goto done;
     608                 :            :         }
     609                 :            :       }
     610                 :            :     }
     611                 :            :   }
     612                 :            : done:
     613                 :          0 :   gst_plugin_feature_list_free (type_list);
     614                 :            : 
     615         [ #  # ]:          0 :   GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT, result);
     616                 :            : 
     617                 :          0 :   return result;
     618                 :            : }

Generated by: LCOV version 1.9