b6739f42b1b057c44ae6bdfaadddc8c2fc2fd3cd
[platform/upstream/gst-plugins-good.git] / gst / effectv / gstaging.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David Schleef <ds@schleef.org>
4  *
5  * EffecTV - Realtime Digital Video Effector
6  * Copyright (C) 2001 FUKUCHI Kentarou
7  *
8  * This library is free software; 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.
12  *
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.
17  *
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.
22  */
23
24 /*
25  * This file was (probably) generated from gstvideotemplate.c,
26  * gstvideotemplate.c,v 1.11 2004/01/07 08:56:45 ds Exp 
27  */
28
29 /* From main.c of warp-1.1:
30  *
31  *      Simple DirectMedia Layer demo
32  *      Realtime picture 'gooing'
33  *      by sam lantinga slouken@devolution.com
34  */
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <gst/gst.h>
41 #include <gstvideofilter.h>
42 #include <string.h>
43 #include <math.h>
44
45 #define GST_TYPE_AGINGTV \
46   (gst_agingtv_get_type())
47 #define GST_AGINGTV(obj) \
48   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AGINGTV,GstAgingTV))
49 #define GST_AGINGTV_CLASS(klass) \
50   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AGINGTV,GstAgingTVClass))
51 #define GST_IS_AGINGTV(obj) \
52   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AGINGTV))
53 #define GST_IS_AGINGTV_CLASS(obj) \
54   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AGINGTV))
55
56 #define SCRATCH_MAX 20
57 typedef struct _scratch
58 {
59   gint life;
60   gint x;
61   gint dx;
62   gint init;
63 } scratch;
64
65 static int dx[8] = { 1, 1, 0, -1, -1, -1,  0, 1};
66 static int dy[8] = { 0, -1, -1, -1, 0, 1, 1, 1};
67
68 typedef struct _GstAgingTV GstAgingTV;
69 typedef struct _GstAgingTVClass GstAgingTVClass;
70
71 struct _GstAgingTV {
72   GstVideofilter videofilter;
73
74   gint width, height;
75   gint aging_mode;
76
77   scratch scratches[SCRATCH_MAX];
78   gint scratch_lines;
79
80   gint dust_interval;
81   gint pits_interval;
82
83 };
84
85 struct _GstAgingTVClass {
86   GstVideofilterClass parent_class;
87 };
88
89 /* GstAgingTV signals and args */
90 enum {
91   /* FILL ME */
92   LAST_SIGNAL
93 };
94
95 enum {
96   ARG_0,
97   /* FILL ME */
98 };
99
100 static void     gst_agingtv_base_init   (gpointer g_class);
101 static void     gst_agingtv_class_init  (gpointer g_class, gpointer class_data);
102 static void     gst_agingtv_init        (GTypeInstance *instance, gpointer g_class);
103 static void     gst_agingtv_setup       (GstVideofilter *videofilter);
104
105 static void     gst_agingtv_set_property                (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
106 static void     gst_agingtv_get_property                (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
107 static void     gst_agingtv_rgb32       (GstVideofilter *videofilter, void *d, void *s);
108
109 GType
110 gst_agingtv_get_type (void)
111 {
112   static GType agingtv_type = 0;
113
114   if (!agingtv_type) {
115     static const GTypeInfo agingtv_info = {
116       sizeof(GstAgingTVClass),
117       gst_agingtv_base_init,
118       NULL,
119       gst_agingtv_class_init,
120       NULL,
121       NULL,
122       sizeof(GstAgingTV),
123       0,
124       gst_agingtv_init,
125     };
126     agingtv_type = g_type_register_static(GST_TYPE_VIDEOFILTER,
127         "GstAgingTV", &agingtv_info, 0);
128   }
129   return agingtv_type;
130 }
131
132 static GstVideofilterFormat gst_agingtv_formats[] = {
133   { "RGB ", 32, gst_agingtv_rgb32, 24, G_BIG_ENDIAN, 0x0000ff00, 0x00ff0000, 0xff000000 }
134 };
135   
136 static void
137 gst_agingtv_base_init (gpointer g_class)
138 {
139   static GstElementDetails agingtv_details = GST_ELEMENT_DETAILS (
140     "AgingTV",
141     "Filter/Effect/Video",
142     "AgingTV adds age to video input using scratches and dust",
143     "Sam Lantinga <slouken@devolution.com>"
144   );
145   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
146   GstVideofilterClass *videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
147   int i;
148   
149   gst_element_class_set_details (element_class, &agingtv_details);
150
151   for(i=0;i<G_N_ELEMENTS(gst_agingtv_formats);i++){
152     gst_videofilter_class_add_format(videofilter_class,
153         gst_agingtv_formats + i);
154   }
155
156   gst_videofilter_class_add_pad_templates (GST_VIDEOFILTER_CLASS (g_class));
157 }
158
159 static void
160 gst_agingtv_class_init (gpointer g_class, gpointer class_data)
161 {
162   GObjectClass *gobject_class;
163   GstVideofilterClass *videofilter_class;
164
165   gobject_class = G_OBJECT_CLASS (g_class);
166   videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
167
168 #if 0
169   g_object_class_install_property(gobject_class, ARG_METHOD,
170       g_param_spec_enum("method","method","method",
171       GST_TYPE_AGINGTV_METHOD, GST_AGINGTV_METHOD_1,
172       G_PARAM_READWRITE));
173 #endif
174
175   gobject_class->set_property = gst_agingtv_set_property;
176   gobject_class->get_property = gst_agingtv_get_property;
177
178   videofilter_class->setup = gst_agingtv_setup;
179 }
180
181 static void
182 gst_agingtv_init (GTypeInstance *instance, gpointer g_class)
183 {
184   GstAgingTV *agingtv = GST_AGINGTV (instance);
185   GstVideofilter *videofilter;
186
187   GST_DEBUG("gst_agingtv_init");
188
189   videofilter = GST_VIDEOFILTER(agingtv);
190
191   /* do stuff */
192 }
193
194 static void gst_agingtv_setup(GstVideofilter *videofilter)
195 {
196   GstAgingTV *agingtv;
197   int width = gst_videofilter_get_input_width(videofilter);
198   int height = gst_videofilter_get_input_height(videofilter);
199
200   g_return_if_fail(GST_IS_AGINGTV(videofilter));
201   agingtv = GST_AGINGTV(videofilter);
202
203   /* if any setup needs to be done, do it here */
204
205   agingtv->width = width;
206   agingtv->height = height;
207 }
208
209 static unsigned int 
210 fastrand (void)
211 {
212   static unsigned int fastrand_val;
213
214   return (fastrand_val = fastrand_val * 1103515245 + 12345);
215 }
216
217
218 static void 
219 coloraging (guint32 *src, guint32 *dest, gint video_area)
220 {
221   guint32 a, b;
222   gint i;
223
224   for (i = video_area; i; i--) {
225     a = *src++;
226     b = (a & 0xfcfcfc) >> 2;
227     *dest++ = a - b + 0x181818 + ((fastrand () >> 8) & 0x101010);
228   }
229 }
230
231
232 static void 
233 scratching (scratch *scratches, gint scratch_lines, guint32 *dest, gint width, gint height)
234 {
235   gint i, y, y1, y2;
236   guint32 *p, a, b;
237   scratch *scratch;
238
239   for (i = 0; i < scratch_lines; i++) {
240     scratch = &scratches[i];
241
242     if (scratch->life) {
243       scratch->x = scratch->x + scratch->dx;
244       
245       if (scratch->x < 0 || scratch->x > width * 256) {
246         scratch->life = 0;
247         break;
248       }
249       p = dest + (scratch->x >> 8);
250       if (scratch->init) {
251         y1 = scratch->init;
252         scratch->init = 0;
253       } else {
254         y1 = 0;
255       }
256       scratch->life--;
257       if (scratch->life) {
258         y2 = height;
259       } else {
260         y2 = fastrand () % height;
261       }
262       for (y = y1; y < y2; y++) {
263         a = *p & 0xfefeff;
264         a += 0x202020;
265         b = a & 0x1010100;
266         *p = a | (b - (b >> 8));
267         p += width;
268       }
269     } else {
270       if ((fastrand () & 0xf0000000) == 0) {
271         scratch->life = 2 + (fastrand () >> 27);
272         scratch->x = fastrand () % (width * 256);
273         scratch->dx = ((int) fastrand ()) >> 23;
274         scratch->init = (fastrand () % (height - 1)) + 1;
275       }
276     }
277   }
278 }
279
280 static void 
281 dusts (guint32 *dest, gint width, gint height, gint dust_interval, gint area_scale)
282 {
283   int i, j;
284   int dnum;
285   int d, len;
286   guint x, y;
287
288   if (dust_interval == 0) {
289     if ((fastrand () & 0xf0000000) == 0) {
290       dust_interval = fastrand () >> 29;
291     }
292     return;
293   }
294   dnum = area_scale * 4 + (fastrand() >> 27);
295   
296   for (i = 0; i < dnum; i++) {
297     x = fastrand () % width;
298     y = fastrand () % height;
299     d = fastrand () >> 29;
300     len = fastrand () % area_scale + 5;
301     for (j = 0; j < len; j++) {
302       dest[y * width + x] = 0x101010;
303       y += dy[d];
304       x += dx[d];
305
306       if (y >= height || x >= width) break;
307
308       d = (d + fastrand () % 3 - 1) & 7;
309     }
310   }
311   dust_interval--;
312 }
313
314 static void 
315 pits (guint32 *dest, gint width, gint height, gint area_scale, gint pits_interval)
316 {
317   int i, j;
318   int pnum, size, pnumscale;
319   guint x, y;
320
321   pnumscale = area_scale * 2;
322   if (pits_interval) {
323     pnum = pnumscale + (fastrand () % pnumscale);
324
325     pits_interval--;
326   } else {
327     pnum = fastrand () % pnumscale;
328
329     if ((fastrand () & 0xf8000000) == 0) {
330       pits_interval = (fastrand () >> 28) + 20;
331     }
332   }
333   for (i = 0; i < pnum; i++) {
334     x = fastrand () % (width - 1);
335     y = fastrand () % (height - 1);
336
337     size = fastrand () >> 28;
338
339     for (j = 0; j < size; j++) {
340       x = x + fastrand () % 3 - 1;
341       y = y + fastrand () % 3 - 1;
342
343       if (y >= height || x >= width) break;
344
345       dest[y * width + x] = 0xc0c0c0;
346     }
347   }
348 }
349
350 static void     
351 gst_agingtv_rgb32 (GstVideofilter *videofilter, void *d, void *s)
352 {
353   GstAgingTV *agingtv;
354   int width = gst_videofilter_get_input_width(videofilter);
355   int height = gst_videofilter_get_input_height(videofilter);
356   int video_size = width * height;
357   guint32 *src = s;
358   guint32 *dest = d;
359   gint area_scale = width * height / 64 / 480;
360   if (area_scale <= 0) area_scale = 1;
361
362   g_return_if_fail(GST_IS_AGINGTV(videofilter));
363   agingtv = GST_AGINGTV(videofilter);
364
365   coloraging (src, dest, video_size);
366   scratching (agingtv->scratches, agingtv->scratch_lines, dest, width, height);
367   pits (dest, width, height, area_scale, agingtv->pits_interval);
368   if(area_scale > 1)
369     dusts (dest, width, height, agingtv->dust_interval, area_scale);
370   
371 }
372
373 static void
374 gst_agingtv_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
375 {
376   GstAgingTV *src;
377
378   /* it's not null if we got it, but it might not be ours */
379   g_return_if_fail(GST_IS_AGINGTV(object));
380   src = GST_AGINGTV(object);
381
382   GST_DEBUG("gst_agingtv_set_property");
383   switch (prop_id) {
384 #if 0
385     case ARG_METHOD:
386       src->method = g_value_get_enum (value);
387       break;
388 #endif
389     default:
390       break;
391   }
392 }
393
394 static void
395 gst_agingtv_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
396 {
397   GstAgingTV *src;
398
399   /* it's not null if we got it, but it might not be ours */
400   g_return_if_fail(GST_IS_AGINGTV(object));
401   src = GST_AGINGTV(object);
402
403   switch (prop_id) {
404 #if 0
405     case ARG_METHOD:
406       g_value_set_enum (value, src->method);
407       break;
408 #endif
409     default:
410       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
411       break;
412   }
413 }
414