2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
5 * Copyright (C) 2001 FUKUCHI Kentarou
7 * EffecTV is free software. This library is free software;
8 * you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
28 #include <gstvideofilter.h>
33 #include <gst/video/video.h>
35 #define GST_TYPE_QUARKTV \
36 (gst_quarktv_get_type())
37 #define GST_QUARKTV(obj) \
38 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_QUARKTV,GstQuarkTV))
39 #define GST_QUARKTV_CLASS(klass) \
40 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_QUARKTV,GstQuarkTVClass))
41 #define GST_IS_QUARKTV(obj) \
42 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_QUARKTV))
43 #define GST_IS_QUARKTV_CLASS(obj) \
44 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_QUARKTV))
46 /* number of frames of time-buffer. It should be as a configurable paramater */
47 /* This number also must be 2^n just for the speed. */
50 typedef struct _GstQuarkTV GstQuarkTV;
51 typedef struct _GstQuarkTVClass GstQuarkTVClass;
55 GstVideofilter element;
61 GstBuffer **planetable;
64 struct _GstQuarkTVClass
66 GstVideofilterClass parent_class;
75 GType gst_quarktv_get_type (void);
77 static GstElementDetails quarktv_details = GST_ELEMENT_DETAILS ("QuarkTV",
78 "Filter/Effect/Video",
80 "FUKUCHI, Kentarou <fukuchi@users.sourceforge.net>");
82 static GstStaticPadTemplate gst_quarktv_src_template =
83 GST_STATIC_PAD_TEMPLATE ("src",
86 GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx "; " GST_VIDEO_CAPS_RGBx)
89 static GstStaticPadTemplate gst_quarktv_sink_template =
90 GST_STATIC_PAD_TEMPLATE ("sink",
93 GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx "; " GST_VIDEO_CAPS_RGBx)
96 static GstVideofilterClass *parent_class = NULL;
99 gst_quarktv_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
102 GstQuarkTV *filter = GST_QUARKTV (btrans);
103 GstStructure *structure;
104 gboolean ret = FALSE;
106 structure = gst_caps_get_structure (incaps, 0);
108 if (gst_structure_get_int (structure, "width", &filter->width) &&
109 gst_structure_get_int (structure, "height", &filter->height)) {
110 filter->area = filter->width * filter->height;
118 gst_quarktv_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
122 GstStructure *structure;
123 gboolean ret = FALSE;
126 filter = GST_QUARKTV (btrans);
128 structure = gst_caps_get_structure (caps, 0);
130 if (gst_structure_get_int (structure, "width", &width) &&
131 gst_structure_get_int (structure, "height", &height)) {
132 *size = width * height * 32 / 8;
134 GST_DEBUG_OBJECT (filter, "our frame size is %d bytes (%dx%d)", *size,
141 static inline guint32
144 static unsigned int fastrand_val;
146 return (fastrand_val = fastrand_val * 1103515245 + 12345);
150 gst_quarktv_transform (GstBaseTransform * trans, GstBuffer * in,
156 GstFlowReturn ret = GST_FLOW_OK;
158 filter = GST_QUARKTV (trans);
160 gst_buffer_stamp (out, in);
163 src = (guint32 *) GST_BUFFER_DATA (in);
164 dest = (guint32 *) GST_BUFFER_DATA (out);
166 if (filter->planetable[filter->current_plane])
167 gst_buffer_unref (filter->planetable[filter->current_plane]);
169 filter->planetable[filter->current_plane] = gst_buffer_ref (in);
175 /* pick a random buffer */
177 filter->planetable[(filter->current_plane +
178 (fastrand () >> 24)) & (filter->planes - 1)];
180 /* Copy the pixel from the random buffer to dest */
181 dest[area] = (rand ? ((guint32 *) GST_BUFFER_DATA (rand))[area] : 0);
184 filter->current_plane--;
185 if (filter->current_plane < 0)
186 filter->current_plane = filter->planes - 1;
191 static GstStateChangeReturn
192 gst_quarktv_change_state (GstElement * element, GstStateChange transition)
194 GstQuarkTV *filter = GST_QUARKTV (element);
195 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
197 switch (transition) {
198 case GST_STATE_CHANGE_READY_TO_PAUSED:
201 (GstBuffer **) g_malloc (filter->planes * sizeof (GstBuffer *));
202 memset (filter->planetable, 0, filter->planes * sizeof (GstBuffer *));
209 if (GST_ELEMENT_CLASS (parent_class)->change_state)
210 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
212 switch (transition) {
213 case GST_STATE_CHANGE_PAUSED_TO_READY:
217 for (i = 0; i < filter->planes; i++) {
218 if (filter->planetable[i])
219 gst_buffer_unref (filter->planetable[i]);
220 filter->planetable[i] = NULL;
222 g_free (filter->planetable);
223 filter->planetable = NULL;
235 gst_quarktv_set_property (GObject * object, guint prop_id, const GValue * value,
240 g_return_if_fail (GST_IS_QUARKTV (object));
242 filter = GST_QUARKTV (object);
247 gint new_n_planes = g_value_get_int (value);
248 GstBuffer **new_planetable;
251 /* If the number of planes changed, copy across any existing planes */
252 if (new_n_planes != filter->planes) {
254 (GstBuffer **) g_malloc (new_n_planes * sizeof (GstBuffer *));
256 for (i = 0; (i < new_n_planes) && (i < filter->planes); i++) {
257 new_planetable[i] = filter->planetable[i];
259 for (; i < filter->planes; i++) {
260 if (filter->planetable[i])
261 gst_buffer_unref (filter->planetable[i]);
263 g_free (filter->planetable);
264 filter->planetable = new_planetable;
265 filter->current_plane = filter->planes - 1;
266 filter->planes = new_n_planes;
271 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
277 gst_quarktv_get_property (GObject * object, guint prop_id, GValue * value,
282 g_return_if_fail (GST_IS_QUARKTV (object));
284 filter = GST_QUARKTV (object);
288 g_value_set_int (value, filter->planes);
291 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
297 gst_quarktv_base_init (gpointer g_class)
299 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
301 gst_element_class_set_details (element_class, &quarktv_details);
303 gst_element_class_add_pad_template (element_class,
304 gst_static_pad_template_get (&gst_quarktv_sink_template));
305 gst_element_class_add_pad_template (element_class,
306 gst_static_pad_template_get (&gst_quarktv_src_template));
310 gst_quarktv_class_init (gpointer klass, gpointer class_data)
312 GObjectClass *gobject_class;
313 GstElementClass *element_class;
314 GstBaseTransformClass *trans_class;
316 gobject_class = (GObjectClass *) klass;
317 element_class = (GstElementClass *) klass;
318 trans_class = (GstBaseTransformClass *) klass;
320 parent_class = g_type_class_peek_parent (klass);
322 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_quarktv_set_property);
323 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_quarktv_get_property);
325 element_class->change_state = GST_DEBUG_FUNCPTR (gst_quarktv_change_state);
327 trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_quarktv_set_caps);
328 trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_quarktv_get_unit_size);
329 trans_class->transform = GST_DEBUG_FUNCPTR (gst_quarktv_transform);
333 gst_quarktv_init (GTypeInstance * instance, gpointer g_class)
335 GstQuarkTV *filter = GST_QUARKTV (instance);
337 filter->planes = PLANES;
338 filter->current_plane = filter->planes - 1;
342 gst_quarktv_get_type (void)
344 static GType quarktv_type = 0;
347 static const GTypeInfo quarktv_info = {
348 sizeof (GstQuarkTVClass),
349 gst_quarktv_base_init,
351 gst_quarktv_class_init,
359 quarktv_type = g_type_register_static (GST_TYPE_VIDEOFILTER,
360 "GstQuarkTV", &quarktv_info, 0);