Blame gst/gstcaps.c

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