LCOV - code coverage report
Current view: top level - plugins/indexers - gstfileindex.c (source / functions) Hit Total Coverage
Test: GStreamer 0.10.32.1 Lines: 10 412 2.4 %
Date: 2011-03-25 Functions: 2 23 8.7 %
Branches: 3 273 1.1 %

           Branch data     Line data    Source code
       1                 :            : /* GStreamer
       2                 :            :  * Copyright (C) 2003 Erik Walthinsen <omega@cse.ogi.edu>
       3                 :            :  *               2003 Joshua N Pritikin <jpritikin@pobox.com>
       4                 :            :  *
       5                 :            :  * This library is free software; you can redistribute it and/or
       6                 :            :  * modify it under the terms of the GNU Library General Public
       7                 :            :  * License as published by the Free Software Foundation; either
       8                 :            :  * version 2 of the License, or (at your option) any later version.
       9                 :            :  *
      10                 :            :  * This library is distributed in the hope that it will be useful,
      11                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13                 :            :  * Library General Public License for more details.
      14                 :            :  *
      15                 :            :  * You should have received a copy of the GNU Library General Public
      16                 :            :  * License along with this library; if not, write to the
      17                 :            :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      18                 :            :  * Boston, MA 02111-1307, USA.
      19                 :            :  */
      20                 :            : 
      21                 :            : #include <gst/gst.h>
      22                 :            : 
      23                 :            : #include <unistd.h>
      24                 :            : #include <sys/mman.h>
      25                 :            : #include <sys/stat.h>
      26                 :            : #include <errno.h>
      27                 :            : #include <fcntl.h>
      28                 :            : #include <string.h>
      29                 :            : 
      30                 :            : #ifdef GST_DISABLE_DEPRECATED
      31                 :            : #include <libxml/parser.h>
      32                 :            : #endif
      33                 :            : 
      34                 :            : #include "gstindexers.h"
      35                 :            : 
      36                 :            : #define GST_TYPE_FILE_INDEX             \
      37                 :            :   (gst_file_index_get_type ())
      38                 :            : #define GST_FILE_INDEX(obj)             \
      39                 :            :   (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_FILE_INDEX, GstFileIndex))
      40                 :            : #define GST_FILE_INDEX_CLASS(klass)     \
      41                 :            :   (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_FILE_INDEX, GstFileIndexClass))
      42                 :            : #define GST_IS_FILE_INDEX(obj)          \
      43                 :            :   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_FILE_INDEX))
      44                 :            : #define GST_IS_FILE_INDEX_CLASS(klass)    \
      45                 :            :   (GST_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_FILE_INDEX))
      46                 :            : 
      47                 :            : /*
      48                 :            :  * Object model:
      49                 :            :  *
      50                 :            :  * We build an index to each entry for each id.
      51                 :            :  *
      52                 :            :  *
      53                 :            :  *  fileindex
      54                 :            :  *    -----------------------------...
      55                 :            :  *    !                  !
      56                 :            :  *   id1                 id2
      57                 :            :  *    !
      58                 :            :  *   GArray
      59                 :            :  *
      60                 :            :  * The fileindex creates a FileIndexId object for each writer id, a
      61                 :            :  * Hashtable is kept to map the id to the FileIndexId
      62                 :            :  *
      63                 :            :  * The FileIndexId also keeps all the values in a sorted GArray.
      64                 :            :  *
      65                 :            :  * Finding a value for an id/format requires locating the correct GArray,
      66                 :            :  * then do a binary search to get the required value.
      67                 :            :  *
      68                 :            :  * Unlike gstmemindex:  All formats are assumed to sort to the
      69                 :            :  * same order.  All formats are assumed to be available from
      70                 :            :  * any entry.
      71                 :            :  */
      72                 :            : 
      73                 :            : /*
      74                 :            :  * Each array element is (32bits flags, nformats * 64bits)
      75                 :            :  */
      76                 :            : typedef struct
      77                 :            : {
      78                 :            :   gint id;
      79                 :            :   gchar *id_desc;
      80                 :            :   gint nformats;
      81                 :            :   GstFormat *format;
      82                 :            :   GArray *array;
      83                 :            : }
      84                 :            : GstFileIndexId;
      85                 :            : 
      86                 :            : typedef struct _GstFileIndex GstFileIndex;
      87                 :            : typedef struct _GstFileIndexClass GstFileIndexClass;
      88                 :            : 
      89                 :            : #define ARRAY_ROW_SIZE(_ii) \
      90                 :            :   (sizeof (gint32) + (_ii)->nformats * sizeof (gint64))
      91                 :            : #define ARRAY_TOTAL_SIZE(_ii) \
      92                 :            :   (_ii->array->len * ARRAY_ROW_SIZE(_ii))
      93                 :            : 
      94                 :            : /* don't forget to convert to/from BE byte-order */
      95                 :            : #define ARRAY_ROW_FLAGS(_row) \
      96                 :            :   (*((gint32*) (_row)))
      97                 :            : #define ARRAY_ROW_VALUE(_row,_vx) \
      98                 :            :   (*(gint64*) (((gchar*)(_row)) + sizeof (gint32) + (_vx) * sizeof (gint64)))
      99                 :            : 
     100                 :            : GST_DEBUG_CATEGORY_STATIC (DC);
     101                 :            : #define GST_CAT_DEFAULT DC
     102                 :            : 
     103                 :            : struct _GstFileIndex
     104                 :            : {
     105                 :            :   GstIndex parent;
     106                 :            : 
     107                 :            :   gchar *location;
     108                 :            :   gboolean is_loaded;
     109                 :            :   GSList *unresolved;
     110                 :            :   gint next_id;
     111                 :            :   GHashTable *id_index;
     112                 :            : 
     113                 :            :   GstIndexEntry *ret_entry;     /* hack to avoid leaking memory */
     114                 :            : };
     115                 :            : 
     116                 :            : struct _GstFileIndexClass
     117                 :            : {
     118                 :            :   GstIndexClass parent_class;
     119                 :            : };
     120                 :            : 
     121                 :            : enum
     122                 :            : {
     123                 :            :   ARG_0,
     124                 :            :   ARG_LOCATION,
     125                 :            : };
     126                 :            : 
     127                 :            : static void gst_file_index_dispose (GObject * object);
     128                 :            : 
     129                 :            : static void
     130                 :            : gst_file_index_set_property (GObject * object,
     131                 :            :     guint prop_id, const GValue * value, GParamSpec * pspec);
     132                 :            : static void
     133                 :            : gst_file_index_get_property (GObject * object,
     134                 :            :     guint prop_id, GValue * value, GParamSpec * pspec);
     135                 :            : 
     136                 :            : static gboolean
     137                 :            : gst_file_index_get_writer_id (GstIndex * _index, gint * id,
     138                 :            :     gchar * writer_string);
     139                 :            : 
     140                 :            : static void gst_file_index_commit (GstIndex * index, gint writer_id);
     141                 :            : static void gst_file_index_add_entry (GstIndex * index, GstIndexEntry * entry);
     142                 :            : static GstIndexEntry *gst_file_index_get_assoc_entry (GstIndex * index, gint id,
     143                 :            :     GstIndexLookupMethod method,
     144                 :            :     GstAssocFlags flags,
     145                 :            :     GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data);
     146                 :            : 
     147                 :            : #define CLASS(file_index)  GST_FILE_INDEX_CLASS (G_OBJECT_GET_CLASS (file_index))
     148                 :            : 
     149                 :            : GType gst_file_index_get_type (void);
     150                 :            : 
     151         [ +  - ]:          4 : G_DEFINE_TYPE (GstFileIndex, gst_file_index, GST_TYPE_INDEX);
     152                 :            : 
     153                 :            : static void
     154                 :          0 : gst_file_index_class_init (GstFileIndexClass * klass)
     155                 :            : {
     156                 :            :   GObjectClass *gobject_class;
     157                 :            :   GstIndexClass *gstindex_class;
     158                 :            : 
     159                 :          0 :   gobject_class = (GObjectClass *) klass;
     160                 :          0 :   gstindex_class = (GstIndexClass *) klass;
     161                 :            : 
     162                 :          0 :   gobject_class->dispose = gst_file_index_dispose;
     163                 :          0 :   gobject_class->set_property = gst_file_index_set_property;
     164                 :          0 :   gobject_class->get_property = gst_file_index_get_property;
     165                 :            : 
     166                 :          0 :   gstindex_class->add_entry = gst_file_index_add_entry;
     167                 :          0 :   gstindex_class->get_assoc_entry = gst_file_index_get_assoc_entry;
     168                 :          0 :   gstindex_class->commit = gst_file_index_commit;
     169                 :          0 :   gstindex_class->get_writer_id = gst_file_index_get_writer_id;
     170                 :            : 
     171                 :          0 :   g_object_class_install_property (gobject_class, ARG_LOCATION,
     172                 :            :       g_param_spec_string ("location", "File Location",
     173                 :            :           "Location of the index file", NULL,
     174                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     175                 :          0 : }
     176                 :            : 
     177                 :            : static void
     178                 :          0 : gst_file_index_init (GstFileIndex * index)
     179                 :            : {
     180         [ #  # ]:          0 :   GST_DEBUG ("created new file index");
     181                 :            : 
     182                 :          0 :   index->id_index = g_hash_table_new (g_int_hash, g_int_equal);
     183                 :          0 : }
     184                 :            : 
     185                 :            : static void
     186                 :          0 : _file_index_id_free (GstFileIndexId * index_id, gboolean is_mmapped)
     187                 :            : {
     188         [ #  # ]:          0 :   if (index_id->id_desc)
     189                 :          0 :     g_free (index_id->id_desc);
     190         [ #  # ]:          0 :   if (index_id->format)
     191                 :          0 :     g_free (index_id->format);
     192         [ #  # ]:          0 :   if (index_id->array) {
     193         [ #  # ]:          0 :     if (is_mmapped)
     194                 :          0 :       munmap (index_id->array->data, ARRAY_TOTAL_SIZE (index_id));
     195                 :          0 :     g_array_free (index_id->array, !is_mmapped);
     196                 :            :   }
     197                 :          0 :   g_slice_free (GstFileIndexId, index_id);
     198                 :          0 : }
     199                 :            : 
     200                 :            : static gboolean
     201                 :          0 : _id_index_free_helper (gpointer _key, GstFileIndexId * index_id,
     202                 :            :     GstFileIndex * index)
     203                 :            : {
     204                 :          0 :   _file_index_id_free (index_id, index->is_loaded);
     205                 :          0 :   return TRUE;
     206                 :            : }
     207                 :            : 
     208                 :            : static void
     209                 :          0 : gst_file_index_dispose (GObject * object)
     210                 :            : {
     211                 :          0 :   GstFileIndex *index = GST_FILE_INDEX (object);
     212                 :            : 
     213         [ #  # ]:          0 :   if (index->location) {
     214                 :          0 :     g_free (index->location);
     215                 :          0 :     index->location = NULL;
     216                 :            :   }
     217                 :            : 
     218                 :            :   {
     219                 :            :     GSList *elem;
     220                 :            : 
     221 [ #  # ][ #  # ]:          0 :     for (elem = index->unresolved; elem; elem = g_slist_next (elem))
     222                 :          0 :       _file_index_id_free (elem->data, index->is_loaded);
     223                 :          0 :     g_slist_free (index->unresolved);
     224                 :          0 :     index->unresolved = NULL;
     225                 :            :   }
     226                 :            : 
     227                 :          0 :   g_hash_table_foreach_steal (index->id_index,
     228                 :            :       (GHRFunc) _id_index_free_helper, index);
     229                 :          0 :   g_hash_table_destroy (index->id_index);
     230                 :          0 :   index->id_index = NULL;
     231                 :            : 
     232                 :          0 :   gst_index_entry_free (index->ret_entry);      /* hack */
     233                 :            : 
     234                 :          0 :   G_OBJECT_CLASS (gst_file_index_parent_class)->dispose (object);
     235                 :          0 : }
     236                 :            : 
     237                 :            : struct fi_find_writer_context
     238                 :            : {
     239                 :            :   const gchar *writer_string;
     240                 :            :   GstFileIndexId *ii;
     241                 :            : };
     242                 :            : 
     243                 :            : static void
     244                 :          0 : _fi_find_writer (gpointer key, gpointer val, gpointer data)
     245                 :            : {
     246                 :          0 :   struct fi_find_writer_context *cx = data;
     247                 :          0 :   GstFileIndexId *ii = val;
     248                 :            : 
     249         [ #  # ]:          0 :   if (strcmp (ii->id_desc, cx->writer_string) == 0)
     250                 :          0 :     cx->ii = ii;
     251                 :          0 : }
     252                 :            : 
     253                 :            : static gboolean
     254                 :          0 : gst_file_index_get_writer_id (GstIndex * _index,
     255                 :            :     gint * id, gchar * writer_string)
     256                 :            : {
     257                 :          0 :   GstFileIndex *index = GST_FILE_INDEX (_index);
     258                 :          0 :   GSList *pending = index->unresolved;
     259                 :          0 :   gboolean match = FALSE;
     260                 :            :   GSList *elem;
     261                 :            : 
     262         [ #  # ]:          0 :   if (!index->is_loaded)
     263                 :          0 :     return FALSE;
     264                 :            : 
     265         [ #  # ]:          0 :   g_return_val_if_fail (id, FALSE);
     266         [ #  # ]:          0 :   g_return_val_if_fail (writer_string, FALSE);
     267                 :            : 
     268                 :          0 :   index->unresolved = NULL;
     269                 :            : 
     270 [ #  # ][ #  # ]:          0 :   for (elem = pending; elem; elem = g_slist_next (elem)) {
     271                 :          0 :     GstFileIndexId *ii = elem->data;
     272                 :            : 
     273         [ #  # ]:          0 :     if (strcmp (ii->id_desc, writer_string) != 0) {
     274                 :          0 :       index->unresolved = g_slist_prepend (index->unresolved, ii);
     275                 :          0 :       continue;
     276                 :            :     }
     277                 :            : 
     278         [ #  # ]:          0 :     if (match) {
     279         [ #  # ]:          0 :       GST_WARNING_OBJECT (index, "Duplicate matches for writer '%s'",
     280                 :            :           writer_string);
     281                 :          0 :       continue;
     282                 :            :     }
     283                 :            : 
     284                 :          0 :     ii->id = *id = ++index->next_id;
     285                 :          0 :     g_hash_table_insert (index->id_index, &ii->id, ii);
     286                 :          0 :     match = TRUE;
     287                 :            :   }
     288                 :            : 
     289                 :          0 :   g_slist_free (pending);
     290                 :            : 
     291         [ #  # ]:          0 :   if (!match) {
     292                 :            :     struct fi_find_writer_context cx;
     293                 :            : 
     294                 :          0 :     cx.writer_string = writer_string;
     295                 :          0 :     cx.ii = NULL;
     296                 :          0 :     g_hash_table_foreach (index->id_index, _fi_find_writer, &cx);
     297                 :            : 
     298         [ #  # ]:          0 :     if (cx.ii) {
     299                 :          0 :       match = TRUE;
     300         [ #  # ]:          0 :       GST_DEBUG_OBJECT (index, "Resolved writer '%s' again", writer_string);
     301                 :            :     } else
     302         [ #  # ]:          0 :       GST_WARNING_OBJECT (index, "Can't resolve writer '%s'", writer_string);
     303                 :            :   }
     304                 :            : 
     305                 :          0 :   return match;
     306                 :            : }
     307                 :            : 
     308                 :            : static void
     309                 :          0 : _fc_alloc_array (GstFileIndexId * id_index)
     310                 :            : {
     311         [ #  # ]:          0 :   g_assert (!id_index->array);
     312                 :          0 :   id_index->array =
     313                 :          0 :       g_array_sized_new (FALSE, FALSE, ARRAY_ROW_SIZE (id_index), 0);
     314                 :          0 : }
     315                 :            : 
     316                 :            : static void
     317                 :          0 : gst_file_index_load (GstFileIndex * index)
     318                 :            : {
     319                 :            :   xmlDocPtr doc;
     320                 :            :   xmlNodePtr root, part;
     321                 :            :   xmlChar *val;
     322                 :            : 
     323         [ #  # ]:          0 :   g_assert (index->location);
     324         [ #  # ]:          0 :   g_return_if_fail (!index->is_loaded);
     325                 :            : 
     326                 :            :   {
     327                 :          0 :     gchar *path = g_strdup_printf ("%s/gstindex.xml", index->location);
     328                 :          0 :     GError *err = NULL;
     329                 :            :     gchar *buf;
     330                 :            :     gsize len;
     331                 :            : 
     332                 :          0 :     g_file_get_contents (path, &buf, &len, &err);
     333                 :          0 :     g_free (path);
     334         [ #  # ]:          0 :     if (err) {
     335         [ #  # ]:          0 :       GST_ERROR_OBJECT (index, "%s", err->message);
     336                 :          0 :       return;
     337                 :            :     }
     338                 :            : 
     339                 :          0 :     doc = xmlParseMemory (buf, len);
     340                 :          0 :     g_free (buf);
     341                 :            :   }
     342                 :            : 
     343                 :            :   //xmlDocFormatDump (stderr, doc, TRUE);
     344                 :            : 
     345                 :          0 :   root = doc->xmlRootNode;
     346         [ #  # ]:          0 :   if (strcmp ((char *) root->name, "gstfileindex") != 0) {
     347         [ #  # ]:          0 :     GST_ERROR_OBJECT (index, "root node isn't a gstfileindex");
     348                 :          0 :     return;
     349                 :            :   }
     350                 :            : 
     351                 :          0 :   val = xmlGetProp (root, (xmlChar *) "version");
     352 [ #  # ][ #  # ]:          0 :   if (!val || atoi ((char *) val) != 1) {
     353         [ #  # ]:          0 :     GST_ERROR_OBJECT (index, "version != 1");
     354                 :          0 :     return;
     355                 :            :   }
     356                 :          0 :   free (val);
     357                 :            : 
     358         [ #  # ]:          0 :   for (part = root->children; part; part = part->next) {
     359         [ #  # ]:          0 :     if (strcmp ((char *) part->name, "writers") == 0) {
     360                 :            :       xmlNodePtr writer;
     361                 :            : 
     362         [ #  # ]:          0 :       for (writer = part->children; writer; writer = writer->next) {
     363                 :          0 :         xmlChar *datafile = xmlGetProp (writer, (xmlChar *) "datafile");
     364                 :          0 :         gchar *path = g_strdup_printf ("%s/%s", index->location, datafile);
     365                 :            :         int fd;
     366                 :            :         GstFileIndexId *id_index;
     367                 :            :         xmlNodePtr wpart;
     368                 :            :         xmlChar *entries_str;
     369                 :            :         gpointer array_data;
     370                 :            : 
     371                 :          0 :         free (datafile);
     372                 :            : 
     373                 :          0 :         fd = open (path, O_RDONLY);
     374                 :          0 :         g_free (path);
     375         [ #  # ]:          0 :         if (fd < 0) {
     376         [ #  # ]:          0 :           GST_ERROR_OBJECT (index,
     377                 :            :               "Can't open '%s': %s", path, g_strerror (errno));
     378                 :          0 :           continue;
     379                 :            :         }
     380                 :            : 
     381                 :          0 :         id_index = g_slice_new0 (GstFileIndexId);
     382                 :          0 :         id_index->id_desc = (char *) xmlGetProp (writer, (xmlChar *) "id");
     383                 :            : 
     384         [ #  # ]:          0 :         for (wpart = writer->children; wpart; wpart = wpart->next) {
     385         [ #  # ]:          0 :           if (strcmp ((char *) wpart->name, "formats") == 0) {
     386                 :          0 :             xmlChar *count_str = xmlGetProp (wpart, (xmlChar *) "count");
     387                 :          0 :             gint fx = 0;
     388                 :            :             xmlNodePtr format;
     389                 :            : 
     390                 :          0 :             id_index->nformats = atoi ((char *) count_str);
     391                 :          0 :             free (count_str);
     392                 :            : 
     393                 :          0 :             id_index->format = g_new (GstFormat, id_index->nformats);
     394                 :            : 
     395         [ #  # ]:          0 :             for (format = wpart->children; format; format = format->next) {
     396                 :          0 :               xmlChar *nick = xmlGetProp (format, (xmlChar *) "nick");
     397                 :          0 :               GstFormat fmt = gst_format_get_by_nick ((gchar *) nick);
     398                 :            : 
     399         [ #  # ]:          0 :               if (fmt == GST_FORMAT_UNDEFINED)
     400         [ #  # ]:          0 :                 GST_ERROR_OBJECT (index, "format '%s' undefined", nick);
     401         [ #  # ]:          0 :               g_assert (fx < id_index->nformats);
     402                 :          0 :               id_index->format[fx++] = fmt;
     403                 :          0 :               free (nick);
     404                 :            :             }
     405                 :            :           } else
     406         [ #  # ]:          0 :             GST_INFO_OBJECT (index, "unknown wpart '%s'", wpart->name);
     407                 :            :         }
     408                 :            : 
     409         [ #  # ]:          0 :         g_assert (id_index->nformats > 0);
     410                 :          0 :         _fc_alloc_array (id_index);
     411         [ #  # ]:          0 :         g_assert (id_index->array->data == NULL);       /* little bit risky */
     412                 :            : 
     413                 :          0 :         entries_str = xmlGetProp (writer, (xmlChar *) "entries");
     414                 :          0 :         id_index->array->len = atoi ((char *) entries_str);
     415                 :          0 :         free (entries_str);
     416                 :            : 
     417                 :          0 :         array_data =
     418                 :          0 :             mmap (NULL, ARRAY_TOTAL_SIZE (id_index), PROT_READ, MAP_SHARED, fd,
     419                 :            :             0);
     420                 :          0 :         close (fd);
     421         [ #  # ]:          0 :         if (array_data == MAP_FAILED) {
     422         [ #  # ]:          0 :           GST_ERROR_OBJECT (index,
     423                 :            :               "mmap %s failed: %s", path, g_strerror (errno));
     424                 :          0 :           continue;
     425                 :            :         }
     426                 :            : 
     427                 :          0 :         id_index->array->data = array_data;
     428                 :            : 
     429                 :          0 :         index->unresolved = g_slist_prepend (index->unresolved, id_index);
     430                 :            :       }
     431                 :            :     } else
     432         [ #  # ]:          0 :       GST_INFO_OBJECT (index, "unknown part '%s'", part->name);
     433                 :            :   }
     434                 :            : 
     435                 :          0 :   xmlFreeDoc (doc);
     436                 :            : 
     437                 :          0 :   GST_OBJECT_FLAG_UNSET (index, GST_INDEX_WRITABLE);
     438                 :          0 :   index->is_loaded = TRUE;
     439         [ #  # ]:          0 :   GST_LOG_OBJECT (index, "index %s loaded OK", index->location);
     440                 :            : }
     441                 :            : 
     442                 :            : static void
     443                 :          0 : gst_file_index_set_property (GObject * object,
     444                 :            :     guint prop_id, const GValue * value, GParamSpec * pspec)
     445                 :            : {
     446                 :          0 :   GstFileIndex *index = GST_FILE_INDEX (object);
     447                 :            : 
     448         [ #  # ]:          0 :   switch (prop_id) {
     449                 :            :     case ARG_LOCATION:
     450         [ #  # ]:          0 :       if (index->location)
     451                 :          0 :         g_free (index->location);
     452                 :          0 :       index->location = g_value_dup_string (value);
     453                 :            : 
     454 [ #  # ][ #  # ]:          0 :       if (index->location && !g_hash_table_size (index->id_index))
     455                 :          0 :         gst_file_index_load (index);
     456                 :          0 :       break;
     457                 :            :   }
     458                 :          0 : }
     459                 :            : 
     460                 :            : static void
     461                 :          0 : gst_file_index_get_property (GObject * object,
     462                 :            :     guint prop_id, GValue * value, GParamSpec * pspec)
     463                 :            : {
     464                 :          0 :   GstFileIndex *index = GST_FILE_INDEX (object);
     465                 :            : 
     466         [ #  # ]:          0 :   switch (prop_id) {
     467                 :            :     case ARG_LOCATION:
     468                 :          0 :       g_value_set_string (value, index->location);
     469                 :          0 :       break;
     470                 :            :   }
     471                 :          0 : }
     472                 :            : 
     473                 :            : static void
     474                 :          0 : _file_index_id_save_xml (gpointer _key, GstFileIndexId * ii, xmlNodePtr writers)
     475                 :            : {
     476                 :          0 :   const gint bufsize = 16;
     477                 :            :   gchar buf[16];
     478                 :            :   xmlNodePtr writer;
     479                 :            :   xmlNodePtr formats;
     480                 :            :   gint xx;
     481                 :            : 
     482         [ #  # ]:          0 :   if (!ii->array) {
     483         [ #  # ]:          0 :     GST_INFO ("Index for %s is empty", ii->id_desc);
     484                 :          0 :     return;
     485                 :            :   }
     486                 :            : 
     487                 :          0 :   writer = xmlNewChild (writers, NULL, (xmlChar *) "writer", NULL);
     488                 :          0 :   xmlSetProp (writer, (xmlChar *) "id", (xmlChar *) ii->id_desc);
     489                 :          0 :   g_snprintf (buf, bufsize, "%d", ii->array->len);
     490                 :          0 :   xmlSetProp (writer, (xmlChar *) "entries", (xmlChar *) buf);
     491                 :          0 :   g_snprintf (buf, bufsize, "%d", ii->id);      /* any unique number is OK */
     492                 :          0 :   xmlSetProp (writer, (xmlChar *) "datafile", (xmlChar *) buf);
     493                 :            : 
     494                 :          0 :   formats = xmlNewChild (writer, NULL, (xmlChar *) "formats", NULL);
     495                 :          0 :   g_snprintf (buf, bufsize, "%d", ii->nformats);
     496                 :          0 :   xmlSetProp (formats, (xmlChar *) "count", (xmlChar *) buf);
     497                 :            : 
     498         [ #  # ]:          0 :   for (xx = 0; xx < ii->nformats; xx++) {
     499                 :          0 :     xmlNodePtr format = xmlNewChild (formats, NULL, (xmlChar *) "format", NULL);
     500                 :          0 :     const GstFormatDefinition *def = gst_format_get_details (ii->format[xx]);
     501                 :            : 
     502                 :          0 :     xmlSetProp (format, (xmlChar *) "nick", (xmlChar *) def->nick);
     503                 :            :   }
     504                 :            : }
     505                 :            : 
     506                 :            : /*
     507                 :            :   We must save the binary data in separate files because
     508                 :            :   mmap wants getpagesize() alignment.  If we append all
     509                 :            :   the data to one file then we don't know the appropriate
     510                 :            :   padding since the page size isn't fixed.
     511                 :            : */
     512                 :            : static void
     513                 :          0 : _file_index_id_save_entries (gpointer * _key,
     514                 :            :     GstFileIndexId * ii, gchar * prefix)
     515                 :            : {
     516                 :            :   GError *err;
     517                 :            :   gchar *path;
     518                 :            :   GIOChannel *chan;
     519                 :            : 
     520         [ #  # ]:          0 :   if (!ii->array)
     521                 :          0 :     return;
     522                 :            : 
     523                 :          0 :   err = NULL;
     524                 :          0 :   path = g_strdup_printf ("%s/%d", prefix, ii->id);
     525                 :          0 :   chan = g_io_channel_new_file (path, "w", &err);
     526                 :          0 :   g_free (path);
     527         [ #  # ]:          0 :   if (err)
     528                 :          0 :     goto fail;
     529                 :            : 
     530                 :          0 :   g_io_channel_set_encoding (chan, NULL, &err);
     531         [ #  # ]:          0 :   if (err)
     532                 :          0 :     goto fail;
     533                 :            : 
     534                 :          0 :   g_io_channel_write_chars (chan,
     535                 :          0 :       ii->array->data, ARRAY_TOTAL_SIZE (ii), NULL, &err);
     536         [ #  # ]:          0 :   if (err)
     537                 :          0 :     goto fail;
     538                 :            : 
     539                 :          0 :   g_io_channel_shutdown (chan, TRUE, &err);
     540         [ #  # ]:          0 :   if (err)
     541                 :          0 :     goto fail;
     542                 :            : 
     543                 :          0 :   g_io_channel_unref (chan);
     544                 :          0 :   return;
     545                 :            : 
     546                 :            : fail:
     547         [ #  # ]:          0 :   GST_ERROR ("%s", err->message);
     548                 :            : }
     549                 :            : 
     550                 :            : /*
     551                 :            :   We have to save the whole set of indexes into a single file
     552                 :            :   so it doesn't make sense to commit only a single writer.
     553                 :            : 
     554                 :            :   i suggest:
     555                 :            : 
     556                 :            :   gst_index_commit (index, -1);
     557                 :            : */
     558                 :            : static void
     559                 :          0 : gst_file_index_commit (GstIndex * _index, gint _writer_id)
     560                 :            : {
     561                 :          0 :   GstFileIndex *index = GST_FILE_INDEX (_index);
     562                 :            :   xmlDocPtr doc;
     563                 :            :   xmlNodePtr writers;
     564                 :          0 :   GError *err = NULL;
     565                 :            :   gchar *path;
     566                 :            :   GIOChannel *tocfile;
     567                 :            : 
     568         [ #  # ]:          0 :   g_return_if_fail (index->location);
     569         [ #  # ]:          0 :   g_return_if_fail (!index->is_loaded);
     570                 :            : 
     571                 :          0 :   GST_OBJECT_FLAG_UNSET (index, GST_INDEX_WRITABLE);
     572                 :            : 
     573                 :          0 :   doc = xmlNewDoc ((xmlChar *) "1.0");
     574                 :          0 :   doc->xmlRootNode =
     575                 :          0 :       xmlNewDocNode (doc, NULL, (xmlChar *) "gstfileindex", NULL);
     576                 :          0 :   xmlSetProp (doc->xmlRootNode, (xmlChar *) "version", (xmlChar *) "1");
     577                 :            : 
     578                 :          0 :   writers = xmlNewChild (doc->xmlRootNode, NULL, (xmlChar *) "writers", NULL);
     579                 :          0 :   g_hash_table_foreach (index->id_index,
     580                 :            :       (GHFunc) _file_index_id_save_xml, writers);
     581                 :            : 
     582 [ #  # ][ #  # ]:          0 :   if (mkdir (index->location, 0777) && errno != EEXIST) {
     583         [ #  # ]:          0 :     GST_ERROR_OBJECT (index, "mkdir %s: %s", index->location,
     584                 :            :         g_strerror (errno));
     585                 :          0 :     return;
     586                 :            :   }
     587                 :            : 
     588                 :          0 :   path = g_strdup_printf ("%s/gstindex.xml", index->location);
     589                 :          0 :   tocfile = g_io_channel_new_file (path, "w", &err);
     590                 :          0 :   g_free (path);
     591         [ #  # ]:          0 :   if (err) {
     592         [ #  # ]:          0 :     GST_ERROR_OBJECT (index, "%s", err->message);
     593                 :          0 :     return;
     594                 :            :   }
     595                 :            : 
     596                 :          0 :   g_io_channel_set_encoding (tocfile, NULL, &err);
     597         [ #  # ]:          0 :   if (err) {
     598         [ #  # ]:          0 :     GST_ERROR_OBJECT (index, "%s", err->message);
     599                 :          0 :     return;
     600                 :            :   }
     601                 :            : 
     602                 :            :   {
     603                 :            :     xmlChar *xmlmem;
     604                 :            :     int xmlsize;
     605                 :            : 
     606                 :          0 :     xmlDocDumpMemory (doc, &xmlmem, &xmlsize);
     607                 :          0 :     g_io_channel_write_chars (tocfile, (gchar *) xmlmem, xmlsize, NULL, &err);
     608         [ #  # ]:          0 :     if (err) {
     609         [ #  # ]:          0 :       GST_ERROR_OBJECT (index, "%s", err->message);
     610                 :          0 :       return;
     611                 :            :     }
     612                 :          0 :     xmlFreeDoc (doc);
     613                 :          0 :     free (xmlmem);
     614                 :            :   }
     615                 :            : 
     616                 :          0 :   g_io_channel_shutdown (tocfile, TRUE, &err);
     617         [ #  # ]:          0 :   if (err) {
     618         [ #  # ]:          0 :     GST_ERROR_OBJECT (index, "%s", err->message);
     619                 :          0 :     return;
     620                 :            :   }
     621                 :            : 
     622                 :          0 :   g_io_channel_unref (tocfile);
     623                 :            : 
     624                 :          0 :   g_hash_table_foreach (index->id_index,
     625                 :          0 :       (GHFunc) _file_index_id_save_entries, index->location);
     626                 :            : }
     627                 :            : 
     628                 :            : static void
     629                 :          0 : gst_file_index_add_id (GstIndex * index, GstIndexEntry * entry)
     630                 :            : {
     631                 :          0 :   GstFileIndex *fileindex = GST_FILE_INDEX (index);
     632                 :            :   GstFileIndexId *id_index;
     633                 :            : 
     634                 :          0 :   id_index = g_hash_table_lookup (fileindex->id_index, &entry->id);
     635                 :            : 
     636         [ #  # ]:          0 :   if (!id_index) {
     637                 :          0 :     id_index = g_slice_new0 (GstFileIndexId);
     638                 :            : 
     639                 :          0 :     id_index->id = entry->id;
     640                 :          0 :     id_index->id_desc = g_strdup (entry->data.id.description);
     641                 :            : 
     642                 :            :     /* It would be useful to know the GType of the writer so
     643                 :            :        we can try to cope with changes in the id_desc path. */
     644                 :            : 
     645                 :          0 :     g_hash_table_insert (fileindex->id_index, &id_index->id, id_index);
     646                 :            :   }
     647                 :          0 : }
     648                 :            : 
     649                 :            : /* This algorithm differs from libc bsearch in the handling
     650                 :            :    of non-exact matches. */
     651                 :            : 
     652                 :            : static gboolean
     653                 :          0 : _fc_bsearch (GArray * ary,
     654                 :            :     gint stride,
     655                 :            :     gint * ret,
     656                 :            :     GCompareDataFunc compare, gconstpointer sample, gpointer user_data)
     657                 :            : {
     658                 :            :   gint first, last;
     659                 :            :   gint mid;
     660                 :            :   gint midsize;
     661                 :            :   gint cmp;
     662                 :            :   gint tx;
     663                 :            : 
     664         [ #  # ]:          0 :   g_return_val_if_fail (compare, FALSE);
     665                 :            : 
     666         [ #  # ]:          0 :   if (!ary->len) {
     667         [ #  # ]:          0 :     if (ret)
     668                 :          0 :       *ret = 0;
     669                 :          0 :     return FALSE;
     670                 :            :   }
     671                 :            : 
     672                 :          0 :   first = 0;
     673                 :          0 :   last = ary->len - 1;
     674                 :            : 
     675                 :          0 :   midsize = last - first;
     676                 :            : 
     677         [ #  # ]:          0 :   while (midsize > 1) {
     678                 :          0 :     mid = first + midsize / 2;
     679                 :            : 
     680                 :          0 :     cmp = (*compare) (sample, ary->data + mid * stride, user_data);
     681                 :            : 
     682         [ #  # ]:          0 :     if (cmp == 0) {
     683                 :            :       /* if there are multiple matches then scan for the first match */
     684   [ #  #  #  # ]:          0 :       while (mid > 0 &&
     685                 :          0 :           (*compare) (sample, ary->data + (mid - 1) * stride, user_data) == 0)
     686                 :          0 :         --mid;
     687                 :            : 
     688         [ #  # ]:          0 :       if (ret)
     689                 :          0 :         *ret = mid;
     690                 :          0 :       return TRUE;
     691                 :            :     }
     692                 :            : 
     693         [ #  # ]:          0 :     if (cmp < 0)
     694                 :          0 :       last = mid - 1;
     695                 :            :     else
     696                 :          0 :       first = mid + 1;
     697                 :            : 
     698                 :          0 :     midsize = last - first;
     699                 :            :   }
     700                 :            : 
     701         [ #  # ]:          0 :   for (tx = first; tx <= last; tx++) {
     702                 :          0 :     cmp = (*compare) (sample, ary->data + tx * stride, user_data);
     703                 :            : 
     704         [ #  # ]:          0 :     if (cmp < 0) {
     705         [ #  # ]:          0 :       if (ret)
     706                 :          0 :         *ret = tx;
     707                 :          0 :       return FALSE;
     708                 :            :     }
     709         [ #  # ]:          0 :     if (cmp == 0) {
     710         [ #  # ]:          0 :       if (ret)
     711                 :          0 :         *ret = tx;
     712                 :          0 :       return TRUE;
     713                 :            :     }
     714                 :            :   }
     715                 :            : 
     716         [ #  # ]:          0 :   if (ret)
     717                 :          0 :     *ret = last + 1;
     718                 :          0 :   return FALSE;
     719                 :            : }
     720                 :            : 
     721                 :            : static gint
     722                 :          0 : file_index_compare (gconstpointer sample, gconstpointer row, gpointer user_data)
     723                 :            : {
     724                 :            :   //GstFileIndexId *id_index = user_data;
     725                 :          0 :   const GstIndexAssociation *ca = sample;
     726                 :          0 :   gint64 val1 = ca->value;
     727                 :          0 :   gint64 val2_be = ARRAY_ROW_VALUE (row, ca->format);
     728                 :          0 :   gint64 val2 = GINT64_FROM_BE (val2_be);
     729                 :          0 :   gint64 diff = val2 - val1;
     730                 :            : 
     731 [ #  # ][ #  # ]:          0 :   return (diff == 0 ? 0 : (diff < 0 ? 1 : -1));
     732                 :            : }
     733                 :            : 
     734                 :            : static void
     735                 :          0 : gst_file_index_add_association (GstIndex * index, GstIndexEntry * entry)
     736                 :            : {
     737                 :          0 :   GstFileIndex *fileindex = GST_FILE_INDEX (index);
     738                 :            :   GstFileIndexId *id_index;
     739                 :            :   gint mx;
     740                 :            :   GstIndexAssociation sample;
     741                 :            :   gboolean exact;
     742                 :            : 
     743                 :          0 :   id_index = g_hash_table_lookup (fileindex->id_index, &entry->id);
     744         [ #  # ]:          0 :   if (!id_index)
     745                 :          0 :     return;
     746                 :            : 
     747         [ #  # ]:          0 :   if (!id_index->nformats) {
     748                 :            :     gint fx;
     749                 :            : 
     750                 :          0 :     id_index->nformats = GST_INDEX_NASSOCS (entry);
     751         [ #  # ]:          0 :     GST_LOG_OBJECT (fileindex, "creating %d formats for %d",
     752                 :            :         id_index->nformats, entry->id);
     753                 :          0 :     id_index->format = g_new (GstFormat, id_index->nformats);
     754         [ #  # ]:          0 :     for (fx = 0; fx < id_index->nformats; fx++)
     755                 :          0 :       id_index->format[fx] = GST_INDEX_ASSOC_FORMAT (entry, fx);
     756                 :          0 :     _fc_alloc_array (id_index);
     757                 :            :   } else {
     758                 :            :     /* only sanity checking */
     759         [ #  # ]:          0 :     if (id_index->nformats != GST_INDEX_NASSOCS (entry))
     760         [ #  # ]:          0 :       GST_WARNING_OBJECT (fileindex, "arity change %d -> %d",
     761                 :            :           id_index->nformats, GST_INDEX_NASSOCS (entry));
     762                 :            :     else {
     763                 :            :       gint fx;
     764                 :            : 
     765         [ #  # ]:          0 :       for (fx = 0; fx < id_index->nformats; fx++)
     766         [ #  # ]:          0 :         if (id_index->format[fx] != GST_INDEX_ASSOC_FORMAT (entry, fx))
     767         [ #  # ]:          0 :           GST_WARNING_OBJECT (fileindex, "format[%d] changed %d -> %d",
     768                 :            :               fx, id_index->format[fx], GST_INDEX_ASSOC_FORMAT (entry, fx));
     769                 :            :     }
     770                 :            :   }
     771                 :            : 
     772                 :            :   /* this is a hack, we should use a private structure instead */
     773                 :          0 :   sample.format = 0;
     774                 :          0 :   sample.value = GST_INDEX_ASSOC_VALUE (entry, 0);
     775                 :            : 
     776                 :          0 :   exact =
     777                 :          0 :       _fc_bsearch (id_index->array, ARRAY_ROW_SIZE (id_index),
     778                 :            :       &mx, file_index_compare, &sample, id_index);
     779                 :            : 
     780         [ #  # ]:          0 :   if (exact) {
     781                 :            :     /* maybe overwrite instead? */
     782         [ #  # ]:          0 :     GST_DEBUG_OBJECT (index,
     783                 :            :         "Ignoring duplicate index association at %" G_GINT64_FORMAT,
     784                 :            :         GST_INDEX_ASSOC_VALUE (entry, 0));
     785                 :          0 :     return;
     786                 :            :   }
     787                 :            : 
     788                 :            :   {
     789                 :          0 :     gchar *row_data = (gchar *) g_malloc (ARRAY_ROW_SIZE (id_index));
     790                 :            :     gint fx;
     791                 :            : 
     792                 :          0 :     gint32 flags_host = GST_INDEX_ASSOC_FLAGS (entry);
     793                 :            : 
     794                 :          0 :     ARRAY_ROW_FLAGS (row_data) = GINT32_TO_BE (flags_host);
     795                 :            : 
     796         [ #  # ]:          0 :     for (fx = 0; fx < id_index->nformats; fx++) {
     797                 :          0 :       gint64 val_host = GST_INDEX_ASSOC_VALUE (entry, fx);
     798                 :            : 
     799                 :          0 :       ARRAY_ROW_VALUE (row_data, fx) = GINT64_TO_BE (val_host);
     800                 :            :     }
     801                 :            : 
     802                 :          0 :     g_array_insert_vals (id_index->array, mx, row_data, 1);
     803                 :            : 
     804                 :          0 :     g_free (row_data);
     805                 :            :   }
     806                 :            : }
     807                 :            : 
     808                 :            : /*
     809                 :            : static void
     810                 :            : show_entry (GstIndexEntry *entry)
     811                 :            : {
     812                 :            :   switch (entry->type) {
     813                 :            :     case GST_INDEX_ENTRY_ID:
     814                 :            :       g_print ("id %d describes writer %s\n", entry->id,
     815                 :            :                       GST_INDEX_ID_DESCRIPTION (entry));
     816                 :            :       break;
     817                 :            :     case GST_INDEX_ENTRY_FORMAT:
     818                 :            :       g_print ("%d: registered format %d for %s\n", entry->id,
     819                 :            :                       GST_INDEX_FORMAT_FORMAT (entry),
     820                 :            :                       GST_INDEX_FORMAT_KEY (entry));
     821                 :            :       break;
     822                 :            :     case GST_INDEX_ENTRY_ASSOCIATION:
     823                 :            :     {
     824                 :            :       gint i;
     825                 :            : 
     826                 :            :       g_print ("%d: %08x ", entry->id, GST_INDEX_ASSOC_FLAGS (entry));
     827                 :            :       for (i = 0; i < GST_INDEX_NASSOCS (entry); i++) {
     828                 :            :         g_print ("%d %" G_GINT64_FORMAT, GST_INDEX_ASSOC_FORMAT (entry, i),
     829                 :            :                              GST_INDEX_ASSOC_VALUE (entry, i));
     830                 :            :       }
     831                 :            :       g_print ("\n");
     832                 :            :       break;
     833                 :            :     }
     834                 :            :     default:
     835                 :            :       break;
     836                 :            :   }
     837                 :            : }
     838                 :            : */
     839                 :            : 
     840                 :            : static void
     841                 :          0 : gst_file_index_add_entry (GstIndex * index, GstIndexEntry * entry)
     842                 :            : {
     843         [ #  # ]:          0 :   GST_LOG_OBJECT (index, "adding this entry");
     844                 :            : 
     845   [ #  #  #  #  :          0 :   switch (entry->type) {
                      # ]
     846                 :            :     case GST_INDEX_ENTRY_ID:
     847                 :          0 :       gst_file_index_add_id (index, entry);
     848                 :          0 :       break;
     849                 :            :     case GST_INDEX_ENTRY_ASSOCIATION:
     850                 :          0 :       gst_file_index_add_association (index, entry);
     851                 :          0 :       break;
     852                 :            :     case GST_INDEX_ENTRY_OBJECT:
     853         [ #  # ]:          0 :       GST_ERROR_OBJECT (index, "gst_file_index_add_object not implemented");
     854                 :          0 :       break;
     855                 :            :     case GST_INDEX_ENTRY_FORMAT:
     856                 :            :       /*
     857                 :            :          We infer the formats from the entry itself so this type of
     858                 :            :          GST_INDEX_ENTRY_* can probably go away.
     859                 :            :        */
     860         [ #  # ]:          0 :       GST_DEBUG_OBJECT (index, "gst_file_index_add_format not implemented");
     861                 :          0 :       break;
     862                 :            :     default:
     863                 :          0 :       break;
     864                 :            :   }
     865                 :          0 : }
     866                 :            : 
     867                 :            : static GstIndexEntry *
     868                 :          0 : gst_file_index_get_assoc_entry (GstIndex * index,
     869                 :            :     gint id,
     870                 :            :     GstIndexLookupMethod method,
     871                 :            :     GstAssocFlags flags,
     872                 :            :     GstFormat format,
     873                 :            :     gint64 value, GCompareDataFunc _ignore_func, gpointer _ignore_user_data)
     874                 :            : {
     875                 :          0 :   GstFileIndex *fileindex = GST_FILE_INDEX (index);
     876                 :            :   GstFileIndexId *id_index;
     877                 :          0 :   gint formatx = -1;
     878                 :            :   gint fx;
     879                 :            :   GstIndexAssociation sample;
     880                 :            :   gint mx;
     881                 :            :   gboolean exact;
     882                 :            :   gpointer row_data;
     883                 :            :   GstIndexEntry *entry;
     884                 :            :   gint xx;
     885                 :            : 
     886         [ #  # ]:          0 :   g_return_val_if_fail (id > 0, NULL);
     887                 :            : 
     888                 :          0 :   id_index = g_hash_table_lookup (fileindex->id_index, &id);
     889         [ #  # ]:          0 :   if (!id_index) {
     890         [ #  # ]:          0 :     GST_WARNING_OBJECT (fileindex, "writer %d unavailable", id);
     891                 :          0 :     return NULL;
     892                 :            :   }
     893                 :            : 
     894         [ #  # ]:          0 :   for (fx = 0; fx < id_index->nformats; fx++)
     895         [ #  # ]:          0 :     if (id_index->format[fx] == format) {
     896                 :          0 :       formatx = fx;
     897                 :          0 :       break;
     898                 :            :     }
     899                 :            : 
     900         [ #  # ]:          0 :   if (formatx == -1) {
     901         [ #  # ]:          0 :     GST_WARNING_OBJECT (fileindex, "format %d not available", format);
     902                 :          0 :     return NULL;
     903                 :            :   }
     904                 :            : 
     905                 :            :   /* this is a hack, we should use a private structure instead */
     906                 :          0 :   sample.format = formatx;
     907                 :          0 :   sample.value = value;
     908                 :            : 
     909                 :          0 :   exact = _fc_bsearch (id_index->array, ARRAY_ROW_SIZE (id_index),
     910                 :            :       &mx, file_index_compare, &sample, id_index);
     911                 :            : 
     912         [ #  # ]:          0 :   if (!exact) {
     913         [ #  # ]:          0 :     if (method == GST_INDEX_LOOKUP_EXACT)
     914                 :          0 :       return NULL;
     915         [ #  # ]:          0 :     else if (method == GST_INDEX_LOOKUP_BEFORE) {
     916         [ #  # ]:          0 :       if (mx == 0)
     917                 :          0 :         return NULL;
     918                 :          0 :       mx -= 1;
     919         [ #  # ]:          0 :     } else if (method == GST_INDEX_LOOKUP_AFTER) {
     920         [ #  # ]:          0 :       if (mx == id_index->array->len)
     921                 :          0 :         return NULL;
     922                 :            :     }
     923                 :            :   }
     924                 :            : 
     925                 :          0 :   row_data = id_index->array->data + mx * ARRAY_ROW_SIZE (id_index);
     926                 :            : 
     927                 :            :   /* if exact then ignore flags (?) */
     928         [ #  # ]:          0 :   if (method != GST_INDEX_LOOKUP_EXACT)
     929         [ #  # ]:          0 :     while ((GINT32_FROM_BE (ARRAY_ROW_FLAGS (row_data)) & flags) != flags) {
     930         [ #  # ]:          0 :       if (method == GST_INDEX_LOOKUP_BEFORE)
     931                 :          0 :         mx -= 1;
     932         [ #  # ]:          0 :       else if (method == GST_INDEX_LOOKUP_AFTER)
     933                 :          0 :         mx += 1;
     934 [ #  # ][ #  # ]:          0 :       if (mx < 0 || mx >= id_index->array->len)
     935                 :          0 :         return NULL;
     936                 :          0 :       row_data = id_index->array->data + mx * ARRAY_ROW_SIZE (id_index);
     937                 :            :     }
     938                 :            : 
     939                 :            :   /* entry memory management needs improvement FIXME */
     940         [ #  # ]:          0 :   if (!fileindex->ret_entry)
     941                 :          0 :     fileindex->ret_entry = g_slice_new0 (GstIndexEntry);
     942                 :          0 :   entry = fileindex->ret_entry;
     943         [ #  # ]:          0 :   if (entry->data.assoc.assocs) {
     944                 :          0 :     g_free (entry->data.assoc.assocs);
     945                 :          0 :     entry->data.assoc.assocs = NULL;
     946                 :            :   }
     947                 :            : 
     948                 :          0 :   entry->type = GST_INDEX_ENTRY_ASSOCIATION;
     949                 :            : 
     950                 :          0 :   GST_INDEX_NASSOCS (entry) = id_index->nformats;
     951                 :          0 :   entry->data.assoc.assocs = g_new (GstIndexAssociation, id_index->nformats);
     952                 :            : 
     953                 :            :   {
     954                 :          0 :     gint32 flags_be = ARRAY_ROW_FLAGS (row_data);
     955                 :            : 
     956                 :          0 :     GST_INDEX_ASSOC_FLAGS (entry) = GINT32_FROM_BE (flags_be);
     957                 :            : 
     958         [ #  # ]:          0 :     for (xx = 0; xx < id_index->nformats; xx++) {
     959                 :          0 :       gint64 val_be = ARRAY_ROW_VALUE (row_data, xx);
     960                 :            : 
     961                 :          0 :       GST_INDEX_ASSOC_FORMAT (entry, xx) = id_index->format[xx];
     962                 :          0 :       GST_INDEX_ASSOC_VALUE (entry, xx) = GINT64_FROM_BE (val_be);
     963                 :            :     }
     964                 :            :   }
     965                 :            : 
     966                 :          0 :   return entry;
     967                 :            : }
     968                 :            : 
     969                 :            : gboolean
     970                 :          4 : gst_file_index_plugin_init (GstPlugin * plugin)
     971                 :            : {
     972                 :            :   GstIndexFactory *factory;
     973                 :            : 
     974                 :          4 :   factory = gst_index_factory_new ("fileindex",
     975                 :            :       "A index that stores entries in file", gst_file_index_get_type ());
     976                 :            : 
     977         [ -  + ]:          4 :   if (factory == NULL) {
     978                 :          0 :     return FALSE;
     979                 :            :   }
     980                 :            : 
     981                 :          4 :   GST_PLUGIN_FEATURE (factory)->plugin_name = plugin->desc.name;
     982                 :          4 :   GST_PLUGIN_FEATURE (factory)->loaded = TRUE;
     983                 :            : 
     984                 :          4 :   gst_registry_add_feature (gst_registry_get_default (),
     985                 :          4 :       GST_PLUGIN_FEATURE (factory));
     986                 :            : 
     987         [ +  - ]:          4 :   GST_DEBUG_CATEGORY_INIT (DC, "GST_FILEINDEX", 0, NULL);
     988                 :            : 
     989                 :          4 :   return TRUE;
     990                 :            : }

Generated by: LCOV version 1.9