/* creates/returns a list of CodecCap based on given filter function and caps */
static GList *
get_plugins_filtered_from_caps (FilterFunc filter,
                                GstCaps *caps,
                                GstPadDirection direction)
{
  GList *walk, *result;
  GstElementFactory *factory;
  GList *list = NULL;
  gboolean is_valid;
  GstCaps *matched_caps = NULL;

  result = gst_registry_get_feature_list (gst_registry_get_default (),
          GST_TYPE_ELEMENT_FACTORY);

  result = g_list_sort (result, (GCompareFunc) compare_ranks);

  walk = result;
  while (walk)
  {
    factory = GST_ELEMENT_FACTORY (walk->data);
    is_valid = FALSE;

    if (!filter (factory))
    {
      goto next;
    }

    if (caps)
    {
      if (check_caps_compatibility (factory, caps, &matched_caps))
      {
        is_valid = TRUE;
      }
    }

    if (is_valid || !caps)
    {
      if (!matched_caps)
      {
        list = create_codec_cap_list (factory, direction, list, NULL);
      }
      else
      {
        gint i;
        for (i = 0; i < gst_caps_get_size (matched_caps); i++)
        {
          GstStructure *structure = gst_caps_get_structure (matched_caps, i);
          GstCaps *cur_caps =
            gst_caps_new_full (gst_structure_copy (structure), NULL);

          list = create_codec_cap_list (factory, direction, list, cur_caps);
          gst_caps_unref (cur_caps);
        }
        gst_caps_unref (matched_caps);
      }
    }

next:
    walk = g_list_next (walk);
  }

  /*
  walk = result;
  while (walk)
  {
    factory = GST_ELEMENT_FACTORY (walk->data);
    DEBUG ("new refcnt is %d", GST_OBJECT_REFCOUNT_VALUE (GST_OBJECT (factory)));
    walk = g_list_next (walk);
  }
  */

  gst_plugin_feature_list_free (result);

  return list;
}
/* creates/returns a list of CodecCap based on given filter function and caps */
static GList *
get_plugins_filtered_from_caps (FilterFunc filter,
                                GstCaps *caps,
                                GstPadDirection direction)
{
  GList *walk, *result;
  GList *list = NULL;
  GstCaps *matched_caps = NULL;

  result = gst_registry_get_feature_list (gst_registry_get (),
          GST_TYPE_ELEMENT_FACTORY);

  result = g_list_sort (result, (GCompareFunc) compare_ranks);

  for (walk = result; walk; walk = walk->next)
  {
    GstElementFactory *factory = GST_ELEMENT_FACTORY (walk->data);

    /* Ignore unranked plugins */
    if (gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory)) ==
        GST_RANK_NONE)
      continue;

    if (!filter (factory))
      continue;

    if (caps && !check_caps_compatibility (factory, caps, &matched_caps))
      continue;

    if (!matched_caps)
    {
      list = create_codec_cap_list (factory, direction, list, NULL);
    }
    else
    {
      gint i;
      GPtrArray *capslist = g_ptr_array_new_with_free_func (
        (GDestroyNotify) gst_caps_unref);

      while (gst_caps_get_size (matched_caps) > 0)
      {
        GstCaps *stolencaps = gst_caps_new_full (
          gst_caps_steal_structure (matched_caps, 0), NULL);
        gboolean got_match = FALSE;

        for (i = 0; i < capslist->len; i++)
        {
          GstCaps *intersect = gst_caps_intersect (stolencaps,
              g_ptr_array_index (capslist, i));

          if (gst_caps_is_empty (intersect))
          {
            gst_caps_unref (intersect);
          }
          else
          {
            got_match = TRUE;
            gst_caps_unref (g_ptr_array_index (capslist, i));
            g_ptr_array_index (capslist, i) = intersect;
          }
        }

        if (got_match)
          gst_caps_unref (stolencaps);
        else
          g_ptr_array_add (capslist, stolencaps);

      }
      gst_caps_unref (matched_caps);

      for (i = 0; i < capslist->len; i++)
        list = create_codec_cap_list (factory, direction, list,
            g_ptr_array_index (capslist, i));
      g_ptr_array_unref (capslist);
    }
  }

  gst_plugin_feature_list_free (result);

  return list;
}