2
* Copyright (C) 2006-2009 Mark Nauwelaerts <mnauw@users.sourceforge.net>
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Library General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Library General Public License for more details.
14
* You should have received a copy of the GNU Library General Public
15
* License along with this library; if not, write to the
16
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
* Boston, MA 02110-1307, USA.
21
* SECTION:element-capssetter
25
* Sets or merges caps on a stream's buffers.
26
* That is, a buffer's caps are updated using (fields of)
27
* <link linkend="GstCapsSetter--caps">caps</link>. Note that this may
28
* contain multiple structures (though not likely recommended), but each
29
* of these must be fixed (or will otherwise be rejected).
32
* If <link linkend="GstCapsSetter--join">join</link>
33
* is TRUE, then the incoming caps' mime-type is compared to the mime-type(s)
34
* of provided caps and only matching structure(s) are considered for updating.
37
* If <link linkend="GstCapsSetter--replace">replace</link>
38
* is TRUE, then any caps update is preceded by clearing existing fields,
39
* making provided fields (as a whole) replace incoming ones.
40
* Otherwise, no clearing is performed, in which case provided fields are
41
* added/merged onto incoming caps
44
* Although this element might mainly serve as debug helper,
45
* it can also practically be used to correct a faulty pixel-aspect-ratio,
46
* or to modify a yuv fourcc value to effectively swap chroma components or such
58
#include "plugin-entrans.h"
63
#define GST_TYPE_CAPS_SETTER \
64
(gst_caps_setter_get_type())
65
#define GST_CAPS_SETTER(obj) \
66
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAPS_SETTER,GstCapsSetter))
67
#define GST_CAPS_SETTER_CLASS(klass) \
68
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAPS_SETTER,GstCapsSetterClass))
69
#define GST_IS_CAPS_SETTER(obj) \
70
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAPS_SETTER))
71
#define GST_IS_CAPS_SETTER_CLASS(klass) \
72
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAPS_SETTER))
75
typedef struct _GstCapsSetter GstCapsSetter;
76
typedef struct _GstCapsSetterClass GstCapsSetterClass;
80
GstBaseTransform parent;
89
struct _GstCapsSetterClass
91
GstBaseTransformClass parent_class;
94
GST_DEBUG_CATEGORY_STATIC (caps_setter_debug);
95
#define GST_CAT_DEFAULT caps_setter_debug
98
/* signals and args */
114
#define DEFAULT_JOIN TRUE
115
#define DEFAULT_REPLACE FALSE
117
static GstElementDetails caps_setter_details =
118
GST_ELEMENT_DETAILS ("CapsSetter",
120
"Set/merge caps on stream",
121
"Mark Nauwelaerts <mnauw@users.sourceforge.net>");
123
static GstStaticPadTemplate gst_caps_setter_src_template =
124
GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SRC_NAME,
127
GST_STATIC_CAPS_ANY);
129
static GstStaticPadTemplate gst_caps_setter_sink_template =
130
GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SINK_NAME,
133
GST_STATIC_CAPS_ANY);
136
static gboolean gst_caps_setter_transform_size (GstBaseTransform *trans,
137
GstPadDirection direction, GstCaps *caps, guint size,
138
GstCaps *othercaps, guint *othersize);
139
static GstCaps* gst_caps_setter_transform_caps (GstBaseTransform * trans,
140
GstPadDirection direction, GstCaps * caps);
141
static GstFlowReturn gst_caps_setter_transform_ip (GstBaseTransform * btrans,
144
static void gst_caps_setter_finalize (GObject * object);
146
static void gst_caps_setter_set_property (GObject * object, guint prop_id,
147
const GValue * value, GParamSpec * pspec);
148
static void gst_caps_setter_get_property (GObject * object, guint prop_id,
149
GValue * value, GParamSpec * pspec);
151
GST_BOILERPLATE (GstCapsSetter, gst_caps_setter, GstBaseTransform,
152
GST_TYPE_BASE_TRANSFORM);
155
gst_caps_setter_base_init (gpointer g_class)
157
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
159
gst_element_class_set_details (element_class, &caps_setter_details);
161
gst_element_class_add_pad_template (element_class,
162
gst_static_pad_template_get (&gst_caps_setter_sink_template));
163
gst_element_class_add_pad_template (element_class,
164
gst_static_pad_template_get (&gst_caps_setter_src_template));
168
gst_caps_setter_class_init (GstCapsSetterClass * g_class)
170
GObjectClass *gobject_class;
171
GstBaseTransformClass *trans_class;
173
gobject_class = G_OBJECT_CLASS (g_class);
174
trans_class = GST_BASE_TRANSFORM_CLASS (g_class);
176
GST_DEBUG_CATEGORY_INIT (caps_setter_debug, "capssetter", 0, "capssetter");
178
gobject_class->set_property = gst_caps_setter_set_property;
179
gobject_class->get_property = gst_caps_setter_get_property;
181
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_caps_setter_finalize);
183
g_object_class_install_property (gobject_class, PROP_CAPS,
184
g_param_spec_boxed ("caps", "Merge caps",
185
"Merge these caps (thereby overwriting) in the stream",
186
GST_TYPE_CAPS, G_PARAM_READWRITE));
187
g_object_class_install_property (gobject_class, PROP_JOIN,
188
g_param_spec_boolean ("join", "Join",
189
"Match incoming caps' mime-type to mime-type of provided caps",
190
DEFAULT_JOIN, G_PARAM_READWRITE));
191
g_object_class_install_property (gobject_class, PROP_REPLACE,
192
g_param_spec_boolean ("replace", "Replace",
193
"Drop fields of incoming caps",
194
DEFAULT_REPLACE, G_PARAM_READWRITE));
196
trans_class->transform_size =
197
GST_DEBUG_FUNCPTR (gst_caps_setter_transform_size);
198
trans_class->transform_caps =
199
GST_DEBUG_FUNCPTR (gst_caps_setter_transform_caps);
200
/* dummy seems needed */
201
trans_class->transform_ip =
202
GST_DEBUG_FUNCPTR (gst_caps_setter_transform_ip);
206
gst_caps_setter_init (GstCapsSetter * filter, GstCapsSetterClass * g_class)
208
filter->caps = gst_caps_new_any ();
209
filter->join = DEFAULT_JOIN;
210
filter->replace = DEFAULT_REPLACE;
214
gst_caps_setter_finalize (GObject * object)
216
GstCapsSetter *filter = GST_CAPS_SETTER (object);
218
gst_caps_replace (&filter->caps, NULL);
220
G_OBJECT_CLASS (parent_class)->finalize (object);
224
gst_caps_setter_transform_size (GstBaseTransform *trans,
225
GstPadDirection direction, GstCaps *caps, guint size,
226
GstCaps *othercaps, guint *othersize)
234
gst_caps_setter_transform_caps (GstBaseTransform * trans,
235
GstPadDirection direction, GstCaps * caps)
237
GstCapsSetter *filter;
238
GstCaps *ret, *filter_caps;
239
GstStructure *structure, *merge;
243
filter = GST_CAPS_SETTER (trans);
245
GST_DEBUG_OBJECT (trans, "receiving caps: %" GST_PTR_FORMAT, caps);
247
ret = gst_caps_copy (caps);
249
/* this function is always called with a simple caps */
250
if (!GST_CAPS_IS_SIMPLE (ret) || direction != GST_PAD_SINK)
253
structure = gst_caps_get_structure (ret, 0);
254
name = gst_structure_get_name (structure);
256
GST_OBJECT_LOCK (filter);
257
filter_caps = gst_caps_ref (filter->caps);
258
GST_OBJECT_UNLOCK (filter);
260
for (i = 0; i < gst_caps_get_size (filter_caps); ++i) {
261
merge = gst_caps_get_structure (filter_caps, i);
262
if (gst_structure_has_name (merge, name) || !filter->join) {
265
gst_structure_set_name (structure, gst_structure_get_name (merge));
268
gst_structure_remove_all_fields (structure);
270
for (j = 0; j < gst_structure_n_fields (merge); ++j) {
273
fname = gst_structure_nth_field_name (merge, j);
274
gst_structure_set_value (structure, fname,
275
gst_structure_get_value (merge, fname));
280
GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, ret);
282
gst_caps_unref (filter_caps);
288
gst_caps_setter_transform_ip (GstBaseTransform * btrans, GstBuffer * in)
294
gst_caps_is_fixed_foreach (GQuark field_id, const GValue * value,
297
return gst_value_is_fixed (value);
301
gst_caps_setter_set_property (GObject * object, guint prop_id,
302
const GValue * value, GParamSpec * pspec)
304
GstCapsSetter *filter;
306
g_return_if_fail (GST_IS_CAPS_SETTER (object));
307
filter = GST_CAPS_SETTER (object);
312
const GstCaps *new_caps_val = gst_value_get_caps (value);
315
if (new_caps_val == NULL) {
316
new_caps = gst_caps_new_any ();
318
new_caps = gst_caps_copy (new_caps_val);
321
for (i = 0; new_caps && (i < gst_caps_get_size (new_caps)); ++i) {
324
s = gst_caps_get_structure (new_caps, i);
325
if (!gst_structure_foreach (s, gst_caps_is_fixed_foreach, NULL)) {
326
GST_ERROR_OBJECT (filter, "rejected unfixed caps: %" GST_PTR_FORMAT,
328
gst_caps_unref (new_caps);
335
GST_OBJECT_LOCK (filter);
336
gst_caps_replace (&filter->caps, new_caps);
338
gst_caps_unref (new_caps);
339
GST_OBJECT_UNLOCK (filter);
341
GST_DEBUG_OBJECT (filter, "set new caps %" GST_PTR_FORMAT, new_caps);
344
/* try to activate these new caps next time around */
345
gst_base_transform_reconfigure (GST_BASE_TRANSFORM (filter));
349
filter->join = g_value_get_boolean (value);
352
filter->replace = g_value_get_boolean (value);
355
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
361
gst_caps_setter_get_property (GObject * object, guint prop_id, GValue * value,
364
GstCapsSetter *filter;
366
g_return_if_fail (GST_IS_CAPS_SETTER (object));
367
filter = GST_CAPS_SETTER (object);
371
gst_value_set_caps (value, filter->caps);
374
g_value_set_boolean (value, filter->join);
377
g_value_set_boolean (value, filter->replace);
380
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);