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 <gst/video/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 void gst_quarktv_planetable_clear (GstQuarkTV * filter);
79 static GstElementDetails quarktv_details =
80 GST_ELEMENT_DETAILS ("QuarkTV effect",
81 "Filter/Effect/Video",
83 "FUKUCHI, Kentarou <fukuchi@users.sourceforge.net>");
85 static GstStaticPadTemplate gst_quarktv_src_template =
86 GST_STATIC_PAD_TEMPLATE ("src",
89 GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx "; " GST_VIDEO_CAPS_RGBx)
92 static GstStaticPadTemplate gst_quarktv_sink_template =
93 GST_STATIC_PAD_TEMPLATE ("sink",
96 GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx "; " GST_VIDEO_CAPS_RGBx)
99 static GstVideoFilterClass *parent_class = NULL;
102 gst_quarktv_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
105 GstQuarkTV *filter = GST_QUARKTV (btrans);
106 GstStructure *structure;
107 gboolean ret = FALSE;
109 structure = gst_caps_get_structure (incaps, 0);
111 if (gst_structure_get_int (structure, "width", &filter->width) &&
112 gst_structure_get_int (structure, "height", &filter->height)) {
113 gst_quarktv_planetable_clear (filter);
114 filter->area = filter->width * filter->height;
122 gst_quarktv_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
126 GstStructure *structure;
127 gboolean ret = FALSE;
130 filter = GST_QUARKTV (btrans);
132 structure = gst_caps_get_structure (caps, 0);
134 if (gst_structure_get_int (structure, "width", &width) &&
135 gst_structure_get_int (structure, "height", &height)) {
136 *size = width * height * 32 / 8;
138 GST_DEBUG_OBJECT (filter, "our frame size is %d bytes (%dx%d)", *size,
145 static inline guint32
148 static unsigned int fastrand_val;
150 return (fastrand_val = fastrand_val * 1103515245 + 12345);
154 gst_quarktv_transform (GstBaseTransform * trans, GstBuffer * in,
160 GstFlowReturn ret = GST_FLOW_OK;
162 filter = GST_QUARKTV (trans);
164 gst_buffer_stamp (out, in);
167 src = (guint32 *) GST_BUFFER_DATA (in);
168 dest = (guint32 *) GST_BUFFER_DATA (out);
170 if (filter->planetable[filter->current_plane])
171 gst_buffer_unref (filter->planetable[filter->current_plane]);
173 filter->planetable[filter->current_plane] = gst_buffer_ref (in);
179 /* pick a random buffer */
181 filter->planetable[(filter->current_plane +
182 (fastrand () >> 24)) & (filter->planes - 1)];
184 /* Copy the pixel from the random buffer to dest */
185 dest[area] = (rand ? ((guint32 *) GST_BUFFER_DATA (rand))[area] : 0);
188 filter->current_plane--;
189 if (filter->current_plane < 0)
190 filter->current_plane = filter->planes - 1;
196 gst_quarktv_planetable_clear (GstQuarkTV * filter)
200 for (i = 0; i < filter->planes; i++) {
201 if (GST_IS_BUFFER (filter->planetable[i])) {
202 gst_buffer_unref (filter->planetable[i]);
204 filter->planetable[i] = NULL;
208 static GstStateChangeReturn
209 gst_quarktv_change_state (GstElement * element, GstStateChange transition)
211 GstQuarkTV *filter = GST_QUARKTV (element);
212 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
214 switch (transition) {
215 case GST_STATE_CHANGE_READY_TO_PAUSED:
218 (GstBuffer **) g_malloc0 (filter->planes * sizeof (GstBuffer *));
225 if (GST_ELEMENT_CLASS (parent_class)->change_state)
226 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
228 switch (transition) {
229 case GST_STATE_CHANGE_PAUSED_TO_READY:
231 gst_quarktv_planetable_clear (filter);
232 g_free (filter->planetable);
233 filter->planetable = NULL;
245 gst_quarktv_set_property (GObject * object, guint prop_id, const GValue * value,
250 g_return_if_fail (GST_IS_QUARKTV (object));
252 filter = GST_QUARKTV (object);
257 gint new_n_planes = g_value_get_int (value);
258 GstBuffer **new_planetable;
261 /* If the number of planes changed, copy across any existing planes */
262 if (new_n_planes != filter->planes) {
264 (GstBuffer **) g_malloc (new_n_planes * sizeof (GstBuffer *));
266 for (i = 0; (i < new_n_planes) && (i < filter->planes); i++) {
267 new_planetable[i] = filter->planetable[i];
269 for (; i < filter->planes; i++) {
270 if (filter->planetable[i])
271 gst_buffer_unref (filter->planetable[i]);
273 g_free (filter->planetable);
274 filter->planetable = new_planetable;
275 filter->current_plane = filter->planes - 1;
276 filter->planes = new_n_planes;
281 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
287 gst_quarktv_get_property (GObject * object, guint prop_id, GValue * value,
292 g_return_if_fail (GST_IS_QUARKTV (object));
294 filter = GST_QUARKTV (object);
298 g_value_set_int (value, filter->planes);
301 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
307 gst_quarktv_base_init (gpointer g_class)
309 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
311 gst_element_class_set_details (element_class, &quarktv_details);
313 gst_element_class_add_pad_template (element_class,
314 gst_static_pad_template_get (&gst_quarktv_sink_template));
315 gst_element_class_add_pad_template (element_class,
316 gst_static_pad_template_get (&gst_quarktv_src_template));
320 gst_quarktv_class_init (gpointer klass, gpointer class_data)
322 GObjectClass *gobject_class;
323 GstElementClass *element_class;
324 GstBaseTransformClass *trans_class;
326 gobject_class = (GObjectClass *) klass;
327 element_class = (GstElementClass *) klass;
328 trans_class = (GstBaseTransformClass *) klass;
330 parent_class = g_type_class_peek_parent (klass);
332 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_quarktv_set_property);
333 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_quarktv_get_property);
335 element_class->change_state = GST_DEBUG_FUNCPTR (gst_quarktv_change_state);
337 trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_quarktv_set_caps);
338 trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_quarktv_get_unit_size);
339 trans_class->transform = GST_DEBUG_FUNCPTR (gst_quarktv_transform);
343 gst_quarktv_init (GTypeInstance * instance, gpointer g_class)
345 GstQuarkTV *filter = GST_QUARKTV (instance);
347 filter->planes = PLANES;
348 filter->current_plane = filter->planes - 1;
352 gst_quarktv_get_type (void)
354 static GType quarktv_type = 0;
357 static const GTypeInfo quarktv_info = {
358 sizeof (GstQuarkTVClass),
359 gst_quarktv_base_init,
361 gst_quarktv_class_init,
369 quarktv_type = g_type_register_static (GST_TYPE_VIDEO_FILTER,
370 "GstQuarkTV", &quarktv_info, 0);