plugins/elements/gsttypefindelement.*: Use gst_type_find_helper_for_buffer() for...
authorTim-Philipp Müller <tim@centricular.net>
Fri, 3 Mar 2006 14:18:01 +0000 (14:18 +0000)
committerTim-Philipp Müller <tim@centricular.net>
Fri, 3 Mar 2006 14:18:01 +0000 (14:18 +0000)
Original commit message from CVS:
* plugins/elements/gsttypefindelement.h:
* plugins/elements/gsttypefindelement.c:
(gst_type_find_element_src_event), (start_typefinding),
(stop_typefinding), (gst_type_find_element_handle_event),
(gst_type_find_element_chain),
(gst_type_find_element_chain_do_typefinding):
Use gst_type_find_helper_for_buffer() for chain-based
typefinding.

ChangeLog
plugins/elements/gsttypefindelement.c
plugins/elements/gsttypefindelement.h

index f9fb300..d6caaeb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2006-03-03  Tim-Philipp Müller  <tim at centricular dot net>
 
+       * plugins/elements/gsttypefindelement.h:
+       * plugins/elements/gsttypefindelement.c:
+       (gst_type_find_element_src_event), (start_typefinding),
+       (stop_typefinding), (gst_type_find_element_handle_event),
+       (gst_type_find_element_chain),
+       (gst_type_find_element_chain_do_typefinding):
+         Use gst_type_find_helper_for_buffer() for chain-based
+         typefinding.
+
+2006-03-03  Tim-Philipp Müller  <tim at centricular dot net>
+
        * plugins/elements/gsttypefindelement.c:
        (gst_type_find_element_class_init),
        (gst_type_find_element_set_property),
index fa2d2d6..2c1f0b6 100644 (file)
@@ -143,6 +143,8 @@ gst_type_find_element_change_state (GstElement * element,
 static gboolean gst_type_find_element_activate (GstPad * pad);
 static gboolean
 gst_type_find_element_activate_src_pull (GstPad * pad, gboolean active);
+static GstFlowReturn
+gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind);
 
 static guint gst_type_find_element_signals[LAST_SIGNAL] = { 0 };
 
@@ -389,42 +391,16 @@ gst_type_find_element_src_event (GstPad * pad, GstEvent * event)
   }
   return gst_pad_event_default (pad, event);
 }
-typedef struct
-{
-  GstTypeFindFactory *factory;
-  guint probability;
-  GstCaps *caps;
-  guint requested_size;
-  GstTypeFindElement *self;
-}
-TypeFindEntry;
 
-static inline TypeFindEntry *
-new_entry (void)
-{
-  return g_new0 (TypeFindEntry, 1);
-}
-static void
-free_entry (TypeFindEntry * entry)
-{
-  if (entry->caps)
-    gst_caps_unref (entry->caps);
-  gst_object_unref (entry->factory);
-  g_free (entry);
-}
 static void
 start_typefinding (GstTypeFindElement * typefind)
 {
-  g_assert (typefind->possibilities == NULL);
-
   GST_DEBUG_OBJECT (typefind, "starting typefinding");
   gst_pad_set_caps (typefind->src, NULL);
   if (typefind->caps) {
     gst_caps_replace (&typefind->caps, NULL);
   }
   typefind->mode = MODE_TYPEFIND;
-  typefind->stream_length_available = TRUE;
-  typefind->stream_length = 0;
 }
 
 static void
@@ -439,15 +415,6 @@ stop_typefinding (GstTypeFindElement * typefind)
 
   GST_DEBUG_OBJECT (typefind, "stopping typefinding%s",
       push_cached_buffers ? " and pushing cached buffers" : "");
-  if (typefind->possibilities != NULL) {
-    /* this should only happen on PAUSED => READY or EOS */
-    GST_LOG_OBJECT (typefind, "freeing remaining %u typefind functions",
-        g_list_length (typefind->possibilities));
-    g_list_foreach (typefind->possibilities, (GFunc) free_entry, NULL);
-    g_list_free (typefind->possibilities);
-    typefind->possibilities = NULL;
-  }
-  //typefind->mode = MODE_TRANSITION;
 
   if (typefind->store) {
     if (!push_cached_buffers) {
@@ -483,64 +450,6 @@ stop_typefinding (GstTypeFindElement * typefind)
   }
 }
 
-static guint64
-find_element_get_length (gpointer data)
-{
-  TypeFindEntry *entry = (TypeFindEntry *) data;
-  GstTypeFindElement *typefind = entry->self;
-  GstFormat format = GST_FORMAT_BYTES;
-
-  if (!typefind->stream_length_available) {
-    GST_LOG_OBJECT (entry->self,
-        "'%s' called get_length () but we know it's not available",
-        GST_PLUGIN_FEATURE_NAME (entry->factory));
-    return 0;
-  }
-  if (entry->self->stream_length == 0) {
-    if (!gst_pad_query_duration (GST_PAD_PEER (entry->self->sink), &format,
-            (gint64 *) & entry->self->stream_length))
-      goto no_length;
-
-    if (format != GST_FORMAT_BYTES) {
-      typefind->stream_length_available = FALSE;
-      entry->self->stream_length = 0;
-    } else {
-      GST_DEBUG_OBJECT (entry->self,
-          "'%s' called get_length () and it's %" G_GUINT64_FORMAT " bytes",
-          GST_PLUGIN_FEATURE_NAME (entry->factory), entry->self->stream_length);
-    }
-  }
-  return entry->self->stream_length;
-
-no_length:
-  {
-    typefind->stream_length_available = FALSE;
-    GST_DEBUG_OBJECT (entry->self,
-        "'%s' called get_length () but it's not available",
-        GST_PLUGIN_FEATURE_NAME (entry->factory));
-    return 0;
-  }
-}
-
-static TypeFindEntry *
-gst_type_find_element_get_best_possibility (GstTypeFindElement * typefind)
-{
-  TypeFindEntry *best = NULL;
-  GList *walk;
-
-  for (walk = typefind->possibilities; walk != NULL; walk = walk->next) {
-    TypeFindEntry *entry;
-
-    entry = (TypeFindEntry *) walk->data;
-    if ((!best || entry->probability > best->probability) &&
-        entry->probability >= typefind->min_probability) {
-      best = entry;
-    }
-  }
-
-  return best;
-}
-
 static gboolean
 gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
 {
@@ -598,85 +507,12 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
   }
   return res;
 }
-static guint8 *
-find_peek (gpointer data, gint64 offset, guint size)
-{
-  TypeFindEntry *entry = (TypeFindEntry *) data;
-
-  GST_LOG_OBJECT (entry->self, "'%s' called peek (%" G_GINT64_FORMAT ", %u)",
-      GST_PLUGIN_FEATURE_NAME (entry->factory), offset, size);
-
-  if (offset < 0) {
-    GST_LOG_OBJECT (entry->self, "peek at end not supported in push mode");
-    return NULL;
-  }
-
-  if (offset > 0) {
-    if ((offset + size) <= entry->self->store->size) {
-      entry->requested_size = 0;
-      return GST_BUFFER_DATA (entry->self->store) + offset;
-    }
-    /* no can do */
-    return NULL;
-  }
-
-  /* offset == 0 ... */
-
-  if (size <= entry->self->store->size) {
-    entry->requested_size = 0;
-    return GST_BUFFER_DATA (entry->self->store);
-  } else {
-    entry->requested_size = size;
-
-    GST_LOG_OBJECT (entry->self,
-        "setting requested peek (%" G_GINT64_FORMAT ", %u) on '%s'", offset,
-        size, GST_PLUGIN_FEATURE_NAME (entry->factory));
-    return NULL;
-  }
-}
-static void
-find_suggest (gpointer data, guint probability, const GstCaps * caps)
-{
-  TypeFindEntry *entry = (TypeFindEntry *) data;
-
-  GST_LOG_OBJECT (entry->self, "'%s' called suggest (%u, %" GST_PTR_FORMAT ")",
-      GST_PLUGIN_FEATURE_NAME (entry->factory), probability, caps);
-  if (((gint) probability) > entry->probability) {
-    entry->probability = probability;
-    gst_caps_replace (&entry->caps, (GstCaps *) caps);
-  }
-}
-
-#if 0
-static gint
-compare_type_find_entry (gconstpointer a, gconstpointer b)
-{
-  TypeFindEntry *one = (TypeFindEntry *) a;
-  TypeFindEntry *two = (TypeFindEntry *) b;
-
-  if (one->probability == two->probability) {
-    /* FIXME: can be improved by analyzing requests */
-    return 0;
-  } else {
-    return two->probability - one->probability;
-  }
-}
-#endif
-
-static gint
-compare_type_find_factory (gconstpointer fac1, gconstpointer fac2)
-{
-  return GST_PLUGIN_FEATURE (fac1)->rank - GST_PLUGIN_FEATURE (fac2)->rank;
-}
 
 static GstFlowReturn
 gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
 {
   GstTypeFindElement *typefind;
-  TypeFindEntry *entry;
-  GList *walk;
   GstFlowReturn res = GST_FLOW_OK;
-  GstTypeFind find = { find_peek, find_suggest, NULL, find_element_get_length };
 
   typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
 
@@ -688,121 +524,12 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
       gst_buffer_set_caps (buffer, typefind->caps);
       return gst_pad_push (typefind->src, buffer);
     case MODE_TYPEFIND:{
-      gboolean done = TRUE;
-
       if (typefind->store)
         typefind->store = gst_buffer_join (typefind->store, buffer);
       else
         typefind->store = buffer;
 
-      if (GST_BUFFER_SIZE (typefind->store) < TYPE_FIND_MIN_SIZE) {
-        GST_DEBUG_OBJECT (typefind, "not enough data for typefinding yet");
-        return GST_FLOW_OK;
-      }
-
-      if (typefind->possibilities == NULL) {
-        /* not yet started, get all typefinding functions into our "queue" */
-        GList *all_factories = gst_type_find_factory_get_list ();
-
-        GST_INFO_OBJECT (typefind, "starting with %u typefinding functions",
-            g_list_length (all_factories));
-
-        all_factories = g_list_sort (all_factories, compare_type_find_factory);
-        walk = all_factories;
-        while (walk) {
-          entry = new_entry ();
-
-          entry->factory = gst_object_ref (GST_TYPE_FIND_FACTORY (walk->data));
-          entry->self = typefind;
-          entry->probability = 0;
-          typefind->possibilities =
-              g_list_prepend (typefind->possibilities, entry);
-          walk = g_list_next (walk);
-        }
-        gst_plugin_feature_list_free (all_factories);
-      }
-
-      /* call every typefind function once */
-      walk = typefind->possibilities;
-      GST_INFO_OBJECT (typefind, "iterating %u typefinding functions",
-          g_list_length (walk));
-      while (walk) {
-        find.data = entry = (TypeFindEntry *) walk->data;
-        if (entry->probability != 0) {
-          /* Probability already known, just continue along the list */
-          walk = g_list_next (walk);
-          continue;
-        }
-
-        entry->requested_size = 0;
-        gst_type_find_factory_call_function (entry->factory, &find);
-
-        if (entry->probability == 0 && entry->requested_size == 0) {
-          GList *next;
-
-          GST_DEBUG_OBJECT (typefind,
-              "'%s' was removed - no chance of being the right plugin",
-              GST_PLUGIN_FEATURE_NAME (entry->factory));
-          next = g_list_next (walk);
-          free_entry (entry);
-          typefind->possibilities =
-              g_list_delete_link (typefind->possibilities, walk);
-          walk = next;
-        } else if (entry->probability >= typefind->max_probability) {
-          /* wooha, got caps */
-          GstCaps *found_caps = entry->caps;
-          guint probability = entry->probability;
-
-          GST_INFO_OBJECT (typefind,
-              "'%s' returned %u/%u probability, using it NOW",
-              GST_PLUGIN_FEATURE_NAME (entry->factory), probability,
-              typefind->max_probability);
-          g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
-              probability, found_caps);
-
-          g_list_foreach (typefind->possibilities, (GFunc) free_entry, NULL);
-          g_list_free (typefind->possibilities);
-          typefind->possibilities = NULL;
-          break;
-        } else {
-          walk = g_list_next (walk);
-          if (entry->requested_size != 0)
-            done = FALSE;
-        }
-      }
-
-      /* we may now already have caps or we might be left without functions to try */
-      if (typefind->caps) {
-        stop_typefinding (typefind);
-      } else if (typefind->possibilities == NULL) {
-        if (GST_BUFFER_SIZE (typefind->store) > TYPE_FIND_MAX_SIZE) {
-          GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
-          stop_typefinding (typefind);
-          return GST_FLOW_ERROR;
-        } else {
-          GST_DEBUG_OBJECT (typefind, "no type found with %u bytes - waiting "
-              "for more data", GST_BUFFER_SIZE (typefind->store));
-          return GST_FLOW_OK;
-        }
-      } else if (done) {
-        TypeFindEntry *best;
-
-        if ((best = gst_type_find_element_get_best_possibility (typefind))) {
-          GST_INFO_OBJECT (typefind,
-              "'%s' is the best typefind left, using it now (probability %u)",
-              GST_PLUGIN_FEATURE_NAME (best->factory), best->probability);
-          g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
-              0, best->probability, best->caps);
-          g_list_foreach (typefind->possibilities, (GFunc) free_entry, NULL);
-          g_list_free (typefind->possibilities);
-          typefind->possibilities = NULL;
-          stop_typefinding (typefind);
-        } else {
-          GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
-          stop_typefinding (typefind);
-          return GST_FLOW_ERROR;
-        }
-      }
+      res = gst_type_find_element_chain_do_typefinding (typefind);
 
       if (typefind->mode == MODE_ERROR)
         res = GST_FLOW_ERROR;
@@ -817,6 +544,56 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
   return res;
 }
 
+static GstFlowReturn
+gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind)
+{
+  GstTypeFindProbability probability;
+  GstCaps *caps;
+
+  if (GST_BUFFER_SIZE (typefind->store) < TYPE_FIND_MIN_SIZE) {
+    GST_DEBUG_OBJECT (typefind, "not enough data for typefinding yet "
+        "(%u bytes)", GST_BUFFER_SIZE (typefind->store));
+    return GST_FLOW_OK;
+  }
+
+  caps = gst_type_find_helper_for_buffer (GST_OBJECT (typefind),
+      typefind->store, &probability);
+
+  if (caps == NULL && GST_BUFFER_SIZE (typefind->store) > TYPE_FIND_MAX_SIZE) {
+    GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
+    stop_typefinding (typefind);
+    return GST_FLOW_ERROR;
+  } else if (caps == NULL) {
+    GST_DEBUG_OBJECT (typefind, "no caps found with %u bytes of data, "
+        "waiting for more data", GST_BUFFER_SIZE (typefind->store));
+    return GST_FLOW_OK;
+  }
+
+  /* found a type */
+  if (probability < typefind->min_probability) {
+    GST_DEBUG_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", but "
+        "probability is %u which is lower than the required minimum of %u",
+        caps, probability, typefind->min_probability);
+
+    if (GST_BUFFER_SIZE (typefind->store) >= TYPE_FIND_MAX_SIZE) {
+      GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
+      stop_typefinding (typefind);
+      return GST_FLOW_ERROR;
+    }
+
+    GST_DEBUG_OBJECT (typefind, "waiting for more data to try again");
+    return GST_FLOW_OK;
+  }
+
+  /* probability is good enough too, so let's make it known ... */
+  g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
+      probability, caps);
+
+  /* .. and send out the accumulated data */
+  stop_typefinding (typefind);
+  return GST_FLOW_OK;
+}
+
 static gboolean
 gst_type_find_element_checkgetrange (GstPad * srcpad)
 {
index 3ef30cc..f4dcec2 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <gst/gstinfo.h>
 #include <gst/gstelement.h>
-/* #include <gst/gstbufferstore.h> */
 #include "gstbufferstore.h"
 
 G_BEGIN_DECLS
@@ -59,10 +58,6 @@ struct _GstTypeFindElement {
 
   guint                        mode;
   GstBuffer *          store;
-  guint64              stream_length;
-  gboolean             stream_length_available;
-
-  GList *              possibilities;
 };
 
 struct _GstTypeFindElementClass {