summaryrefslogtreecommitdiff
path: root/gst-libs/gst/cairo/gstcairocaps.c
blob: 433e2ca1a5dbdded1734c8292732c84f01403ee8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* GStreamer
 * Copyright (C) 2009 Benjamin Otte <otte@gnome.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include "gstcairocaps.h"

#include <string.h>
#include <gobject/gvaluecollector.h>

#include "gstcairocapsany.h"

/**
 * SECTION:gstcairocaps
 * @title: Caps
 * @short_description: caps negotiation and format handling
 *
 * This section describes how to handle #GstCaps inside an element that
 * uses this library.
 *
 * Fixed caps as passed to a setcaps function are converted into a
 * #GstCairoFormat using gst_cairo_format_new(), which is a simple and
 * fast wrapper around a static caps. It is suggested that you do not store
 * things like framerate, width or height, but use a #GstCairoFormat instead.
 * These formats are also required when converting a #GstBuffer into a
 * #cairo_surface_t.
 *
 * The GStreamer Cairo library also provides some utility function that 
 * help during caps negotiation. Those are listed here, too. The most 
 * important one certainly is gst_cairo_caps_expand() that eases caps
 * transformations.
 */

/**
 * gst_cairo_caps_any:
 *
 * Returns a #GstCaps that references all formats that can be handled by
 * this library. The returned caps will not be writable. Use 
 * gst_caps_make_writable() if you want to change them.
 * <note>The caps returned by this function can change between versions
 * of this library as new formats are added.</note>
 *
 * Returns: a #GstCaps, use gst_caps_unref() to get rid of it. The caps will
 *          not be writable.
 **/
GstCaps *
gst_cairo_caps_any (void)
{
  GstCaps *any = NULL;

  if (g_once_init_enter ((gsize *) & any)) {
    GstCaps *caps = gst_caps_from_string (GST_CAIRO_CAPS_ANY);
    g_once_init_leave ((gsize *) & any, GPOINTER_TO_SIZE (caps));
  }

  return gst_caps_copy (any);
}

/**
 * gst_cairo_caps_expand:
 * @caps: a valid cairo caps to expand
 * @expand: parts of the caps that should be expanded
 *
 * Expands the given @caps so that all options set in @expand are expanded
 * to all their options. This function is useful in caps negotiation when
 * your element is transforming the Cairo data given to it, like in a 
 * colorspace or scaling element.
 *
 * Returns: a new caps with the expanded fields.
 **/
GstCaps *
gst_cairo_caps_expand (const GstCaps * caps, GstCairoFormatOption expand)
{
  GstCaps *expanded;
  guint i;

  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);

  /* start with a copy of the current caps - we prefer unchanged caps */
  expanded = gst_caps_copy (caps);

  for (i = 0; i < gst_caps_get_size (caps); i++) {
    GstStructure *expand_me = gst_caps_get_structure (caps, i);
    GstCaps *copy;

    if (expand & GST_CAIRO_FORMAT_FORMAT) {
      copy = gst_caps_make_writable (gst_cairo_caps_any ());
    } else {
      copy = gst_caps_copy_nth (caps, i);
    }

    if (expand & GST_CAIRO_FORMAT_WIDTH) {
      gst_caps_set_simple (copy, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
          NULL);
    } else {
      gst_caps_set_value (copy, "width",
          gst_structure_get_value (expand_me, "width"));
    }

    if (expand & GST_CAIRO_FORMAT_HEIGHT) {
      gst_caps_set_simple (copy, "height", GST_TYPE_INT_RANGE, 1,
          G_MAXINT, NULL);
    } else {
      gst_caps_set_value (copy, "height",
          gst_structure_get_value (expand_me, "height"));
    }

    if (expand & GST_CAIRO_FORMAT_FRAMERATE) {
      gst_caps_set_simple (copy, "framerate", GST_TYPE_FRACTION_RANGE, 0,
          1, G_MAXINT, 1, NULL);
    } else {
      gst_caps_set_value (copy, "framerate",
          gst_structure_get_value (expand_me, "framerate"));
    }

    if (expand & GST_CAIRO_FORMAT_PAR) {
      guint j;
      for (j = 0; j < gst_caps_get_size (copy); j++) {
        gst_structure_remove_field (gst_caps_get_structure (copy, j),
            "pixel-aspect-ratio");
      }
    } else {
      const GValue *value =
          gst_structure_get_value (expand_me, "pixel-aspect-ratio");
      if (value)
        gst_caps_set_value (copy, "pixel-aspect-ratio", value);
    }

    gst_caps_append (expanded, copy);
  }

  return expanded;
}