Blame gst/gstcaps.c

Packit f546b1
/* GStreamer
Packit f546b1
 * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
Packit f546b1
 *
Packit f546b1
 * This library is free software; you can redistribute it and/or
Packit f546b1
 * modify it under the terms of the GNU Library General Public
Packit f546b1
 * License as published by the Free Software Foundation; either
Packit f546b1
 * version 2 of the License, or (at your option) any later version.
Packit f546b1
 *
Packit f546b1
 * This library is distributed in the hope that it will be useful,
Packit f546b1
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit f546b1
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit f546b1
 * Library General Public License for more details.
Packit f546b1
 *
Packit f546b1
 * You should have received a copy of the GNU Library General Public
Packit f546b1
 * License along with this library; if not, write to the
Packit f546b1
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit f546b1
 * Boston, MA 02110-1301, USA.
Packit f546b1
 */
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * SECTION:gstcaps
Packit f546b1
 * @title: GstCaps
Packit f546b1
 * @short_description: Structure describing sets of media formats
Packit f546b1
 * @see_also: #GstStructure, #GstMiniObject
Packit f546b1
 *
Packit f546b1
 * Caps (capabilities) are lightweight refcounted objects describing media types.
Packit f546b1
 * They are composed of an array of #GstStructure.
Packit f546b1
 *
Packit f546b1
 * Caps are exposed on #GstPadTemplate to describe all possible types a
Packit f546b1
 * given pad can handle. They are also stored in the #GstRegistry along with
Packit f546b1
 * a description of the #GstElement.
Packit f546b1
 *
Packit f546b1
 * Caps are exposed on the element pads using the gst_pad_query_caps() pad
Packit f546b1
 * function. This function describes the possible types that the pad can
Packit f546b1
 * handle or produce at runtime.
Packit f546b1
 *
Packit f546b1
 * A #GstCaps can be constructed with the following code fragment:
Packit f546b1
 * |[
Packit f546b1
 *   GstCaps *caps = gst_caps_new_simple ("video/x-raw",
Packit f546b1
 *      "format", G_TYPE_STRING, "I420",
Packit f546b1
 *      "framerate", GST_TYPE_FRACTION, 25, 1,
Packit f546b1
 *      "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
Packit f546b1
 *      "width", G_TYPE_INT, 320,
Packit f546b1
 *      "height", G_TYPE_INT, 240,
Packit f546b1
 *      NULL);
Packit f546b1
 * ]|
Packit f546b1
 *
Packit f546b1
 * A #GstCaps is fixed when it has no properties with ranges or lists. Use
Packit f546b1
 * gst_caps_is_fixed() to test for fixed caps. Fixed caps can be used in a
Packit f546b1
 * caps event to notify downstream elements of the current media type.
Packit f546b1
 *
Packit f546b1
 * Various methods exist to work with the media types such as subtracting
Packit f546b1
 * or intersecting.
Packit f546b1
 *
Packit f546b1
 * Be aware that the current #GstCaps / #GstStructure serialization into string
Packit f546b1
 * has limited support for nested #GstCaps / #GstStructure fields. It can only
Packit f546b1
 * support one level of nesting. Using more levels will lead to unexpected
Packit f546b1
 * behavior when using serialization features, such as gst_caps_to_string() or
Packit f546b1
 * gst_value_serialize() and their counterparts.
Packit f546b1
 */
Packit f546b1
Packit f546b1
#ifdef HAVE_CONFIG_H
Packit f546b1
#include "config.h"
Packit f546b1
#endif
Packit f546b1
#include <string.h>
Packit f546b1
#include <signal.h>
Packit f546b1
Packit f546b1
#include "gst_private.h"
Packit f546b1
#include <gst/gst.h>
Packit f546b1
#include <gobject/gvaluecollector.h>
Packit f546b1
Packit f546b1
#define DEBUG_REFCOUNT
Packit f546b1
Packit f546b1
typedef struct _GstCapsArrayElement
Packit f546b1
{
Packit f546b1
  GstStructure *structure;
Packit f546b1
  GstCapsFeatures *features;
Packit f546b1
} GstCapsArrayElement;
Packit f546b1
Packit f546b1
typedef struct _GstCapsImpl
Packit f546b1
{
Packit f546b1
  GstCaps caps;
Packit f546b1
Packit f546b1
  GArray *array;
Packit f546b1
} GstCapsImpl;
Packit f546b1
Packit f546b1
#define GST_CAPS_ARRAY(c) (((GstCapsImpl *)(c))->array)
Packit f546b1
Packit f546b1
#define GST_CAPS_LEN(c)   (GST_CAPS_ARRAY(c)->len)
Packit f546b1
Packit f546b1
#define IS_WRITABLE(caps) \
Packit f546b1
  (GST_CAPS_REFCOUNT_VALUE (caps) == 1)
Packit f546b1
Packit f546b1
/* same as gst_caps_is_any () */
Packit f546b1
#define CAPS_IS_ANY(caps)				\
Packit f546b1
  (!!(GST_CAPS_FLAGS(caps) & GST_CAPS_FLAG_ANY))
Packit f546b1
Packit f546b1
/* same as gst_caps_is_empty () */
Packit f546b1
#define CAPS_IS_EMPTY(caps)				\
Packit f546b1
  (!CAPS_IS_ANY(caps) && CAPS_IS_EMPTY_SIMPLE(caps))
Packit f546b1
Packit f546b1
#define CAPS_IS_EMPTY_SIMPLE(caps)					\
Packit f546b1
  ((GST_CAPS_ARRAY (caps) == NULL) || (GST_CAPS_LEN (caps) == 0))
Packit f546b1
Packit f546b1
#define gst_caps_features_copy_conditional(f) ((f && (gst_caps_features_is_any (f) || !gst_caps_features_is_equal (f, GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))) ? gst_caps_features_copy (f) : NULL)
Packit f546b1
Packit f546b1
/* quick way to get a caps structure at an index without doing a type or array
Packit f546b1
 * length check */
Packit f546b1
#define gst_caps_get_structure_unchecked(caps, index) \
Packit f546b1
     (g_array_index (GST_CAPS_ARRAY (caps), GstCapsArrayElement, (index)).structure)
Packit f546b1
#define gst_caps_get_features_storage_unchecked(caps, index) \
Packit f546b1
     (&g_array_index (GST_CAPS_ARRAY (caps), GstCapsArrayElement, (index)).features)
Packit f546b1
#define gst_caps_get_features_unchecked(caps, index) \
Packit f546b1
     (g_atomic_pointer_get (gst_caps_get_features_storage_unchecked (caps, index)))
Packit f546b1
/* quick way to append a structure without checking the args */
Packit f546b1
#define gst_caps_append_structure_unchecked(caps, s, f) G_STMT_START{\
Packit f546b1
  GstCapsArrayElement __e={s, f};                                      \
Packit f546b1
  if (gst_structure_set_parent_refcount (__e.structure, &GST_MINI_OBJECT_REFCOUNT(caps)) && \
Packit f546b1
      (!__e.features || gst_caps_features_set_parent_refcount (__e.features, &GST_MINI_OBJECT_REFCOUNT(caps))))         \
Packit f546b1
    g_array_append_val (GST_CAPS_ARRAY (caps), __e);                             \
Packit f546b1
}G_STMT_END
Packit f546b1
Packit f546b1
/* lock to protect multiple invocations of static caps to caps conversion */
Packit f546b1
G_LOCK_DEFINE_STATIC (static_caps_lock);
Packit f546b1
Packit f546b1
static void gst_caps_transform_to_string (const GValue * src_value,
Packit f546b1
    GValue * dest_value);
Packit f546b1
static gboolean gst_caps_from_string_inplace (GstCaps * caps,
Packit f546b1
    const gchar * string);
Packit f546b1
Packit f546b1
GType _gst_caps_type = 0;
Packit f546b1
GstCaps *_gst_caps_any;
Packit f546b1
GstCaps *_gst_caps_none;
Packit f546b1
Packit f546b1
GST_DEFINE_MINI_OBJECT_TYPE (GstCaps, gst_caps);
Packit f546b1
Packit f546b1
void
Packit f546b1
_priv_gst_caps_initialize (void)
Packit f546b1
{
Packit f546b1
  _gst_caps_type = gst_caps_get_type ();
Packit f546b1
Packit f546b1
  _gst_caps_any = gst_caps_new_any ();
Packit f546b1
  _gst_caps_none = gst_caps_new_empty ();
Packit f546b1
Packit f546b1
  g_value_register_transform_func (_gst_caps_type,
Packit f546b1
      G_TYPE_STRING, gst_caps_transform_to_string);
Packit f546b1
}
Packit f546b1
Packit f546b1
void
Packit f546b1
_priv_gst_caps_cleanup (void)
Packit f546b1
{
Packit f546b1
  gst_caps_unref (_gst_caps_any);
Packit f546b1
  _gst_caps_any = NULL;
Packit f546b1
  gst_caps_unref (_gst_caps_none);
Packit f546b1
  _gst_caps_none = NULL;
Packit f546b1
}
Packit f546b1
Packit f546b1
GstCapsFeatures *
Packit f546b1
__gst_caps_get_features_unchecked (const GstCaps * caps, guint idx)
Packit f546b1
{
Packit f546b1
  return gst_caps_get_features_unchecked (caps, idx);
Packit f546b1
}
Packit f546b1
Packit f546b1
static GstCaps *
Packit f546b1
_gst_caps_copy (const GstCaps * caps)
Packit f546b1
{
Packit f546b1
  GstCaps *newcaps;
Packit f546b1
  GstStructure *structure;
Packit f546b1
  GstCapsFeatures *features;
Packit f546b1
  guint i, n;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
Packit f546b1
Packit f546b1
  newcaps = gst_caps_new_empty ();
Packit f546b1
  GST_CAPS_FLAGS (newcaps) = GST_CAPS_FLAGS (caps);
Packit f546b1
  n = GST_CAPS_LEN (caps);
Packit f546b1
Packit f546b1
  GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, caps, "doing copy %p -> %p",
Packit f546b1
      caps, newcaps);
Packit f546b1
Packit f546b1
  for (i = 0; i < n; i++) {
Packit f546b1
    structure = gst_caps_get_structure_unchecked (caps, i);
Packit f546b1
    features = gst_caps_get_features_unchecked (caps, i);
Packit f546b1
    gst_caps_append_structure_full (newcaps, gst_structure_copy (structure),
Packit f546b1
        gst_caps_features_copy_conditional (features));
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return newcaps;
Packit f546b1
}
Packit f546b1
Packit f546b1
/* creation/deletion */
Packit f546b1
static void
Packit f546b1
_gst_caps_free (GstCaps * caps)
Packit f546b1
{
Packit f546b1
  GstStructure *structure;
Packit f546b1
  GstCapsFeatures *features;
Packit f546b1
  guint i, len;
Packit f546b1
Packit f546b1
  /* The refcount must be 0, but since we're only called by gst_caps_unref,
Packit f546b1
   * don't bother testing. */
Packit f546b1
  len = GST_CAPS_LEN (caps);
Packit f546b1
  /* This can be used to get statistics about caps sizes */
Packit f546b1
  /*GST_CAT_INFO (GST_CAT_CAPS, "caps size: %d", len); */
Packit f546b1
  for (i = 0; i < len; i++) {
Packit f546b1
    structure = gst_caps_get_structure_unchecked (caps, i);
Packit f546b1
    gst_structure_set_parent_refcount (structure, NULL);
Packit f546b1
    gst_structure_free (structure);
Packit f546b1
    features = gst_caps_get_features_unchecked (caps, i);
Packit f546b1
    if (features) {
Packit f546b1
      gst_caps_features_set_parent_refcount (features, NULL);
Packit f546b1
      gst_caps_features_free (features);
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
  g_array_free (GST_CAPS_ARRAY (caps), TRUE);
Packit f546b1
Packit f546b1
#ifdef DEBUG_REFCOUNT
Packit f546b1
  GST_CAT_TRACE (GST_CAT_CAPS, "freeing caps %p", caps);
Packit f546b1
#endif
Packit f546b1
  g_slice_free1 (sizeof (GstCapsImpl), caps);
Packit f546b1
}
Packit f546b1
Packit f546b1
static void
Packit f546b1
gst_caps_init (GstCaps * caps)
Packit f546b1
{
Packit f546b1
  gst_mini_object_init (GST_MINI_OBJECT_CAST (caps), 0, _gst_caps_type,
Packit f546b1
      (GstMiniObjectCopyFunction) _gst_caps_copy, NULL,
Packit f546b1
      (GstMiniObjectFreeFunction) _gst_caps_free);
Packit f546b1
Packit f546b1
  /* the 32 has been determined by logging caps sizes in _gst_caps_free
Packit f546b1
   * but g_ptr_array uses 16 anyway if it expands once, so this does not help
Packit f546b1
   * in practice
Packit f546b1
   * GST_CAPS_ARRAY (caps) = g_ptr_array_sized_new (32);
Packit f546b1
   */
Packit f546b1
  GST_CAPS_ARRAY (caps) =
Packit f546b1
      g_array_new (FALSE, TRUE, sizeof (GstCapsArrayElement));
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_new_empty:
Packit f546b1
 *
Packit f546b1
 * Creates a new #GstCaps that is empty.  That is, the returned
Packit f546b1
 * #GstCaps contains no media formats.
Packit f546b1
 * The #GstCaps is guaranteed to be writable.
Packit f546b1
 * Caller is responsible for unreffing the returned caps.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the new #GstCaps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_new_empty (void)
Packit f546b1
{
Packit f546b1
  GstCaps *caps;
Packit f546b1
Packit f546b1
  caps = (GstCaps *) g_slice_new (GstCapsImpl);
Packit f546b1
Packit f546b1
  gst_caps_init (caps);
Packit f546b1
Packit f546b1
#ifdef DEBUG_REFCOUNT
Packit f546b1
  GST_CAT_TRACE (GST_CAT_CAPS, "created caps %p", caps);
Packit f546b1
#endif
Packit f546b1
Packit f546b1
  return caps;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_new_any:
Packit f546b1
 *
Packit f546b1
 * Creates a new #GstCaps that indicates that it is compatible with
Packit f546b1
 * any media format.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the new #GstCaps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_new_any (void)
Packit f546b1
{
Packit f546b1
  GstCaps *caps = gst_caps_new_empty ();
Packit f546b1
Packit f546b1
  GST_CAPS_FLAG_SET (caps, GST_CAPS_FLAG_ANY);
Packit f546b1
Packit f546b1
  return caps;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_new_empty_simple:
Packit f546b1
 * @media_type: the media type of the structure
Packit f546b1
 *
Packit f546b1
 * Creates a new #GstCaps that contains one #GstStructure with name
Packit f546b1
 * @media_type.
Packit f546b1
 * Caller is responsible for unreffing the returned caps.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the new #GstCaps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_new_empty_simple (const char *media_type)
Packit f546b1
{
Packit f546b1
  GstCaps *caps;
Packit f546b1
  GstStructure *structure;
Packit f546b1
Packit f546b1
  caps = gst_caps_new_empty ();
Packit f546b1
  structure = gst_structure_new_empty (media_type);
Packit f546b1
  if (structure)
Packit f546b1
    gst_caps_append_structure_unchecked (caps, structure, NULL);
Packit f546b1
Packit f546b1
  return caps;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_new_simple:
Packit f546b1
 * @media_type: the media type of the structure
Packit f546b1
 * @fieldname: first field to set
Packit f546b1
 * @...: additional arguments
Packit f546b1
 *
Packit f546b1
 * Creates a new #GstCaps that contains one #GstStructure.  The
Packit f546b1
 * structure is defined by the arguments, which have the same format
Packit f546b1
 * as gst_structure_new().
Packit f546b1
 * Caller is responsible for unreffing the returned caps.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the new #GstCaps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_new_simple (const char *media_type, const char *fieldname, ...)
Packit f546b1
{
Packit f546b1
  GstCaps *caps;
Packit f546b1
  GstStructure *structure;
Packit f546b1
  va_list var_args;
Packit f546b1
Packit f546b1
  caps = gst_caps_new_empty ();
Packit f546b1
Packit f546b1
  va_start (var_args, fieldname);
Packit f546b1
  structure = gst_structure_new_valist (media_type, fieldname, var_args);
Packit f546b1
  va_end (var_args);
Packit f546b1
Packit f546b1
  if (structure)
Packit f546b1
    gst_caps_append_structure_unchecked (caps, structure, NULL);
Packit f546b1
  else
Packit f546b1
    gst_caps_replace (&caps, NULL);
Packit f546b1
Packit f546b1
  return caps;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_new_full:
Packit f546b1
 * @struct1: the first structure to add
Packit f546b1
 * @...: additional structures to add
Packit f546b1
 *
Packit f546b1
 * Creates a new #GstCaps and adds all the structures listed as
Packit f546b1
 * arguments.  The list must be %NULL-terminated.  The structures
Packit f546b1
 * are not copied; the returned #GstCaps owns the structures.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the new #GstCaps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_new_full (GstStructure * struct1, ...)
Packit f546b1
{
Packit f546b1
  GstCaps *caps;
Packit f546b1
  va_list var_args;
Packit f546b1
Packit f546b1
  va_start (var_args, struct1);
Packit f546b1
  caps = gst_caps_new_full_valist (struct1, var_args);
Packit f546b1
  va_end (var_args);
Packit f546b1
Packit f546b1
  return caps;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_new_full_valist:
Packit f546b1
 * @structure: the first structure to add
Packit f546b1
 * @var_args: additional structures to add
Packit f546b1
 *
Packit f546b1
 * Creates a new #GstCaps and adds all the structures listed as
Packit f546b1
 * arguments.  The list must be %NULL-terminated.  The structures
Packit f546b1
 * are not copied; the returned #GstCaps owns the structures.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the new #GstCaps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_new_full_valist (GstStructure * structure, va_list var_args)
Packit f546b1
{
Packit f546b1
  GstCaps *caps;
Packit f546b1
Packit f546b1
  caps = gst_caps_new_empty ();
Packit f546b1
Packit f546b1
  while (structure) {
Packit f546b1
    gst_caps_append_structure_unchecked (caps, structure, NULL);
Packit f546b1
    structure = va_arg (var_args, GstStructure *);
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return caps;
Packit f546b1
}
Packit f546b1
Packit f546b1
G_DEFINE_POINTER_TYPE (GstStaticCaps, gst_static_caps);
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_static_caps_get:
Packit f546b1
 * @static_caps: the #GstStaticCaps to convert
Packit f546b1
 *
Packit f546b1
 * Converts a #GstStaticCaps to a #GstCaps.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full) (nullable): a pointer to the #GstCaps. Unref
Packit f546b1
 *     after usage. Since the core holds an additional ref to the
Packit f546b1
 *     returned caps, use gst_caps_make_writable() on the returned caps
Packit f546b1
 *     to modify it.
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_static_caps_get (GstStaticCaps * static_caps)
Packit f546b1
{
Packit f546b1
  GstCaps **caps;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (static_caps != NULL, NULL);
Packit f546b1
Packit f546b1
  caps = &static_caps->caps;
Packit f546b1
Packit f546b1
  /* refcount is 0 when we need to convert */
Packit f546b1
  if (G_UNLIKELY (*caps == NULL)) {
Packit f546b1
    const char *string;
Packit f546b1
Packit f546b1
    G_LOCK (static_caps_lock);
Packit f546b1
    /* check if other thread already updated */
Packit f546b1
    if (G_UNLIKELY (*caps != NULL))
Packit f546b1
      goto done;
Packit f546b1
Packit f546b1
    string = static_caps->string;
Packit f546b1
Packit f546b1
    if (G_UNLIKELY (string == NULL))
Packit f546b1
      goto no_string;
Packit f546b1
Packit f546b1
    *caps = gst_caps_from_string (string);
Packit f546b1
Packit f546b1
    /* convert to string */
Packit f546b1
    if (G_UNLIKELY (*caps == NULL)) {
Packit f546b1
      g_critical ("Could not convert static caps \"%s\"", string);
Packit f546b1
      goto done;
Packit f546b1
    }
Packit f546b1
Packit f546b1
    /* Caps generated from static caps are usually leaked */
Packit f546b1
    GST_MINI_OBJECT_FLAG_SET (*caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
Packit f546b1
Packit f546b1
    GST_CAT_TRACE (GST_CAT_CAPS, "created %p from string %s", static_caps,
Packit f546b1
        string);
Packit f546b1
  done:
Packit f546b1
    G_UNLOCK (static_caps_lock);
Packit f546b1
  }
Packit f546b1
  /* ref the caps, makes it not writable */
Packit f546b1
  if (G_LIKELY (*caps != NULL))
Packit f546b1
    gst_caps_ref (*caps);
Packit f546b1
Packit f546b1
  return *caps;
Packit f546b1
Packit f546b1
  /* ERRORS */
Packit f546b1
no_string:
Packit f546b1
  {
Packit f546b1
    G_UNLOCK (static_caps_lock);
Packit f546b1
    g_warning ("static caps %p string is NULL", static_caps);
Packit f546b1
    return NULL;
Packit f546b1
  }
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_static_caps_cleanup:
Packit f546b1
 * @static_caps: the #GstStaticCaps to clean
Packit f546b1
 *
Packit f546b1
 * Clean up the cached caps contained in @static_caps.
Packit f546b1
 */
Packit f546b1
void
Packit f546b1
gst_static_caps_cleanup (GstStaticCaps * static_caps)
Packit f546b1
{
Packit f546b1
  G_LOCK (static_caps_lock);
Packit f546b1
  gst_caps_replace (&static_caps->caps, NULL);
Packit f546b1
  G_UNLOCK (static_caps_lock);
Packit f546b1
}
Packit f546b1
Packit f546b1
/* manipulation */
Packit f546b1
Packit f546b1
static void
Packit f546b1
gst_caps_remove_and_get_structure_and_features (GstCaps * caps, guint idx,
Packit f546b1
    GstStructure ** s, GstCapsFeatures ** f)
Packit f546b1
{
Packit f546b1
  GstStructure *s_;
Packit f546b1
  GstCapsFeatures *f_;
Packit f546b1
Packit f546b1
  s_ = gst_caps_get_structure_unchecked (caps, idx);
Packit f546b1
  f_ = gst_caps_get_features_unchecked (caps, idx);
Packit f546b1
Packit f546b1
  /* don't use index_fast, gst_caps_simplify relies on the order */
Packit f546b1
  g_array_remove_index (GST_CAPS_ARRAY (caps), idx);
Packit f546b1
Packit f546b1
  gst_structure_set_parent_refcount (s_, NULL);
Packit f546b1
  if (f_) {
Packit f546b1
    gst_caps_features_set_parent_refcount (f_, NULL);
Packit f546b1
  }
Packit f546b1
Packit f546b1
  *s = s_;
Packit f546b1
  *f = f_;
Packit f546b1
}
Packit f546b1
Packit f546b1
static GstStructure *
Packit f546b1
gst_caps_remove_and_get_structure (GstCaps * caps, guint idx)
Packit f546b1
{
Packit f546b1
  GstStructure *s;
Packit f546b1
  GstCapsFeatures *f;
Packit f546b1
Packit f546b1
  gst_caps_remove_and_get_structure_and_features (caps, idx, &s, &f);
Packit f546b1
Packit f546b1
  if (f)
Packit f546b1
    gst_caps_features_free (f);
Packit f546b1
Packit f546b1
  return s;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_steal_structure:
Packit f546b1
 * @caps: the #GstCaps to retrieve from
Packit f546b1
 * @index: Index of the structure to retrieve
Packit f546b1
 *
Packit f546b1
 * Retrieves the structure with the given index from the list of structures
Packit f546b1
 * contained in @caps. The caller becomes the owner of the returned structure.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full) (nullable): a pointer to the #GstStructure
Packit f546b1
 *     corresponding to @index.
Packit f546b1
 */
Packit f546b1
GstStructure *
Packit f546b1
gst_caps_steal_structure (GstCaps * caps, guint index)
Packit f546b1
{
Packit f546b1
  g_return_val_if_fail (caps != NULL, NULL);
Packit f546b1
  g_return_val_if_fail (IS_WRITABLE (caps), NULL);
Packit f546b1
Packit f546b1
  if (G_UNLIKELY (index >= GST_CAPS_LEN (caps)))
Packit f546b1
    return NULL;
Packit f546b1
Packit f546b1
  return gst_caps_remove_and_get_structure (caps, index);
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_append:
Packit f546b1
 * @caps1: the #GstCaps that will be appended to
Packit f546b1
 * @caps2: (transfer full): the #GstCaps to append
Packit f546b1
 *
Packit f546b1
 * Appends the structures contained in @caps2 to @caps1. The structures in
Packit f546b1
 * @caps2 are not copied -- they are transferred to @caps1, and then @caps2 is
Packit f546b1
 * freed. If either caps is ANY, the resulting caps will be ANY.
Packit f546b1
 */
Packit f546b1
void
Packit f546b1
gst_caps_append (GstCaps * caps1, GstCaps * caps2)
Packit f546b1
{
Packit f546b1
  GstStructure *structure;
Packit f546b1
  GstCapsFeatures *features;
Packit f546b1
  int i;
Packit f546b1
Packit f546b1
  g_return_if_fail (GST_IS_CAPS (caps1));
Packit f546b1
  g_return_if_fail (GST_IS_CAPS (caps2));
Packit f546b1
  g_return_if_fail (IS_WRITABLE (caps1));
Packit f546b1
Packit f546b1
  if (G_UNLIKELY (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))) {
Packit f546b1
    GST_CAPS_FLAGS (caps1) |= GST_CAPS_FLAG_ANY;
Packit f546b1
    gst_caps_unref (caps2);
Packit f546b1
  } else {
Packit f546b1
    caps2 = gst_caps_make_writable (caps2);
Packit f546b1
Packit f546b1
    for (i = GST_CAPS_LEN (caps2); i; i--) {
Packit f546b1
      gst_caps_remove_and_get_structure_and_features (caps2, 0, &structure,
Packit f546b1
          &features);
Packit f546b1
      gst_caps_append_structure_unchecked (caps1, structure, features);
Packit f546b1
    }
Packit f546b1
    gst_caps_unref (caps2);     /* guaranteed to free it */
Packit f546b1
  }
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_merge:
Packit f546b1
 * @caps1: (transfer full): the #GstCaps that will take the new entries
Packit f546b1
 * @caps2: (transfer full): the #GstCaps to merge in
Packit f546b1
 *
Packit f546b1
 * Appends the structures contained in @caps2 to @caps1 if they are not yet
Packit f546b1
 * expressed by @caps1. The structures in @caps2 are not copied -- they are
Packit f546b1
 * transferred to a writable copy of @caps1, and then @caps2 is freed.
Packit f546b1
 * If either caps is ANY, the resulting caps will be ANY.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the merged caps.
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_merge (GstCaps * caps1, GstCaps * caps2)
Packit f546b1
{
Packit f546b1
  GstStructure *structure;
Packit f546b1
  GstCapsFeatures *features;
Packit f546b1
  int i;
Packit f546b1
  GstCaps *result;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps1), NULL);
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps2), NULL);
Packit f546b1
Packit f546b1
  if (G_UNLIKELY (CAPS_IS_ANY (caps1))) {
Packit f546b1
    gst_caps_unref (caps2);
Packit f546b1
    result = caps1;
Packit f546b1
  } else if (G_UNLIKELY (CAPS_IS_ANY (caps2))) {
Packit f546b1
    gst_caps_unref (caps1);
Packit f546b1
    result = caps2;
Packit f546b1
  } else {
Packit f546b1
    caps2 = gst_caps_make_writable (caps2);
Packit f546b1
Packit f546b1
    for (i = GST_CAPS_LEN (caps2); i; i--) {
Packit f546b1
      gst_caps_remove_and_get_structure_and_features (caps2, 0, &structure,
Packit f546b1
          &features);
Packit f546b1
      caps1 = gst_caps_merge_structure_full (caps1, structure, features);
Packit f546b1
    }
Packit f546b1
    gst_caps_unref (caps2);
Packit f546b1
    result = caps1;
Packit f546b1
Packit f546b1
    /* this is too naive
Packit f546b1
       GstCaps *com = gst_caps_intersect (caps1, caps2);
Packit f546b1
       GstCaps *add = gst_caps_subtract (caps2, com);
Packit f546b1
Packit f546b1
       GST_DEBUG ("common : %d", gst_caps_get_size (com));
Packit f546b1
       GST_DEBUG ("adding : %d", gst_caps_get_size (add));
Packit f546b1
       gst_caps_append (caps1, add);
Packit f546b1
       gst_caps_unref (com);
Packit f546b1
     */
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return result;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_append_structure:
Packit f546b1
 * @caps: the #GstCaps that will be appended to
Packit f546b1
 * @structure: (transfer full): the #GstStructure to append
Packit f546b1
 *
Packit f546b1
 * Appends @structure to @caps.  The structure is not copied; @caps
Packit f546b1
 * becomes the owner of @structure.
Packit f546b1
 */
Packit f546b1
void
Packit f546b1
gst_caps_append_structure (GstCaps * caps, GstStructure * structure)
Packit f546b1
{
Packit f546b1
  g_return_if_fail (GST_IS_CAPS (caps));
Packit f546b1
  g_return_if_fail (IS_WRITABLE (caps));
Packit f546b1
Packit f546b1
  if (G_LIKELY (structure)) {
Packit f546b1
    gst_caps_append_structure_unchecked (caps, structure, NULL);
Packit f546b1
  }
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_append_structure_full:
Packit f546b1
 * @caps: the #GstCaps that will be appended to
Packit f546b1
 * @structure: (transfer full): the #GstStructure to append
Packit f546b1
 * @features: (transfer full) (allow-none): the #GstCapsFeatures to append
Packit f546b1
 *
Packit f546b1
 * Appends @structure with @features to @caps.  The structure is not copied; @caps
Packit f546b1
 * becomes the owner of @structure.
Packit f546b1
 *
Packit f546b1
 * Since: 1.2
Packit f546b1
 */
Packit f546b1
void
Packit f546b1
gst_caps_append_structure_full (GstCaps * caps, GstStructure * structure,
Packit f546b1
    GstCapsFeatures * features)
Packit f546b1
{
Packit f546b1
  g_return_if_fail (GST_IS_CAPS (caps));
Packit f546b1
  g_return_if_fail (IS_WRITABLE (caps));
Packit f546b1
Packit f546b1
  if (G_LIKELY (structure)) {
Packit f546b1
    gst_caps_append_structure_unchecked (caps, structure, features);
Packit f546b1
  }
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_remove_structure:
Packit f546b1
 * @caps: the #GstCaps to remove from
Packit f546b1
 * @idx: Index of the structure to remove
Packit f546b1
 *
Packit f546b1
 * removes the structure with the given index from the list of structures
Packit f546b1
 * contained in @caps.
Packit f546b1
 */
Packit f546b1
void
Packit f546b1
gst_caps_remove_structure (GstCaps * caps, guint idx)
Packit f546b1
{
Packit f546b1
  GstStructure *structure;
Packit f546b1
Packit f546b1
  g_return_if_fail (caps != NULL);
Packit f546b1
  g_return_if_fail (idx <= gst_caps_get_size (caps));
Packit f546b1
  g_return_if_fail (IS_WRITABLE (caps));
Packit f546b1
Packit f546b1
  structure = gst_caps_remove_and_get_structure (caps, idx);
Packit f546b1
  gst_structure_free (structure);
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_merge_structure:
Packit f546b1
 * @caps: (transfer full): the #GstCaps to merge into
Packit f546b1
 * @structure: (transfer full): the #GstStructure to merge
Packit f546b1
 *
Packit f546b1
 * Appends @structure to @caps if its not already expressed by @caps.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the merged caps.
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_merge_structure (GstCaps * caps, GstStructure * structure)
Packit f546b1
{
Packit f546b1
  GstStructure *structure1;
Packit f546b1
  GstCapsFeatures *features1;
Packit f546b1
  int i;
Packit f546b1
  gboolean unique = TRUE;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
Packit f546b1
Packit f546b1
  if (G_UNLIKELY (structure == NULL))
Packit f546b1
    return caps;
Packit f546b1
Packit f546b1
  /* check each structure */
Packit f546b1
  for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
Packit f546b1
    structure1 = gst_caps_get_structure_unchecked (caps, i);
Packit f546b1
    features1 = gst_caps_get_features_unchecked (caps, i);
Packit f546b1
    if (!features1)
Packit f546b1
      features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
Packit f546b1
    /* if structure is a subset of structure1 and the
Packit f546b1
     * there are no existing features, then skip it */
Packit f546b1
    if (gst_caps_features_is_equal (features1,
Packit f546b1
            GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY)
Packit f546b1
        && gst_structure_is_subset (structure, structure1)) {
Packit f546b1
      unique = FALSE;
Packit f546b1
      break;
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
  if (unique) {
Packit f546b1
    caps = gst_caps_make_writable (caps);
Packit f546b1
    gst_caps_append_structure_unchecked (caps, structure, NULL);
Packit f546b1
  } else {
Packit f546b1
    gst_structure_free (structure);
Packit f546b1
  }
Packit f546b1
  return caps;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_merge_structure_full:
Packit f546b1
 * @caps: (transfer full): the #GstCaps to merge into
Packit f546b1
 * @structure: (transfer full): the #GstStructure to merge
Packit f546b1
 * @features: (transfer full) (allow-none): the #GstCapsFeatures to merge
Packit f546b1
 *
Packit f546b1
 * Appends @structure with @features to @caps if its not already expressed by @caps.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the merged caps.
Packit f546b1
 *
Packit f546b1
 * Since: 1.2
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_merge_structure_full (GstCaps * caps, GstStructure * structure,
Packit f546b1
    GstCapsFeatures * features)
Packit f546b1
{
Packit f546b1
  GstStructure *structure1;
Packit f546b1
  GstCapsFeatures *features1, *features_tmp;
Packit f546b1
  int i;
Packit f546b1
  gboolean unique = TRUE;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
Packit f546b1
Packit f546b1
  if (G_UNLIKELY (structure == NULL))
Packit f546b1
    return caps;
Packit f546b1
Packit f546b1
  /* To make comparisons easier below */
Packit f546b1
  features_tmp = features ? features : GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
Packit f546b1
  /* check each structure */
Packit f546b1
  for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
Packit f546b1
    structure1 = gst_caps_get_structure_unchecked (caps, i);
Packit f546b1
    features1 = gst_caps_get_features_unchecked (caps, i);
Packit f546b1
    if (!features1)
Packit f546b1
      features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
    /* if structure is a subset of structure1 and the
Packit f546b1
     * the features are a subset, then skip it */
Packit f546b1
    /* FIXME: We only skip if none of the features are
Packit f546b1
     * ANY and are still equal. That way all ANY structures
Packit f546b1
     * show up in the caps and no non-ANY structures are
Packit f546b1
     * swallowed by ANY structures
Packit f546b1
     */
Packit f546b1
    if (((!gst_caps_features_is_any (features_tmp)
Packit f546b1
                || gst_caps_features_is_any (features1))
Packit f546b1
            && gst_caps_features_is_equal (features_tmp, features1))
Packit f546b1
        && gst_structure_is_subset (structure, structure1)) {
Packit f546b1
      unique = FALSE;
Packit f546b1
      break;
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
  if (unique) {
Packit f546b1
    caps = gst_caps_make_writable (caps);
Packit f546b1
    gst_caps_append_structure_unchecked (caps, structure, features);
Packit f546b1
  } else {
Packit f546b1
    gst_structure_free (structure);
Packit f546b1
    if (features)
Packit f546b1
      gst_caps_features_free (features);
Packit f546b1
  }
Packit f546b1
  return caps;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_get_size:
Packit f546b1
 * @caps: a #GstCaps
Packit f546b1
 *
Packit f546b1
 * Gets the number of structures contained in @caps.
Packit f546b1
 *
Packit f546b1
 * Returns: the number of structures that @caps contains
Packit f546b1
 */
Packit f546b1
guint
Packit f546b1
gst_caps_get_size (const GstCaps * caps)
Packit f546b1
{
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), 0);
Packit f546b1
Packit f546b1
  return GST_CAPS_LEN (caps);
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_get_structure:
Packit f546b1
 * @caps: a #GstCaps
Packit f546b1
 * @index: the index of the structure
Packit f546b1
 *
Packit f546b1
 * Finds the structure in @caps that has the index @index, and
Packit f546b1
 * returns it.
Packit f546b1
 *
Packit f546b1
 * WARNING: This function takes a const GstCaps *, but returns a
Packit f546b1
 * non-const GstStructure *.  This is for programming convenience --
Packit f546b1
 * the caller should be aware that structures inside a constant
Packit f546b1
 * #GstCaps should not be modified. However, if you know the caps
Packit f546b1
 * are writable, either because you have just copied them or made
Packit f546b1
 * them writable with gst_caps_make_writable(), you may modify the
Packit f546b1
 * structure returned in the usual way, e.g. with functions like
Packit f546b1
 * gst_structure_set().
Packit f546b1
 *
Packit f546b1
 * You do not need to free or unref the structure returned, it
Packit f546b1
 * belongs to the #GstCaps.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer none): a pointer to the #GstStructure corresponding
Packit f546b1
 *     to @index
Packit f546b1
 */
Packit f546b1
GstStructure *
Packit f546b1
gst_caps_get_structure (const GstCaps * caps, guint index)
Packit f546b1
{
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
Packit f546b1
  g_return_val_if_fail (index < GST_CAPS_LEN (caps), NULL);
Packit f546b1
Packit f546b1
  return gst_caps_get_structure_unchecked (caps, index);
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_get_features:
Packit f546b1
 * @caps: a #GstCaps
Packit f546b1
 * @index: the index of the structure
Packit f546b1
 *
Packit f546b1
 * Finds the features in @caps that has the index @index, and
Packit f546b1
 * returns it.
Packit f546b1
 *
Packit f546b1
 * WARNING: This function takes a const GstCaps *, but returns a
Packit f546b1
 * non-const GstCapsFeatures *.  This is for programming convenience --
Packit f546b1
 * the caller should be aware that structures inside a constant
Packit f546b1
 * #GstCaps should not be modified. However, if you know the caps
Packit f546b1
 * are writable, either because you have just copied them or made
Packit f546b1
 * them writable with gst_caps_make_writable(), you may modify the
Packit f546b1
 * features returned in the usual way, e.g. with functions like
Packit f546b1
 * gst_caps_features_add().
Packit f546b1
 *
Packit f546b1
 * You do not need to free or unref the structure returned, it
Packit f546b1
 * belongs to the #GstCaps.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer none) (nullable): a pointer to the #GstCapsFeatures
Packit f546b1
 *     corresponding to @index
Packit f546b1
 *
Packit f546b1
 * Since: 1.2
Packit f546b1
 */
Packit f546b1
GstCapsFeatures *
Packit f546b1
gst_caps_get_features (const GstCaps * caps, guint index)
Packit f546b1
{
Packit f546b1
  GstCapsFeatures *features;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
Packit f546b1
  g_return_val_if_fail (index < GST_CAPS_LEN (caps), NULL);
Packit f546b1
Packit f546b1
  features = gst_caps_get_features_unchecked (caps, index);
Packit f546b1
  if (!features) {
Packit f546b1
    GstCapsFeatures **storage;
Packit f546b1
Packit f546b1
    /* We have to do some atomic pointer magic here as the caps
Packit f546b1
     * might not be writable and someone else calls this function
Packit f546b1
     * at the very same time */
Packit f546b1
    features = gst_caps_features_copy (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY);
Packit f546b1
    gst_caps_features_set_parent_refcount (features, &GST_CAPS_REFCOUNT (caps));
Packit f546b1
Packit f546b1
    storage = gst_caps_get_features_storage_unchecked (caps, index);
Packit f546b1
    if (!g_atomic_pointer_compare_and_exchange (storage, NULL, features)) {
Packit f546b1
      /* Someone did the same we just tried in the meantime */
Packit f546b1
      gst_caps_features_set_parent_refcount (features, NULL);
Packit f546b1
      gst_caps_features_free (features);
Packit f546b1
Packit f546b1
      features = gst_caps_get_features_unchecked (caps, index);
Packit f546b1
      g_assert (features != NULL);
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return features;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_set_features:
Packit f546b1
 * @caps: a #GstCaps
Packit f546b1
 * @index: the index of the structure
Packit f546b1
 * @features: (allow-none) (transfer full): the #GstCapsFeatures to set
Packit f546b1
 *
Packit f546b1
 * Sets the #GstCapsFeatures @features for the structure at @index.
Packit f546b1
 *
Packit f546b1
 * Since: 1.2
Packit f546b1
 */
Packit f546b1
void
Packit f546b1
gst_caps_set_features (GstCaps * caps, guint index, GstCapsFeatures * features)
Packit f546b1
{
Packit f546b1
  GstCapsFeatures **storage, *old;
Packit f546b1
Packit f546b1
  g_return_if_fail (caps != NULL);
Packit f546b1
  g_return_if_fail (index <= gst_caps_get_size (caps));
Packit f546b1
  g_return_if_fail (IS_WRITABLE (caps));
Packit f546b1
Packit f546b1
  storage = gst_caps_get_features_storage_unchecked (caps, index);
Packit f546b1
  /* Not much problem here as caps are writable */
Packit f546b1
  old = g_atomic_pointer_get (storage);
Packit f546b1
  g_atomic_pointer_set (storage, features);
Packit f546b1
Packit f546b1
  if (features)
Packit f546b1
    gst_caps_features_set_parent_refcount (features, &GST_CAPS_REFCOUNT (caps));
Packit f546b1
Packit f546b1
  if (old) {
Packit f546b1
    gst_caps_features_set_parent_refcount (old, NULL);
Packit f546b1
    gst_caps_features_free (old);
Packit f546b1
  }
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_copy_nth:
Packit f546b1
 * @caps: the #GstCaps to copy
Packit f546b1
 * @nth: the nth structure to copy
Packit f546b1
 *
Packit f546b1
 * Creates a new #GstCaps and appends a copy of the nth structure
Packit f546b1
 * contained in @caps.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the new #GstCaps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_copy_nth (const GstCaps * caps, guint nth)
Packit f546b1
{
Packit f546b1
  GstCaps *newcaps;
Packit f546b1
  GstStructure *structure;
Packit f546b1
  GstCapsFeatures *features;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
Packit f546b1
Packit f546b1
  newcaps = gst_caps_new_empty ();
Packit f546b1
  GST_CAPS_FLAGS (newcaps) = GST_CAPS_FLAGS (caps);
Packit f546b1
Packit f546b1
  if (G_LIKELY (GST_CAPS_LEN (caps) > nth)) {
Packit f546b1
    structure = gst_caps_get_structure_unchecked (caps, nth);
Packit f546b1
    features = gst_caps_get_features_unchecked (caps, nth);
Packit f546b1
    gst_caps_append_structure_unchecked (newcaps,
Packit f546b1
        gst_structure_copy (structure),
Packit f546b1
        gst_caps_features_copy_conditional (features));
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return newcaps;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_truncate:
Packit f546b1
 * @caps: (transfer full): the #GstCaps to truncate
Packit f546b1
 *
Packit f546b1
 * Discard all but the first structure from @caps. Useful when
Packit f546b1
 * fixating.
Packit f546b1
 *
Packit f546b1
 * This function takes ownership of @caps and will call gst_caps_make_writable()
Packit f546b1
 * on it if necessary, so you must not use @caps afterwards unless you keep an
Packit f546b1
 * additional reference to it with gst_caps_ref().
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): truncated caps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_truncate (GstCaps * caps)
Packit f546b1
{
Packit f546b1
  gint i;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
Packit f546b1
Packit f546b1
  i = GST_CAPS_LEN (caps) - 1;
Packit f546b1
  if (i == 0)
Packit f546b1
    return caps;
Packit f546b1
Packit f546b1
  caps = gst_caps_make_writable (caps);
Packit f546b1
  while (i > 0)
Packit f546b1
    gst_caps_remove_structure (caps, i--);
Packit f546b1
Packit f546b1
  return caps;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_set_value:
Packit f546b1
 * @caps: a writable caps
Packit f546b1
 * @field: name of the field to set
Packit f546b1
 * @value: value to set the field to
Packit f546b1
 *
Packit f546b1
 * Sets the given @field on all structures of @caps to the given @value.
Packit f546b1
 * This is a convenience function for calling gst_structure_set_value() on
Packit f546b1
 * all structures of @caps.
Packit f546b1
 **/
Packit f546b1
void
Packit f546b1
gst_caps_set_value (GstCaps * caps, const char *field, const GValue * value)
Packit f546b1
{
Packit f546b1
  guint i, len;
Packit f546b1
Packit f546b1
  g_return_if_fail (GST_IS_CAPS (caps));
Packit f546b1
  g_return_if_fail (IS_WRITABLE (caps));
Packit f546b1
  g_return_if_fail (field != NULL);
Packit f546b1
  g_return_if_fail (G_IS_VALUE (value));
Packit f546b1
Packit f546b1
  len = GST_CAPS_LEN (caps);
Packit f546b1
  for (i = 0; i < len; i++) {
Packit f546b1
    GstStructure *structure = gst_caps_get_structure_unchecked (caps, i);
Packit f546b1
    gst_structure_set_value (structure, field, value);
Packit f546b1
  }
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_set_simple_valist:
Packit f546b1
 * @caps: the #GstCaps to set
Packit f546b1
 * @field: first field to set
Packit f546b1
 * @varargs: additional parameters
Packit f546b1
 *
Packit f546b1
 * Sets fields in a #GstCaps.  The arguments must be passed in the same
Packit f546b1
 * manner as gst_structure_set(), and be %NULL-terminated.
Packit f546b1
 */
Packit f546b1
void
Packit f546b1
gst_caps_set_simple_valist (GstCaps * caps, const char *field, va_list varargs)
Packit f546b1
{
Packit f546b1
  GValue value = { 0, };
Packit f546b1
Packit f546b1
  g_return_if_fail (GST_IS_CAPS (caps));
Packit f546b1
  g_return_if_fail (IS_WRITABLE (caps));
Packit f546b1
Packit f546b1
  while (field) {
Packit f546b1
    GType type;
Packit f546b1
    char *err;
Packit f546b1
Packit f546b1
    type = va_arg (varargs, GType);
Packit f546b1
Packit f546b1
    G_VALUE_COLLECT_INIT (&value, type, varargs, 0, &err;;
Packit f546b1
    if (G_UNLIKELY (err)) {
Packit f546b1
      g_critical ("%s", err);
Packit f546b1
      return;
Packit f546b1
    }
Packit f546b1
Packit f546b1
    gst_caps_set_value (caps, field, &value);
Packit f546b1
Packit f546b1
    g_value_unset (&value);
Packit f546b1
Packit f546b1
    field = va_arg (varargs, const gchar *);
Packit f546b1
  }
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_set_simple:
Packit f546b1
 * @caps: the #GstCaps to set
Packit f546b1
 * @field: first field to set
Packit f546b1
 * @...: additional parameters
Packit f546b1
 *
Packit f546b1
 * Sets fields in a #GstCaps.  The arguments must be passed in the same
Packit f546b1
 * manner as gst_structure_set(), and be %NULL-terminated.
Packit f546b1
 */
Packit f546b1
void
Packit f546b1
gst_caps_set_simple (GstCaps * caps, const char *field, ...)
Packit f546b1
{
Packit f546b1
  va_list var_args;
Packit f546b1
Packit f546b1
  g_return_if_fail (GST_IS_CAPS (caps));
Packit f546b1
  g_return_if_fail (IS_WRITABLE (caps));
Packit f546b1
Packit f546b1
  va_start (var_args, field);
Packit f546b1
  gst_caps_set_simple_valist (caps, field, var_args);
Packit f546b1
  va_end (var_args);
Packit f546b1
}
Packit f546b1
Packit f546b1
/* tests */
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_is_any:
Packit f546b1
 * @caps: the #GstCaps to test
Packit f546b1
 *
Packit f546b1
 * Determines if @caps represents any media format.
Packit f546b1
 *
Packit f546b1
 * Returns: %TRUE if @caps represents any format.
Packit f546b1
 */
Packit f546b1
gboolean
Packit f546b1
gst_caps_is_any (const GstCaps * caps)
Packit f546b1
{
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
Packit f546b1
Packit f546b1
  return (CAPS_IS_ANY (caps));
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_is_empty:
Packit f546b1
 * @caps: the #GstCaps to test
Packit f546b1
 *
Packit f546b1
 * Determines if @caps represents no media formats.
Packit f546b1
 *
Packit f546b1
 * Returns: %TRUE if @caps represents no formats.
Packit f546b1
 */
Packit f546b1
gboolean
Packit f546b1
gst_caps_is_empty (const GstCaps * caps)
Packit f546b1
{
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
Packit f546b1
Packit f546b1
  if (CAPS_IS_ANY (caps))
Packit f546b1
    return FALSE;
Packit f546b1
Packit f546b1
  return CAPS_IS_EMPTY_SIMPLE (caps);
Packit f546b1
}
Packit f546b1
Packit f546b1
static gboolean
Packit f546b1
gst_caps_is_fixed_foreach (GQuark field_id, const GValue * value,
Packit f546b1
    gpointer unused)
Packit f546b1
{
Packit f546b1
  return gst_value_is_fixed (value);
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_is_fixed:
Packit f546b1
 * @caps: the #GstCaps to test
Packit f546b1
 *
Packit f546b1
 * Fixed #GstCaps describe exactly one format, that is, they have exactly
Packit f546b1
 * one structure, and each field in the structure describes a fixed type.
Packit f546b1
 * Examples of non-fixed types are GST_TYPE_INT_RANGE and GST_TYPE_LIST.
Packit f546b1
 *
Packit f546b1
 * Returns: %TRUE if @caps is fixed
Packit f546b1
 */
Packit f546b1
gboolean
Packit f546b1
gst_caps_is_fixed (const GstCaps * caps)
Packit f546b1
{
Packit f546b1
  GstStructure *structure;
Packit f546b1
  GstCapsFeatures *features;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
Packit f546b1
Packit f546b1
  if (GST_CAPS_LEN (caps) != 1)
Packit f546b1
    return FALSE;
Packit f546b1
Packit f546b1
  features = gst_caps_get_features_unchecked (caps, 0);
Packit f546b1
  if (features && gst_caps_features_is_any (features))
Packit f546b1
    return FALSE;
Packit f546b1
Packit f546b1
  structure = gst_caps_get_structure_unchecked (caps, 0);
Packit f546b1
Packit f546b1
  return gst_structure_foreach (structure, gst_caps_is_fixed_foreach, NULL);
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_is_equal_fixed:
Packit f546b1
 * @caps1: the #GstCaps to test
Packit f546b1
 * @caps2: the #GstCaps to test
Packit f546b1
 *
Packit f546b1
 * Tests if two #GstCaps are equal.  This function only works on fixed
Packit f546b1
 * #GstCaps.
Packit f546b1
 *
Packit f546b1
 * Returns: %TRUE if the arguments represent the same format
Packit f546b1
 */
Packit f546b1
gboolean
Packit f546b1
gst_caps_is_equal_fixed (const GstCaps * caps1, const GstCaps * caps2)
Packit f546b1
{
Packit f546b1
  GstStructure *struct1, *struct2;
Packit f546b1
  GstCapsFeatures *features1, *features2;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (gst_caps_is_fixed (caps1), FALSE);
Packit f546b1
  g_return_val_if_fail (gst_caps_is_fixed (caps2), FALSE);
Packit f546b1
Packit f546b1
  struct1 = gst_caps_get_structure_unchecked (caps1, 0);
Packit f546b1
  features1 = gst_caps_get_features_unchecked (caps1, 0);
Packit f546b1
  if (!features1)
Packit f546b1
    features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
  struct2 = gst_caps_get_structure_unchecked (caps2, 0);
Packit f546b1
  features2 = gst_caps_get_features_unchecked (caps2, 0);
Packit f546b1
  if (!features2)
Packit f546b1
    features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
Packit f546b1
  return gst_structure_is_equal (struct1, struct2) &&
Packit f546b1
      gst_caps_features_is_equal (features1, features2);
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_is_always_compatible:
Packit f546b1
 * @caps1: the #GstCaps to test
Packit f546b1
 * @caps2: the #GstCaps to test
Packit f546b1
 *
Packit f546b1
 * A given #GstCaps structure is always compatible with another if
Packit f546b1
 * every media format that is in the first is also contained in the
Packit f546b1
 * second.  That is, @caps1 is a subset of @caps2.
Packit f546b1
 *
Packit f546b1
 * Returns: %TRUE if @caps1 is a subset of @caps2.
Packit f546b1
 */
Packit f546b1
gboolean
Packit f546b1
gst_caps_is_always_compatible (const GstCaps * caps1, const GstCaps * caps2)
Packit f546b1
{
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE);
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE);
Packit f546b1
Packit f546b1
  return gst_caps_is_subset (caps1, caps2);
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_is_subset:
Packit f546b1
 * @subset: a #GstCaps
Packit f546b1
 * @superset: a potentially greater #GstCaps
Packit f546b1
 *
Packit f546b1
 * Checks if all caps represented by @subset are also represented by @superset.
Packit f546b1
 *
Packit f546b1
 * Returns: %TRUE if @subset is a subset of @superset
Packit f546b1
 */
Packit f546b1
gboolean
Packit f546b1
gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
Packit f546b1
{
Packit f546b1
  GstStructure *s1, *s2;
Packit f546b1
  GstCapsFeatures *f1, *f2;
Packit f546b1
  gboolean ret = TRUE;
Packit f546b1
  gint i, j;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (subset != NULL, FALSE);
Packit f546b1
  g_return_val_if_fail (superset != NULL, FALSE);
Packit f546b1
Packit f546b1
  if (CAPS_IS_EMPTY (subset) || CAPS_IS_ANY (superset))
Packit f546b1
    return TRUE;
Packit f546b1
  if (CAPS_IS_ANY (subset) || CAPS_IS_EMPTY (superset))
Packit f546b1
    return FALSE;
Packit f546b1
Packit f546b1
  for (i = GST_CAPS_LEN (subset) - 1; i >= 0; i--) {
Packit f546b1
    for (j = GST_CAPS_LEN (superset) - 1; j >= 0; j--) {
Packit f546b1
      s1 = gst_caps_get_structure_unchecked (subset, i);
Packit f546b1
      f1 = gst_caps_get_features_unchecked (subset, i);
Packit f546b1
      if (!f1)
Packit f546b1
        f1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
      s2 = gst_caps_get_structure_unchecked (superset, j);
Packit f546b1
      f2 = gst_caps_get_features_unchecked (superset, j);
Packit f546b1
      if (!f2)
Packit f546b1
        f2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
      if ((!gst_caps_features_is_any (f1) || gst_caps_features_is_any (f2)) &&
Packit f546b1
          gst_caps_features_is_equal (f1, f2)
Packit f546b1
          && gst_structure_is_subset (s1, s2)) {
Packit f546b1
        /* If we found a superset, continue with the next
Packit f546b1
         * subset structure */
Packit f546b1
        break;
Packit f546b1
      }
Packit f546b1
    }
Packit f546b1
    /* If we found no superset for this subset structure
Packit f546b1
     * we return FALSE immediately */
Packit f546b1
    if (j == -1) {
Packit f546b1
      ret = FALSE;
Packit f546b1
      break;
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return ret;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_is_subset_structure:
Packit f546b1
 * @caps: a #GstCaps
Packit f546b1
 * @structure: a potential #GstStructure subset of @caps
Packit f546b1
 *
Packit f546b1
 * Checks if @structure is a subset of @caps. See gst_caps_is_subset()
Packit f546b1
 * for more information.
Packit f546b1
 *
Packit f546b1
 * Returns: %TRUE if @structure is a subset of @caps
Packit f546b1
 */
Packit f546b1
gboolean
Packit f546b1
gst_caps_is_subset_structure (const GstCaps * caps,
Packit f546b1
    const GstStructure * structure)
Packit f546b1
{
Packit f546b1
  GstStructure *s;
Packit f546b1
  gint i;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (caps != NULL, FALSE);
Packit f546b1
  g_return_val_if_fail (structure != NULL, FALSE);
Packit f546b1
Packit f546b1
  if (CAPS_IS_ANY (caps))
Packit f546b1
    return TRUE;
Packit f546b1
  if (CAPS_IS_EMPTY (caps))
Packit f546b1
    return FALSE;
Packit f546b1
Packit f546b1
  for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
Packit f546b1
    s = gst_caps_get_structure_unchecked (caps, i);
Packit f546b1
    if (gst_structure_is_subset (structure, s)) {
Packit f546b1
      /* If we found a superset return TRUE */
Packit f546b1
      return TRUE;
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return FALSE;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_is_subset_structure_full:
Packit f546b1
 * @caps: a #GstCaps
Packit f546b1
 * @structure: a potential #GstStructure subset of @caps
Packit f546b1
 * @features: (allow-none): a #GstCapsFeatures for @structure
Packit f546b1
 *
Packit f546b1
 * Checks if @structure is a subset of @caps. See gst_caps_is_subset()
Packit f546b1
 * for more information.
Packit f546b1
 *
Packit f546b1
 * Returns: %TRUE if @structure is a subset of @caps
Packit f546b1
 *
Packit f546b1
 * Since: 1.2
Packit f546b1
 */
Packit f546b1
gboolean
Packit f546b1
gst_caps_is_subset_structure_full (const GstCaps * caps,
Packit f546b1
    const GstStructure * structure, const GstCapsFeatures * features)
Packit f546b1
{
Packit f546b1
  GstStructure *s;
Packit f546b1
  GstCapsFeatures *f;
Packit f546b1
  gint i;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (caps != NULL, FALSE);
Packit f546b1
  g_return_val_if_fail (structure != NULL, FALSE);
Packit f546b1
Packit f546b1
  if (CAPS_IS_ANY (caps))
Packit f546b1
    return TRUE;
Packit f546b1
  if (CAPS_IS_EMPTY (caps))
Packit f546b1
    return FALSE;
Packit f546b1
Packit f546b1
  if (!features)
Packit f546b1
    features = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
Packit f546b1
  for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
Packit f546b1
    s = gst_caps_get_structure_unchecked (caps, i);
Packit f546b1
    f = gst_caps_get_features_unchecked (caps, i);
Packit f546b1
    if (!f)
Packit f546b1
      f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
    if ((!gst_caps_features_is_any (features) || gst_caps_features_is_any (f))
Packit f546b1
        && gst_caps_features_is_equal (features, f)
Packit f546b1
        && gst_structure_is_subset (structure, s)) {
Packit f546b1
      /* If we found a superset return TRUE */
Packit f546b1
      return TRUE;
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return FALSE;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_is_equal:
Packit f546b1
 * @caps1: a #GstCaps
Packit f546b1
 * @caps2: another #GstCaps
Packit f546b1
 *
Packit f546b1
 * Checks if the given caps represent the same set of caps.
Packit f546b1
 *
Packit f546b1
 * Returns: %TRUE if both caps are equal.
Packit f546b1
 */
Packit f546b1
gboolean
Packit f546b1
gst_caps_is_equal (const GstCaps * caps1, const GstCaps * caps2)
Packit f546b1
{
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE);
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE);
Packit f546b1
Packit f546b1
  if (G_UNLIKELY (caps1 == caps2))
Packit f546b1
    return TRUE;
Packit f546b1
Packit f546b1
  if (G_UNLIKELY (gst_caps_is_fixed (caps1) && gst_caps_is_fixed (caps2)))
Packit f546b1
    return gst_caps_is_equal_fixed (caps1, caps2);
Packit f546b1
Packit f546b1
  return gst_caps_is_subset (caps1, caps2) && gst_caps_is_subset (caps2, caps1);
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_is_strictly_equal:
Packit f546b1
 * @caps1: a #GstCaps
Packit f546b1
 * @caps2: another #GstCaps
Packit f546b1
 *
Packit f546b1
 * Checks if the given caps are exactly the same set of caps.
Packit f546b1
 *
Packit f546b1
 * Returns: %TRUE if both caps are strictly equal.
Packit f546b1
 */
Packit f546b1
gboolean
Packit f546b1
gst_caps_is_strictly_equal (const GstCaps * caps1, const GstCaps * caps2)
Packit f546b1
{
Packit f546b1
  int i;
Packit f546b1
  GstStructure *s1, *s2;
Packit f546b1
  GstCapsFeatures *f1, *f2;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE);
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE);
Packit f546b1
Packit f546b1
  if (G_UNLIKELY (caps1 == caps2))
Packit f546b1
    return TRUE;
Packit f546b1
Packit f546b1
  if (GST_CAPS_LEN (caps1) != GST_CAPS_LEN (caps2))
Packit f546b1
    return FALSE;
Packit f546b1
Packit f546b1
  for (i = 0; i < GST_CAPS_LEN (caps1); i++) {
Packit f546b1
    s1 = gst_caps_get_structure_unchecked (caps1, i);
Packit f546b1
    f1 = gst_caps_get_features_unchecked (caps1, i);
Packit f546b1
    if (!f1)
Packit f546b1
      f1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
    s2 = gst_caps_get_structure_unchecked (caps2, i);
Packit f546b1
    f2 = gst_caps_get_features_unchecked (caps2, i);
Packit f546b1
    if (!f2)
Packit f546b1
      f2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
Packit f546b1
    if (gst_caps_features_is_any (f1) != gst_caps_features_is_any (f2) ||
Packit f546b1
        !gst_caps_features_is_equal (f1, f2) ||
Packit f546b1
        !gst_structure_is_equal (s1, s2))
Packit f546b1
      return FALSE;
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return TRUE;
Packit f546b1
}
Packit f546b1
Packit f546b1
/* intersect operation */
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_can_intersect:
Packit f546b1
 * @caps1: a #GstCaps to intersect
Packit f546b1
 * @caps2: a #GstCaps to intersect
Packit f546b1
 *
Packit f546b1
 * Tries intersecting @caps1 and @caps2 and reports whether the result would not
Packit f546b1
 * be empty
Packit f546b1
 *
Packit f546b1
 * Returns: %TRUE if intersection would be not empty
Packit f546b1
 */
Packit f546b1
gboolean
Packit f546b1
gst_caps_can_intersect (const GstCaps * caps1, const GstCaps * caps2)
Packit f546b1
{
Packit f546b1
  guint64 i;                    /* index can be up to 2 * G_MAX_UINT */
Packit f546b1
  guint j, k, len1, len2;
Packit f546b1
  GstStructure *struct1;
Packit f546b1
  GstStructure *struct2;
Packit f546b1
  GstCapsFeatures *features1;
Packit f546b1
  GstCapsFeatures *features2;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE);
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE);
Packit f546b1
Packit f546b1
  /* caps are exactly the same pointers */
Packit f546b1
  if (G_UNLIKELY (caps1 == caps2))
Packit f546b1
    return TRUE;
Packit f546b1
Packit f546b1
  /* empty caps on either side, return empty */
Packit f546b1
  if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2)))
Packit f546b1
    return FALSE;
Packit f546b1
Packit f546b1
  /* one of the caps is any */
Packit f546b1
  if (G_UNLIKELY (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2)))
Packit f546b1
    return TRUE;
Packit f546b1
Packit f546b1
  /* run zigzag on top line then right line, this preserves the caps order
Packit f546b1
   * much better than a simple loop.
Packit f546b1
   *
Packit f546b1
   * This algorithm zigzags over the caps structures as demonstrated in
Packit f546b1
   * the following matrix:
Packit f546b1
   *
Packit f546b1
   *          caps1                              0  1  2  3
Packit f546b1
   *       +-------------     total distance:  +-------------
Packit f546b1
   *       | 1  2  4  7                      0 | 0  1  2  3
Packit f546b1
   * caps2 | 3  5  8 10                      1 | 1  2  3  4
Packit f546b1
   *       | 6  9 11 12                      2 | 2  3  4  5
Packit f546b1
   *
Packit f546b1
   * First we iterate over the caps1 structures (top line) intersecting
Packit f546b1
   * the structures diagonally down, then we iterate over the caps2
Packit f546b1
   * structures. The result is that the intersections are ordered based on the
Packit f546b1
   * sum of the indexes in the list.
Packit f546b1
   */
Packit f546b1
  len1 = GST_CAPS_LEN (caps1);
Packit f546b1
  len2 = GST_CAPS_LEN (caps2);
Packit f546b1
  for (i = 0; i < len1 + len2 - 1; i++) {
Packit f546b1
    /* superset index goes from 0 to superset->structs->len-1 */
Packit f546b1
    j = MIN (i, len1 - 1);
Packit f546b1
    /* subset index stays 0 until i reaches superset->structs->len, then it
Packit f546b1
     * counts up from 1 to subset->structs->len - 1 */
Packit f546b1
    k = (i > j) ? (i - j) : 0;  /* MAX (0, i - j) */
Packit f546b1
    /* now run the diagonal line, end condition is the left or bottom
Packit f546b1
     * border */
Packit f546b1
    while (k < len2) {
Packit f546b1
      struct1 = gst_caps_get_structure_unchecked (caps1, j);
Packit f546b1
      features1 = gst_caps_get_features_unchecked (caps1, j);
Packit f546b1
      if (!features1)
Packit f546b1
        features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
      struct2 = gst_caps_get_structure_unchecked (caps2, k);
Packit f546b1
      features2 = gst_caps_get_features_unchecked (caps2, k);
Packit f546b1
      if (!features2)
Packit f546b1
        features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
      if (gst_caps_features_is_equal (features1, features2) &&
Packit f546b1
          gst_structure_can_intersect (struct1, struct2)) {
Packit f546b1
        return TRUE;
Packit f546b1
      }
Packit f546b1
      /* move down left */
Packit f546b1
      k++;
Packit f546b1
      if (G_UNLIKELY (j == 0))
Packit f546b1
        break;                  /* so we don't roll back to G_MAXUINT */
Packit f546b1
      j--;
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return FALSE;
Packit f546b1
}
Packit f546b1
Packit f546b1
static GstCaps *
Packit f546b1
gst_caps_intersect_zig_zag (GstCaps * caps1, GstCaps * caps2)
Packit f546b1
{
Packit f546b1
  guint64 i;                    /* index can be up to 2 * G_MAX_UINT */
Packit f546b1
  guint j, k, len1, len2;
Packit f546b1
  GstStructure *struct1;
Packit f546b1
  GstStructure *struct2;
Packit f546b1
  GstCapsFeatures *features1;
Packit f546b1
  GstCapsFeatures *features2;
Packit f546b1
  GstCaps *dest;
Packit f546b1
  GstStructure *istruct;
Packit f546b1
Packit f546b1
  /* caps are exactly the same pointers, just copy one caps */
Packit f546b1
  if (G_UNLIKELY (caps1 == caps2))
Packit f546b1
    return gst_caps_ref (caps1);
Packit f546b1
Packit f546b1
  /* empty caps on either side, return empty */
Packit f546b1
  if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2)))
Packit f546b1
    return gst_caps_ref (GST_CAPS_NONE);
Packit f546b1
Packit f546b1
  /* one of the caps is any, just copy the other caps */
Packit f546b1
  if (G_UNLIKELY (CAPS_IS_ANY (caps1)))
Packit f546b1
    return gst_caps_ref (caps2);
Packit f546b1
Packit f546b1
  if (G_UNLIKELY (CAPS_IS_ANY (caps2)))
Packit f546b1
    return gst_caps_ref (caps1);
Packit f546b1
Packit f546b1
  dest = gst_caps_new_empty ();
Packit f546b1
  /* run zigzag on top line then right line, this preserves the caps order
Packit f546b1
   * much better than a simple loop.
Packit f546b1
   *
Packit f546b1
   * This algorithm zigzags over the caps structures as demonstrated in
Packit f546b1
   * the following matrix:
Packit f546b1
   *
Packit f546b1
   *          caps1
Packit f546b1
   *       +-------------
Packit f546b1
   *       | 1  2  4  7
Packit f546b1
   * caps2 | 3  5  8 10
Packit f546b1
   *       | 6  9 11 12
Packit f546b1
   *
Packit f546b1
   * First we iterate over the caps1 structures (top line) intersecting
Packit f546b1
   * the structures diagonally down, then we iterate over the caps2
Packit f546b1
   * structures.
Packit f546b1
   */
Packit f546b1
  len1 = GST_CAPS_LEN (caps1);
Packit f546b1
  len2 = GST_CAPS_LEN (caps2);
Packit f546b1
  for (i = 0; i < len1 + len2 - 1; i++) {
Packit f546b1
    /* caps1 index goes from 0 to GST_CAPS_LEN (caps1)-1 */
Packit f546b1
    j = MIN (i, len1 - 1);
Packit f546b1
    /* caps2 index stays 0 until i reaches GST_CAPS_LEN (caps1), then it counts
Packit f546b1
     * up from 1 to GST_CAPS_LEN (caps2) - 1 */
Packit f546b1
    k = (i > j) ? (i - j) : 0;  /* MAX (0, i - j) */
Packit f546b1
    /* now run the diagonal line, end condition is the left or bottom
Packit f546b1
     * border */
Packit f546b1
    while (k < len2) {
Packit f546b1
      struct1 = gst_caps_get_structure_unchecked (caps1, j);
Packit f546b1
      features1 = gst_caps_get_features_unchecked (caps1, j);
Packit f546b1
      if (!features1)
Packit f546b1
        features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
      struct2 = gst_caps_get_structure_unchecked (caps2, k);
Packit f546b1
      features2 = gst_caps_get_features_unchecked (caps2, k);
Packit f546b1
      if (!features2)
Packit f546b1
        features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
      if (gst_caps_features_is_equal (features1, features2)) {
Packit f546b1
        istruct = gst_structure_intersect (struct1, struct2);
Packit f546b1
        if (istruct) {
Packit f546b1
          if (gst_caps_features_is_any (features1))
Packit f546b1
            dest =
Packit f546b1
                gst_caps_merge_structure_full (dest, istruct,
Packit f546b1
                gst_caps_features_copy_conditional (features2));
Packit f546b1
          else
Packit f546b1
            dest =
Packit f546b1
                gst_caps_merge_structure_full (dest, istruct,
Packit f546b1
                gst_caps_features_copy_conditional (features1));
Packit f546b1
        }
Packit f546b1
      }
Packit f546b1
      /* move down left */
Packit f546b1
      k++;
Packit f546b1
      if (G_UNLIKELY (j == 0))
Packit f546b1
        break;                  /* so we don't roll back to G_MAXUINT */
Packit f546b1
      j--;
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
  return dest;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_intersect_first:
Packit f546b1
 * @caps1: a #GstCaps to intersect
Packit f546b1
 * @caps2: a #GstCaps to intersect
Packit f546b1
 *
Packit f546b1
 * Creates a new #GstCaps that contains all the formats that are common
Packit f546b1
 * to both @caps1 and @caps2.
Packit f546b1
 *
Packit f546b1
 * Unlike @gst_caps_intersect, the returned caps will be ordered in a similar
Packit f546b1
 * fashion as @caps1.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the new #GstCaps
Packit f546b1
 */
Packit f546b1
static GstCaps *
Packit f546b1
gst_caps_intersect_first (GstCaps * caps1, GstCaps * caps2)
Packit f546b1
{
Packit f546b1
  guint i;
Packit f546b1
  guint j, len1, len2;
Packit f546b1
  GstStructure *struct1;
Packit f546b1
  GstStructure *struct2;
Packit f546b1
  GstCapsFeatures *features1;
Packit f546b1
  GstCapsFeatures *features2;
Packit f546b1
  GstCaps *dest;
Packit f546b1
  GstStructure *istruct;
Packit f546b1
Packit f546b1
  /* caps are exactly the same pointers, just copy one caps */
Packit f546b1
  if (G_UNLIKELY (caps1 == caps2))
Packit f546b1
    return gst_caps_ref (caps1);
Packit f546b1
Packit f546b1
  /* empty caps on either side, return empty */
Packit f546b1
  if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2)))
Packit f546b1
    return gst_caps_ref (GST_CAPS_NONE);
Packit f546b1
Packit f546b1
  /* one of the caps is any, just copy the other caps */
Packit f546b1
  if (G_UNLIKELY (CAPS_IS_ANY (caps1)))
Packit f546b1
    return gst_caps_ref (caps2);
Packit f546b1
Packit f546b1
  if (G_UNLIKELY (CAPS_IS_ANY (caps2)))
Packit f546b1
    return gst_caps_ref (caps1);
Packit f546b1
Packit f546b1
  dest = gst_caps_new_empty ();
Packit f546b1
  len1 = GST_CAPS_LEN (caps1);
Packit f546b1
  len2 = GST_CAPS_LEN (caps2);
Packit f546b1
  for (i = 0; i < len1; i++) {
Packit f546b1
    struct1 = gst_caps_get_structure_unchecked (caps1, i);
Packit f546b1
    features1 = gst_caps_get_features_unchecked (caps1, i);
Packit f546b1
    if (!features1)
Packit f546b1
      features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
    for (j = 0; j < len2; j++) {
Packit f546b1
      struct2 = gst_caps_get_structure_unchecked (caps2, j);
Packit f546b1
      features2 = gst_caps_get_features_unchecked (caps2, j);
Packit f546b1
      if (!features2)
Packit f546b1
        features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
      if (gst_caps_features_is_equal (features1, features2)) {
Packit f546b1
        istruct = gst_structure_intersect (struct1, struct2);
Packit f546b1
        if (istruct) {
Packit f546b1
          if (gst_caps_features_is_any (features1))
Packit f546b1
            dest =
Packit f546b1
                gst_caps_merge_structure_full (dest, istruct,
Packit f546b1
                gst_caps_features_copy_conditional (features2));
Packit f546b1
          else
Packit f546b1
            dest =
Packit f546b1
                gst_caps_merge_structure_full (dest, istruct,
Packit f546b1
                gst_caps_features_copy_conditional (features1));
Packit f546b1
        }
Packit f546b1
      }
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return dest;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_intersect_full:
Packit f546b1
 * @caps1: a #GstCaps to intersect
Packit f546b1
 * @caps2: a #GstCaps to intersect
Packit f546b1
 * @mode: The intersection algorithm/mode to use
Packit f546b1
 *
Packit f546b1
 * Creates a new #GstCaps that contains all the formats that are common
Packit f546b1
 * to both @caps1 and @caps2, the order is defined by the #GstCapsIntersectMode
Packit f546b1
 * used.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the new #GstCaps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_intersect_full (GstCaps * caps1, GstCaps * caps2,
Packit f546b1
    GstCapsIntersectMode mode)
Packit f546b1
{
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps1), NULL);
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps2), NULL);
Packit f546b1
Packit f546b1
  switch (mode) {
Packit f546b1
    case GST_CAPS_INTERSECT_FIRST:
Packit f546b1
      return gst_caps_intersect_first (caps1, caps2);
Packit f546b1
    default:
Packit f546b1
      g_warning ("Unknown caps intersect mode: %d", mode);
Packit f546b1
      /* fallthrough */
Packit f546b1
    case GST_CAPS_INTERSECT_ZIG_ZAG:
Packit f546b1
      return gst_caps_intersect_zig_zag (caps1, caps2);
Packit f546b1
  }
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_intersect:
Packit f546b1
 * @caps1: a #GstCaps to intersect
Packit f546b1
 * @caps2: a #GstCaps to intersect
Packit f546b1
 *
Packit f546b1
 * Creates a new #GstCaps that contains all the formats that are common
Packit f546b1
 * to both @caps1 and @caps2. Defaults to %GST_CAPS_INTERSECT_ZIG_ZAG mode.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the new #GstCaps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_intersect (GstCaps * caps1, GstCaps * caps2)
Packit f546b1
{
Packit f546b1
  return gst_caps_intersect_full (caps1, caps2, GST_CAPS_INTERSECT_ZIG_ZAG);
Packit f546b1
}
Packit f546b1
Packit f546b1
/* subtract operation */
Packit f546b1
Packit f546b1
typedef struct
Packit f546b1
{
Packit f546b1
  const GstStructure *subtract_from;
Packit f546b1
  GSList *put_into;
Packit f546b1
} SubtractionEntry;
Packit f546b1
Packit f546b1
static gboolean
Packit f546b1
gst_caps_structure_subtract_field (GQuark field_id, const GValue * value,
Packit f546b1
    gpointer user_data)
Packit f546b1
{
Packit f546b1
  SubtractionEntry *e = user_data;
Packit f546b1
  GValue subtraction = { 0, };
Packit f546b1
  const GValue *other;
Packit f546b1
  GstStructure *structure;
Packit f546b1
Packit f546b1
  other = gst_structure_id_get_value (e->subtract_from, field_id);
Packit f546b1
Packit f546b1
  if (!other) {
Packit f546b1
    return FALSE;
Packit f546b1
  }
Packit f546b1
Packit f546b1
  if (!gst_value_subtract (&subtraction, other, value))
Packit f546b1
    return TRUE;
Packit f546b1
Packit f546b1
  if (gst_value_compare (&subtraction, other) == GST_VALUE_EQUAL) {
Packit f546b1
    g_value_unset (&subtraction);
Packit f546b1
    return FALSE;
Packit f546b1
  } else {
Packit f546b1
    structure = gst_structure_copy (e->subtract_from);
Packit f546b1
    gst_structure_id_take_value (structure, field_id, &subtraction);
Packit f546b1
    e->put_into = g_slist_prepend (e->put_into, structure);
Packit f546b1
    return TRUE;
Packit f546b1
  }
Packit f546b1
}
Packit f546b1
Packit f546b1
static gboolean
Packit f546b1
gst_caps_structure_subtract (GSList ** into, const GstStructure * minuend,
Packit f546b1
    const GstStructure * subtrahend)
Packit f546b1
{
Packit f546b1
  SubtractionEntry e;
Packit f546b1
  gboolean ret;
Packit f546b1
Packit f546b1
  e.subtract_from = minuend;
Packit f546b1
  e.put_into = NULL;
Packit f546b1
  ret = gst_structure_foreach ((GstStructure *) subtrahend,
Packit f546b1
      gst_caps_structure_subtract_field, &e);
Packit f546b1
Packit f546b1
  if (ret) {
Packit f546b1
    *into = e.put_into;
Packit f546b1
  } else {
Packit f546b1
    GSList *walk;
Packit f546b1
Packit f546b1
    for (walk = e.put_into; walk; walk = g_slist_next (walk)) {
Packit f546b1
      gst_structure_free (walk->data);
Packit f546b1
    }
Packit f546b1
    g_slist_free (e.put_into);
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return ret;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_subtract:
Packit f546b1
 * @minuend: #GstCaps to subtract from
Packit f546b1
 * @subtrahend: #GstCaps to subtract
Packit f546b1
 *
Packit f546b1
 * Subtracts the @subtrahend from the @minuend.
Packit f546b1
 * > This function does not work reliably if optional properties for caps
Packit f546b1
 * > are included on one caps and omitted on the other.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the resulting caps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_subtract (GstCaps * minuend, GstCaps * subtrahend)
Packit f546b1
{
Packit f546b1
  guint i, j, sublen;
Packit f546b1
  GstStructure *min;
Packit f546b1
  GstStructure *sub;
Packit f546b1
  GstCapsFeatures *min_f, *sub_f;
Packit f546b1
  GstCaps *dest = NULL, *src;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (minuend != NULL, NULL);
Packit f546b1
  g_return_val_if_fail (subtrahend != NULL, NULL);
Packit f546b1
Packit f546b1
  if (CAPS_IS_EMPTY (minuend) || CAPS_IS_ANY (subtrahend)) {
Packit f546b1
    return gst_caps_new_empty ();
Packit f546b1
  }
Packit f546b1
Packit f546b1
  if (CAPS_IS_EMPTY_SIMPLE (subtrahend))
Packit f546b1
    return gst_caps_ref (minuend);
Packit f546b1
Packit f546b1
  /* FIXME: Do we want this here or above?
Packit f546b1
     The reason we need this is that there is no definition about what
Packit f546b1
     ANY means for specific types, so it's not possible to reduce ANY partially
Packit f546b1
     You can only remove everything or nothing and that is done above.
Packit f546b1
     Note: there's a test that checks this behaviour. */
Packit f546b1
Packit f546b1
  g_return_val_if_fail (!CAPS_IS_ANY (minuend), NULL);
Packit f546b1
  sublen = GST_CAPS_LEN (subtrahend);
Packit f546b1
  g_assert (sublen > 0);
Packit f546b1
Packit f546b1
  src = _gst_caps_copy (minuend);
Packit f546b1
  for (i = 0; i < sublen; i++) {
Packit f546b1
    guint srclen;
Packit f546b1
Packit f546b1
    sub = gst_caps_get_structure_unchecked (subtrahend, i);
Packit f546b1
    sub_f = gst_caps_get_features_unchecked (subtrahend, i);
Packit f546b1
    if (!sub_f)
Packit f546b1
      sub_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
    if (dest) {
Packit f546b1
      gst_caps_unref (src);
Packit f546b1
      src = dest;
Packit f546b1
    }
Packit f546b1
    dest = gst_caps_new_empty ();
Packit f546b1
    srclen = GST_CAPS_LEN (src);
Packit f546b1
    for (j = 0; j < srclen; j++) {
Packit f546b1
      min = gst_caps_get_structure_unchecked (src, j);
Packit f546b1
      min_f = gst_caps_get_features_unchecked (src, j);
Packit f546b1
      if (!min_f)
Packit f546b1
        min_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
Packit f546b1
      /* Same reason as above for ANY caps */
Packit f546b1
      g_return_val_if_fail (!gst_caps_features_is_any (min_f), NULL);
Packit f546b1
Packit f546b1
      if (gst_structure_get_name_id (min) == gst_structure_get_name_id (sub) &&
Packit f546b1
          gst_caps_features_is_equal (min_f, sub_f)) {
Packit f546b1
        GSList *list;
Packit f546b1
Packit f546b1
        if (gst_caps_structure_subtract (&list, min, sub)) {
Packit f546b1
          GSList *walk;
Packit f546b1
Packit f546b1
          for (walk = list; walk; walk = g_slist_next (walk)) {
Packit f546b1
            gst_caps_append_structure_unchecked (dest,
Packit f546b1
                (GstStructure *) walk->data,
Packit f546b1
                gst_caps_features_copy_conditional (min_f));
Packit f546b1
          }
Packit f546b1
          g_slist_free (list);
Packit f546b1
        } else {
Packit f546b1
          gst_caps_append_structure_unchecked (dest, gst_structure_copy (min),
Packit f546b1
              gst_caps_features_copy_conditional (min_f));
Packit f546b1
        }
Packit f546b1
      } else {
Packit f546b1
        gst_caps_append_structure_unchecked (dest, gst_structure_copy (min),
Packit f546b1
            gst_caps_features_copy_conditional (min_f));
Packit f546b1
      }
Packit f546b1
    }
Packit f546b1
Packit f546b1
    if (CAPS_IS_EMPTY_SIMPLE (dest)) {
Packit f546b1
      gst_caps_unref (src);
Packit f546b1
      return dest;
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
Packit f546b1
  gst_caps_unref (src);
Packit f546b1
  dest = gst_caps_simplify (dest);
Packit f546b1
Packit f546b1
  return dest;
Packit f546b1
}
Packit f546b1
Packit f546b1
/* normalize/simplify operations */
Packit f546b1
Packit f546b1
typedef struct _NormalizeForeach
Packit f546b1
{
Packit f546b1
  GstCaps *caps;
Packit f546b1
  GstStructure *structure;
Packit f546b1
  GstCapsFeatures *features;
Packit f546b1
} NormalizeForeach;
Packit f546b1
Packit f546b1
static gboolean
Packit f546b1
gst_caps_normalize_foreach (GQuark field_id, const GValue * value, gpointer ptr)
Packit f546b1
{
Packit f546b1
  NormalizeForeach *nf = (NormalizeForeach *) ptr;
Packit f546b1
  GValue val = { 0 };
Packit f546b1
  guint i;
Packit f546b1
Packit f546b1
  if (G_VALUE_TYPE (value) == GST_TYPE_LIST) {
Packit f546b1
    guint len = gst_value_list_get_size (value);
Packit f546b1
Packit f546b1
    for (i = 1; i < len; i++) {
Packit f546b1
      const GValue *v = gst_value_list_get_value (value, i);
Packit f546b1
      GstStructure *structure = gst_structure_copy (nf->structure);
Packit f546b1
Packit f546b1
      gst_structure_id_set_value (structure, field_id, v);
Packit f546b1
      gst_caps_append_structure_unchecked (nf->caps, structure,
Packit f546b1
          gst_caps_features_copy_conditional (nf->features));
Packit f546b1
    }
Packit f546b1
Packit f546b1
    gst_value_init_and_copy (&val, gst_value_list_get_value (value, 0));
Packit f546b1
    gst_structure_id_take_value (nf->structure, field_id, &val;;
Packit f546b1
    return FALSE;
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return TRUE;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_normalize:
Packit f546b1
 * @caps: (transfer full): a #GstCaps to normalize
Packit f546b1
 *
Packit f546b1
 * Returns a #GstCaps that represents the same set of formats as
Packit f546b1
 * @caps, but contains no lists.  Each list is expanded into separate
Packit f546b1
 * @GstStructures.
Packit f546b1
 *
Packit f546b1
 * This function takes ownership of @caps and will call gst_caps_make_writable()
Packit f546b1
 * on it so you must not use @caps afterwards unless you keep an additional
Packit f546b1
 * reference to it with gst_caps_ref().
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the normalized #GstCaps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_normalize (GstCaps * caps)
Packit f546b1
{
Packit f546b1
  NormalizeForeach nf;
Packit f546b1
  guint i;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
Packit f546b1
Packit f546b1
  caps = gst_caps_make_writable (caps);
Packit f546b1
  nf.caps = caps;
Packit f546b1
Packit f546b1
  for (i = 0; i < gst_caps_get_size (nf.caps); i++) {
Packit f546b1
    nf.structure = gst_caps_get_structure_unchecked (nf.caps, i);
Packit f546b1
    nf.features = gst_caps_get_features_unchecked (nf.caps, i);
Packit f546b1
    while (!gst_structure_foreach (nf.structure,
Packit f546b1
            gst_caps_normalize_foreach, &nf);;
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return nf.caps;
Packit f546b1
}
Packit f546b1
Packit f546b1
static gint
Packit f546b1
gst_caps_compare_structures (gconstpointer one, gconstpointer two)
Packit f546b1
{
Packit f546b1
  gint ret;
Packit f546b1
  const GstStructure *struct1 = ((const GstCapsArrayElement *) one)->structure;
Packit f546b1
  const GstStructure *struct2 = ((const GstCapsArrayElement *) two)->structure;
Packit f546b1
Packit f546b1
  /* FIXME: this orders alphabetically, but ordering the quarks might be faster
Packit f546b1
     So what's the best way? */
Packit f546b1
  ret = strcmp (gst_structure_get_name (struct1),
Packit f546b1
      gst_structure_get_name (struct2));
Packit f546b1
Packit f546b1
  if (ret)
Packit f546b1
    return ret;
Packit f546b1
Packit f546b1
  return gst_structure_n_fields (struct2) - gst_structure_n_fields (struct1);
Packit f546b1
}
Packit f546b1
Packit f546b1
typedef struct
Packit f546b1
{
Packit f546b1
  GQuark name;
Packit f546b1
  GValue value;
Packit f546b1
  GstStructure *compare;
Packit f546b1
} UnionField;
Packit f546b1
Packit f546b1
static gboolean
Packit f546b1
gst_caps_structure_figure_out_union (GQuark field_id, const GValue * value,
Packit f546b1
    gpointer user_data)
Packit f546b1
{
Packit f546b1
  UnionField *u = user_data;
Packit f546b1
  const GValue *val = gst_structure_id_get_value (u->compare, field_id);
Packit f546b1
Packit f546b1
  if (!val) {
Packit f546b1
    if (u->name)
Packit f546b1
      g_value_unset (&u->value);
Packit f546b1
    return FALSE;
Packit f546b1
  }
Packit f546b1
Packit f546b1
  if (gst_value_compare (val, value) == GST_VALUE_EQUAL)
Packit f546b1
    return TRUE;
Packit f546b1
Packit f546b1
  if (u->name) {
Packit f546b1
    g_value_unset (&u->value);
Packit f546b1
    return FALSE;
Packit f546b1
  }
Packit f546b1
Packit f546b1
  u->name = field_id;
Packit f546b1
  gst_value_union (&u->value, val, value);
Packit f546b1
Packit f546b1
  return TRUE;
Packit f546b1
}
Packit f546b1
Packit f546b1
static gboolean
Packit f546b1
gst_caps_structure_simplify (GstStructure ** result,
Packit f546b1
    GstStructure * simplify, GstStructure * compare)
Packit f546b1
{
Packit f546b1
  GSList *list;
Packit f546b1
  UnionField field = { 0, {0,}, NULL };
Packit f546b1
Packit f546b1
  /* try to subtract to get a real subset */
Packit f546b1
  if (gst_caps_structure_subtract (&list, simplify, compare)) {
Packit f546b1
    if (list == NULL) {         /* no result */
Packit f546b1
      *result = NULL;
Packit f546b1
      return TRUE;
Packit f546b1
    } else if (list->next == NULL) {    /* one result */
Packit f546b1
      *result = list->data;
Packit f546b1
      g_slist_free (list);
Packit f546b1
      return TRUE;
Packit f546b1
    } else {                    /* multiple results */
Packit f546b1
      g_slist_foreach (list, (GFunc) gst_structure_free, NULL);
Packit f546b1
      g_slist_free (list);
Packit f546b1
      list = NULL;
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
Packit f546b1
  /* try to union both structs */
Packit f546b1
  field.compare = compare;
Packit f546b1
  if (gst_structure_foreach (simplify,
Packit f546b1
          gst_caps_structure_figure_out_union, &field)) {
Packit f546b1
    gboolean ret = FALSE;
Packit f546b1
Packit f546b1
    /* now we know all of simplify's fields are the same in compare
Packit f546b1
     * but at most one field: field.name */
Packit f546b1
    if (G_IS_VALUE (&field.value)) {
Packit f546b1
      if (gst_structure_n_fields (simplify) == gst_structure_n_fields (compare)) {
Packit f546b1
        gst_structure_id_take_value (compare, field.name, &field.value);
Packit f546b1
        *result = NULL;
Packit f546b1
        ret = TRUE;
Packit f546b1
      } else {
Packit f546b1
        g_value_unset (&field.value);
Packit f546b1
      }
Packit f546b1
    } else
Packit f546b1
        if (gst_structure_n_fields (simplify) <=
Packit f546b1
        gst_structure_n_fields (compare)) {
Packit f546b1
      /* compare is just more specific, will be optimized away later */
Packit f546b1
      /* FIXME: do this here? */
Packit f546b1
      GST_LOG ("found a case that will be optimized later.");
Packit f546b1
    } else {
Packit f546b1
      gchar *one = gst_structure_to_string (simplify);
Packit f546b1
      gchar *two = gst_structure_to_string (compare);
Packit f546b1
Packit f546b1
      GST_ERROR
Packit f546b1
          ("caps mismatch: structures %s and %s claim to be possible to unify, but aren't",
Packit f546b1
          one, two);
Packit f546b1
      g_free (one);
Packit f546b1
      g_free (two);
Packit f546b1
    }
Packit f546b1
    return ret;
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return FALSE;
Packit f546b1
}
Packit f546b1
Packit f546b1
static void
Packit f546b1
gst_caps_switch_structures (GstCaps * caps, GstStructure * old,
Packit f546b1
    GstStructure * new, gint i)
Packit f546b1
{
Packit f546b1
  gst_structure_set_parent_refcount (old, NULL);
Packit f546b1
  gst_structure_free (old);
Packit f546b1
  gst_structure_set_parent_refcount (new, &GST_CAPS_REFCOUNT (caps));
Packit f546b1
  g_array_index (GST_CAPS_ARRAY (caps), GstCapsArrayElement, i).structure = new;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_simplify:
Packit f546b1
 * @caps: (transfer full): a #GstCaps to simplify
Packit f546b1
 *
Packit f546b1
 * Converts the given @caps into a representation that represents the
Packit f546b1
 * same set of formats, but in a simpler form.  Component structures that are
Packit f546b1
 * identical are merged.  Component structures that have values that can be
Packit f546b1
 * merged are also merged.
Packit f546b1
 *
Packit f546b1
 * This function takes ownership of @caps and will call gst_caps_make_writable()
Packit f546b1
 * on it if necessary, so you must not use @caps afterwards unless you keep an
Packit f546b1
 * additional reference to it with gst_caps_ref().
Packit f546b1
 *
Packit f546b1
 * This method does not preserve the original order of @caps.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): The simplified caps.
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_simplify (GstCaps * caps)
Packit f546b1
{
Packit f546b1
  GstStructure *simplify, *compare, *result = NULL;
Packit f546b1
  GstCapsFeatures *simplify_f, *compare_f;
Packit f546b1
  gint i, j, start;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
Packit f546b1
Packit f546b1
  start = GST_CAPS_LEN (caps) - 1;
Packit f546b1
  /* one caps, already as simple as can be */
Packit f546b1
  if (start == 0)
Packit f546b1
    return caps;
Packit f546b1
Packit f546b1
  caps = gst_caps_make_writable (caps);
Packit f546b1
Packit f546b1
  g_array_sort (GST_CAPS_ARRAY (caps), gst_caps_compare_structures);
Packit f546b1
Packit f546b1
  for (i = start; i >= 0; i--) {
Packit f546b1
    simplify = gst_caps_get_structure_unchecked (caps, i);
Packit f546b1
    simplify_f = gst_caps_get_features_unchecked (caps, i);
Packit f546b1
    if (!simplify_f)
Packit f546b1
      simplify_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
    compare = gst_caps_get_structure_unchecked (caps, start);
Packit f546b1
    compare_f = gst_caps_get_features_unchecked (caps, start);
Packit f546b1
    if (!compare_f)
Packit f546b1
      compare_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
    if (gst_structure_get_name_id (simplify) !=
Packit f546b1
        gst_structure_get_name_id (compare) ||
Packit f546b1
        !gst_caps_features_is_equal (simplify_f, compare_f))
Packit f546b1
      start = i;
Packit f546b1
    for (j = start; j >= 0; j--) {
Packit f546b1
      if (j == i)
Packit f546b1
        continue;
Packit f546b1
      compare = gst_caps_get_structure_unchecked (caps, j);
Packit f546b1
      compare_f = gst_caps_get_features_unchecked (caps, j);
Packit f546b1
      if (!compare_f)
Packit f546b1
        compare_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
Packit f546b1
      if (gst_structure_get_name_id (simplify) !=
Packit f546b1
          gst_structure_get_name_id (compare) ||
Packit f546b1
          !gst_caps_features_is_equal (simplify_f, compare_f)) {
Packit f546b1
        break;
Packit f546b1
      }
Packit f546b1
      if (gst_caps_structure_simplify (&result, simplify, compare)) {
Packit f546b1
        if (result) {
Packit f546b1
          gst_caps_switch_structures (caps, simplify, result, i);
Packit f546b1
          simplify = result;
Packit f546b1
        } else {
Packit f546b1
          gst_caps_remove_structure (caps, i);
Packit f546b1
          start--;
Packit f546b1
          break;
Packit f546b1
        }
Packit f546b1
      }
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
  return caps;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_fixate:
Packit f546b1
 * @caps: (transfer full): a #GstCaps to fixate
Packit f546b1
 *
Packit f546b1
 * Modifies the given @caps into a representation with only fixed
Packit f546b1
 * values. First the caps will be truncated and then the first structure will be
Packit f546b1
 * fixated with gst_structure_fixate().
Packit f546b1
 *
Packit f546b1
 * This function takes ownership of @caps and will call gst_caps_make_writable()
Packit f546b1
 * on it so you must not use @caps afterwards unless you keep an additional
Packit f546b1
 * reference to it with gst_caps_ref().
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): the fixated caps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_fixate (GstCaps * caps)
Packit f546b1
{
Packit f546b1
  GstStructure *s;
Packit f546b1
  GstCapsFeatures *f;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
Packit f546b1
Packit f546b1
  /* default fixation */
Packit f546b1
  caps = gst_caps_truncate (caps);
Packit f546b1
  caps = gst_caps_make_writable (caps);
Packit f546b1
  s = gst_caps_get_structure (caps, 0);
Packit f546b1
  gst_structure_fixate (s);
Packit f546b1
Packit f546b1
  /* Set features to sysmem if they're still ANY */
Packit f546b1
  f = gst_caps_get_features_unchecked (caps, 0);
Packit f546b1
  if (f && gst_caps_features_is_any (f)) {
Packit f546b1
    f = gst_caps_features_new_empty ();
Packit f546b1
    gst_caps_set_features (caps, 0, f);
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return caps;
Packit f546b1
}
Packit f546b1
Packit f546b1
/* utility */
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_to_string:
Packit f546b1
 * @caps: a #GstCaps
Packit f546b1
 *
Packit f546b1
 * Converts @caps to a string representation.  This string representation
Packit f546b1
 * can be converted back to a #GstCaps by gst_caps_from_string().
Packit f546b1
 *
Packit f546b1
 * For debugging purposes its easier to do something like this:
Packit f546b1
 * |[
Packit f546b1
 * GST_LOG ("caps are %" GST_PTR_FORMAT, caps);
Packit f546b1
 * ]|
Packit f546b1
 * This prints the caps in human readable form.
Packit f546b1
 *
Packit f546b1
 * The current implementation of serialization will lead to unexpected results
Packit f546b1
 * when there are nested #GstCaps / #GstStructure deeper than one level.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full): a newly allocated string representing @caps.
Packit f546b1
 */
Packit f546b1
gchar *
Packit f546b1
gst_caps_to_string (const GstCaps * caps)
Packit f546b1
{
Packit f546b1
  guint i, slen, clen;
Packit f546b1
  GString *s;
Packit f546b1
Packit f546b1
  /* NOTE:  This function is potentially called by the debug system,
Packit f546b1
   * so any calls to gst_log() (and GST_DEBUG(), GST_LOG(), etc.)
Packit f546b1
   * should be careful to avoid recursion.  This includes any functions
Packit f546b1
   * called by gst_caps_to_string.  In particular, calls should
Packit f546b1
   * not use the GST_PTR_FORMAT extension.  */
Packit f546b1
Packit f546b1
  if (caps == NULL) {
Packit f546b1
    return g_strdup ("NULL");
Packit f546b1
  }
Packit f546b1
  if (CAPS_IS_ANY (caps)) {
Packit f546b1
    return g_strdup ("ANY");
Packit f546b1
  }
Packit f546b1
  if (CAPS_IS_EMPTY_SIMPLE (caps)) {
Packit f546b1
    return g_strdup ("EMPTY");
Packit f546b1
  }
Packit f546b1
Packit f546b1
  /* estimate a rough string length to avoid unnecessary reallocs in GString */
Packit f546b1
  slen = 0;
Packit f546b1
  clen = GST_CAPS_LEN (caps);
Packit f546b1
  for (i = 0; i < clen; i++) {
Packit f546b1
    GstCapsFeatures *f;
Packit f546b1
Packit f546b1
    slen +=
Packit f546b1
        STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure_unchecked
Packit f546b1
        (caps, i));
Packit f546b1
    f = gst_caps_get_features_unchecked (caps, i);
Packit f546b1
    if (f)
Packit f546b1
      slen += FEATURES_ESTIMATED_STRING_LEN (f);
Packit f546b1
  }
Packit f546b1
Packit f546b1
  s = g_string_sized_new (slen);
Packit f546b1
  for (i = 0; i < clen; i++) {
Packit f546b1
    GstStructure *structure;
Packit f546b1
    GstCapsFeatures *features;
Packit f546b1
Packit f546b1
    if (i > 0) {
Packit f546b1
      /* ';' is now added by gst_structure_to_string */
Packit f546b1
      g_string_append_c (s, ' ');
Packit f546b1
    }
Packit f546b1
Packit f546b1
    structure = gst_caps_get_structure_unchecked (caps, i);
Packit f546b1
    features = gst_caps_get_features_unchecked (caps, i);
Packit f546b1
Packit f546b1
    g_string_append (s, gst_structure_get_name (structure));
Packit f546b1
    if (features && (gst_caps_features_is_any (features)
Packit f546b1
            || !gst_caps_features_is_equal (features,
Packit f546b1
                GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))) {
Packit f546b1
      g_string_append_c (s, '(');
Packit f546b1
      priv_gst_caps_features_append_to_gstring (features, s);
Packit f546b1
      g_string_append_c (s, ')');
Packit f546b1
    }
Packit f546b1
    priv_gst_structure_append_to_gstring (structure, s);
Packit f546b1
  }
Packit f546b1
  if (s->len && s->str[s->len - 1] == ';') {
Packit f546b1
    /* remove latest ';' */
Packit f546b1
    s->str[--s->len] = '\0';
Packit f546b1
  }
Packit f546b1
  return g_string_free (s, FALSE);
Packit f546b1
}
Packit f546b1
Packit f546b1
static gboolean
Packit f546b1
gst_caps_from_string_inplace (GstCaps * caps, const gchar * string)
Packit f546b1
{
Packit f546b1
  GstStructure *structure;
Packit f546b1
  gchar *s, *copy, *end, *next, save;
Packit f546b1
Packit f546b1
  if (strcmp ("ANY", string) == 0) {
Packit f546b1
    GST_CAPS_FLAGS (caps) = GST_CAPS_FLAG_ANY;
Packit f546b1
    return TRUE;
Packit f546b1
  }
Packit f546b1
Packit f546b1
  if (strcmp ("EMPTY", string) == 0 || strcmp ("NONE", string) == 0) {
Packit f546b1
    return TRUE;
Packit f546b1
  }
Packit f546b1
Packit f546b1
  copy = s = g_strdup (string);
Packit f546b1
  do {
Packit f546b1
    GstCapsFeatures *features = NULL;
Packit f546b1
Packit f546b1
    while (g_ascii_isspace (*s))
Packit f546b1
      s++;
Packit f546b1
    if (*s == '\0') {
Packit f546b1
      break;
Packit f546b1
    }
Packit f546b1
Packit f546b1
    if (!priv_gst_structure_parse_name (s, &s, &end, &next)) {
Packit f546b1
      g_free (copy);
Packit f546b1
      return FALSE;
Packit f546b1
    }
Packit f546b1
Packit f546b1
    save = *end;
Packit f546b1
    *end = '\0';
Packit f546b1
    structure = gst_structure_new_empty (s);
Packit f546b1
    *end = save;
Packit f546b1
Packit f546b1
    if (structure == NULL) {
Packit f546b1
      g_free (copy);
Packit f546b1
      return FALSE;
Packit f546b1
    }
Packit f546b1
Packit f546b1
    s = next;
Packit f546b1
Packit f546b1
    if (*s == '\0') {
Packit f546b1
      goto append;
Packit f546b1
    }
Packit f546b1
Packit f546b1
    if (*s == '(') {
Packit f546b1
      s++;
Packit f546b1
      end = s;
Packit f546b1
Packit f546b1
      while (TRUE) {
Packit f546b1
        if (*end == '\0') {
Packit f546b1
          break;
Packit f546b1
        } else if (*end == ')') {
Packit f546b1
          break;
Packit f546b1
        } else {
Packit f546b1
          end++;
Packit f546b1
        }
Packit f546b1
      }
Packit f546b1
Packit f546b1
      save = *end;
Packit f546b1
      *end = '\0';
Packit f546b1
      features = gst_caps_features_from_string (s);
Packit f546b1
      if (!features) {
Packit f546b1
        gst_structure_free (structure);
Packit f546b1
        g_free (copy);
Packit f546b1
        return FALSE;
Packit f546b1
      }
Packit f546b1
      *end = save;
Packit f546b1
      s = end;
Packit f546b1
      if (save == ')')
Packit f546b1
        s++;
Packit f546b1
    }
Packit f546b1
Packit f546b1
    if (*s == '\0') {
Packit f546b1
      goto append;
Packit f546b1
    }
Packit f546b1
Packit f546b1
    if (!priv_gst_structure_parse_fields (s, &s, structure)) {
Packit f546b1
      gst_structure_free (structure);
Packit f546b1
      if (features)
Packit f546b1
        gst_caps_features_free (features);
Packit f546b1
      g_free (copy);
Packit f546b1
      return FALSE;
Packit f546b1
    }
Packit f546b1
Packit f546b1
  append:
Packit f546b1
    gst_caps_append_structure_unchecked (caps, structure, features);
Packit f546b1
    features = NULL;
Packit f546b1
    if (*s == '\0')
Packit f546b1
      break;
Packit f546b1
  } while (TRUE);
Packit f546b1
Packit f546b1
  g_free (copy);
Packit f546b1
Packit f546b1
  return TRUE;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_from_string:
Packit f546b1
 * @string: a string to convert to #GstCaps
Packit f546b1
 *
Packit f546b1
 * Converts @caps from a string representation.
Packit f546b1
 *
Packit f546b1
 * The current implementation of serialization will lead to unexpected results
Packit f546b1
 * when there are nested #GstCaps / #GstStructure deeper than one level.
Packit f546b1
 *
Packit f546b1
 * Returns: (transfer full) (nullable): a newly allocated #GstCaps
Packit f546b1
 */
Packit f546b1
GstCaps *
Packit f546b1
gst_caps_from_string (const gchar * string)
Packit f546b1
{
Packit f546b1
  GstCaps *caps;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (string, FALSE);
Packit f546b1
Packit f546b1
  caps = gst_caps_new_empty ();
Packit f546b1
  if (gst_caps_from_string_inplace (caps, string)) {
Packit f546b1
    return caps;
Packit f546b1
  } else {
Packit f546b1
    gst_caps_unref (caps);
Packit f546b1
    return NULL;
Packit f546b1
  }
Packit f546b1
}
Packit f546b1
Packit f546b1
static void
Packit f546b1
gst_caps_transform_to_string (const GValue * src_value, GValue * dest_value)
Packit f546b1
{
Packit f546b1
  g_return_if_fail (G_IS_VALUE (src_value));
Packit f546b1
  g_return_if_fail (G_IS_VALUE (dest_value));
Packit f546b1
  g_return_if_fail (G_VALUE_HOLDS (src_value, GST_TYPE_CAPS));
Packit f546b1
  g_return_if_fail (G_VALUE_HOLDS (dest_value, G_TYPE_STRING)
Packit f546b1
      || G_VALUE_HOLDS (dest_value, G_TYPE_POINTER));
Packit f546b1
Packit f546b1
  g_value_take_string (dest_value,
Packit f546b1
      gst_caps_to_string (gst_value_get_caps (src_value)));
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_foreach:
Packit f546b1
 * @caps: a #GstCaps
Packit f546b1
 * @func: (scope call): a function to call for each field
Packit f546b1
 * @user_data: (closure): private data
Packit f546b1
 *
Packit f546b1
 * Calls the provided function once for each structure and caps feature in the
Packit f546b1
 * #GstCaps. The function must not modify the fields.
Packit f546b1
 * Also see gst_caps_map_in_place() and gst_caps_filter_and_map_in_place().
Packit f546b1
 *
Packit f546b1
 * Returns: %TRUE if the supplied function returns %TRUE for each call,
Packit f546b1
 * %FALSE otherwise.
Packit f546b1
 *
Packit f546b1
 * Since: 1.6
Packit f546b1
 */
Packit f546b1
gboolean
Packit f546b1
gst_caps_foreach (const GstCaps * caps, GstCapsForeachFunc func,
Packit f546b1
    gpointer user_data)
Packit f546b1
{
Packit f546b1
  guint i, n;
Packit f546b1
  GstCapsFeatures *features;
Packit f546b1
  GstStructure *structure;
Packit f546b1
  gboolean ret;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
Packit f546b1
  g_return_val_if_fail (func != NULL, FALSE);
Packit f546b1
Packit f546b1
  n = GST_CAPS_LEN (caps);
Packit f546b1
Packit f546b1
  for (i = 0; i < n; i++) {
Packit f546b1
    features = gst_caps_get_features_unchecked (caps, i);
Packit f546b1
    structure = gst_caps_get_structure_unchecked (caps, i);
Packit f546b1
Packit f546b1
    ret = func (features, structure, user_data);
Packit f546b1
    if (G_UNLIKELY (!ret))
Packit f546b1
      return FALSE;
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return TRUE;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_map_in_place:
Packit f546b1
 * @caps: a #GstCaps
Packit f546b1
 * @func: (scope call): a function to call for each field
Packit f546b1
 * @user_data: (closure): private data
Packit f546b1
 *
Packit f546b1
 * Calls the provided function once for each structure and caps feature in the
Packit f546b1
 * #GstCaps. In contrast to gst_caps_foreach(), the function may modify but not
Packit f546b1
 * delete the structures and features. The caps must be mutable.
Packit f546b1
 *
Packit f546b1
 * Returns: %TRUE if the supplied function returns %TRUE for each call,
Packit f546b1
 * %FALSE otherwise.
Packit f546b1
 *
Packit f546b1
 * Since: 1.6
Packit f546b1
 */
Packit f546b1
gboolean
Packit f546b1
gst_caps_map_in_place (GstCaps * caps, GstCapsMapFunc func, gpointer user_data)
Packit f546b1
{
Packit f546b1
  guint i, n;
Packit f546b1
  GstCapsFeatures *features;
Packit f546b1
  GstStructure *structure;
Packit f546b1
  gboolean ret;
Packit f546b1
Packit f546b1
  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
Packit f546b1
  g_return_val_if_fail (gst_caps_is_writable (caps), FALSE);
Packit f546b1
  g_return_val_if_fail (func != NULL, FALSE);
Packit f546b1
Packit f546b1
  n = GST_CAPS_LEN (caps);
Packit f546b1
Packit f546b1
  for (i = 0; i < n; i++) {
Packit f546b1
    features = gst_caps_get_features_unchecked (caps, i);
Packit f546b1
    structure = gst_caps_get_structure_unchecked (caps, i);
Packit f546b1
Packit f546b1
    /* Provide sysmem features if there are none yet */
Packit f546b1
    if (!features) {
Packit f546b1
      features =
Packit f546b1
          gst_caps_features_copy (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY);
Packit f546b1
      gst_caps_set_features (caps, i, features);
Packit f546b1
    }
Packit f546b1
Packit f546b1
    ret = func (features, structure, user_data);
Packit f546b1
    if (G_UNLIKELY (!ret))
Packit f546b1
      return FALSE;
Packit f546b1
  }
Packit f546b1
Packit f546b1
  return TRUE;
Packit f546b1
}
Packit f546b1
Packit f546b1
/**
Packit f546b1
 * gst_caps_filter_and_map_in_place:
Packit f546b1
 * @caps: a #GstCaps
Packit f546b1
 * @func: (scope call): a function to call for each field
Packit f546b1
 * @user_data: (closure): private data
Packit f546b1
 *
Packit f546b1
 * Calls the provided function once for each structure and caps feature in the
Packit f546b1
 * #GstCaps. In contrast to gst_caps_foreach(), the function may modify the
Packit f546b1
 * structure and features. In contrast to gst_caps_filter_and_map_in_place(),
Packit f546b1
 * the structure and features are removed from the caps if %FALSE is returned
Packit f546b1
 * from the function.
Packit f546b1
 * The caps must be mutable.
Packit f546b1
 *
Packit f546b1
 * Since: 1.6
Packit f546b1
 */
Packit f546b1
void
Packit f546b1
gst_caps_filter_and_map_in_place (GstCaps * caps, GstCapsFilterMapFunc func,
Packit f546b1
    gpointer user_data)
Packit f546b1
{
Packit f546b1
  guint i, n;
Packit f546b1
  GstCapsFeatures *features;
Packit f546b1
  GstStructure *structure;
Packit f546b1
  gboolean ret;
Packit f546b1
Packit f546b1
  g_return_if_fail (GST_IS_CAPS (caps));
Packit f546b1
  g_return_if_fail (gst_caps_is_writable (caps));
Packit f546b1
  g_return_if_fail (func != NULL);
Packit f546b1
Packit f546b1
  n = GST_CAPS_LEN (caps);
Packit f546b1
Packit f546b1
  for (i = 0; i < n;) {
Packit f546b1
    features = gst_caps_get_features_unchecked (caps, i);
Packit f546b1
    structure = gst_caps_get_structure_unchecked (caps, i);
Packit f546b1
Packit f546b1
    /* Provide sysmem features if there are none yet */
Packit f546b1
    if (!features) {
Packit f546b1
      features =
Packit f546b1
          gst_caps_features_copy (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY);
Packit f546b1
      gst_caps_set_features (caps, i, features);
Packit f546b1
    }
Packit f546b1
Packit f546b1
    ret = func (features, structure, user_data);
Packit f546b1
    if (!ret) {
Packit f546b1
      GST_CAPS_ARRAY (caps) = g_array_remove_index (GST_CAPS_ARRAY (caps), i);
Packit f546b1
Packit f546b1
      gst_structure_set_parent_refcount (structure, NULL);
Packit f546b1
      gst_structure_free (structure);
Packit f546b1
      if (features) {
Packit f546b1
        gst_caps_features_set_parent_refcount (features, NULL);
Packit f546b1
        gst_caps_features_free (features);
Packit f546b1
      }
Packit f546b1
Packit f546b1
      n = GST_CAPS_LEN (caps);
Packit f546b1
    } else {
Packit f546b1
      i++;
Packit f546b1
    }
Packit f546b1
  }
Packit f546b1
}