first batch : remove ',' at end of enums as they could confuse older gcc, foreign...
[platform/upstream/gstreamer.git] / gst / videofilter / gstvideoflip.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David Schleef <ds@schleef.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * This file was (probably) generated from gstvideoflip.c,
23  * gstvideoflip.c,v 1.7 2003/11/08 02:48:59 dschleef Exp 
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 /*#define DEBUG_ENABLED */
31 #include <gstvideoflip.h>
32 #include <string.h>
33
34 /* GstVideoflip signals and args */
35 enum
36 {
37   /* FILL ME */
38   LAST_SIGNAL
39 };
40
41 enum
42 {
43   ARG_0,
44   ARG_METHOD
45       /* FILL ME */
46 };
47
48 static void gst_videoflip_base_init (gpointer g_class);
49 static void gst_videoflip_class_init (gpointer g_class, gpointer class_data);
50 static void gst_videoflip_init (GTypeInstance * instance, gpointer g_class);
51
52 static void gst_videoflip_set_property (GObject * object, guint prop_id,
53     const GValue * value, GParamSpec * pspec);
54 static void gst_videoflip_get_property (GObject * object, guint prop_id,
55     GValue * value, GParamSpec * pspec);
56
57 static void gst_videoflip_planar411 (GstVideofilter * videofilter, void *dest,
58     void *src);
59 static void gst_videoflip_setup (GstVideofilter * videofilter);
60
61 #define GST_TYPE_VIDEOFLIP_METHOD (gst_videoflip_method_get_type())
62
63 static GType
64 gst_videoflip_method_get_type (void)
65 {
66   static GType videoflip_method_type = 0;
67   static GEnumValue videoflip_methods[] = {
68     {GST_VIDEOFLIP_METHOD_IDENTITY, "0", "Identity (no rotation)"},
69     {GST_VIDEOFLIP_METHOD_90R, "1", "Rotate clockwise 90 degrees"},
70     {GST_VIDEOFLIP_METHOD_180, "2", "Rotate 180 degrees"},
71     {GST_VIDEOFLIP_METHOD_90L, "3", "Rotate counter-clockwise 90 degrees"},
72     {GST_VIDEOFLIP_METHOD_HORIZ, "4", "Flip horizontally"},
73     {GST_VIDEOFLIP_METHOD_VERT, "5", "Flip vertically"},
74     {GST_VIDEOFLIP_METHOD_TRANS, "6",
75         "Flip across upper left/lower right diagonal"},
76     {GST_VIDEOFLIP_METHOD_OTHER, "7",
77         "Flip across upper right/lower left diagonal"},
78     {0, NULL, NULL},
79   };
80
81   if (!videoflip_method_type) {
82     videoflip_method_type = g_enum_register_static ("GstVideoflipMethod",
83         videoflip_methods);
84   }
85   return videoflip_method_type;
86 }
87
88 GType
89 gst_videoflip_get_type (void)
90 {
91   static GType videoflip_type = 0;
92
93   if (!videoflip_type) {
94     static const GTypeInfo videoflip_info = {
95       sizeof (GstVideoflipClass),
96       gst_videoflip_base_init,
97       NULL,
98       gst_videoflip_class_init,
99       NULL,
100       NULL,
101       sizeof (GstVideoflip),
102       0,
103       gst_videoflip_init,
104     };
105
106     videoflip_type = g_type_register_static (GST_TYPE_VIDEOFILTER,
107         "GstVideoflip", &videoflip_info, 0);
108   }
109   return videoflip_type;
110 }
111
112 static GstVideofilterFormat gst_videoflip_formats[] = {
113   /* planar */
114   {"YV12", 12, gst_videoflip_planar411,},
115   {"I420", 12, gst_videoflip_planar411,},
116   {"IYUV", 12, gst_videoflip_planar411,},
117 };
118
119 static void
120 gst_videoflip_base_init (gpointer g_class)
121 {
122   static GstElementDetails videoflip_details =
123       GST_ELEMENT_DETAILS ("Video Flipper",
124       "Filter/Effect/Video",
125       "Flips and rotates video",
126       "David Schleef <ds@schleef.org>");
127   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
128   GstVideofilterClass *videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
129   int i;
130
131   gst_element_class_set_details (element_class, &videoflip_details);
132
133   for (i = 0; i < G_N_ELEMENTS (gst_videoflip_formats); i++) {
134     gst_videofilter_class_add_format (videofilter_class,
135         gst_videoflip_formats + i);
136   }
137
138   gst_videofilter_class_add_pad_templates (GST_VIDEOFILTER_CLASS (g_class));
139 }
140
141 static void
142 gst_videoflip_class_init (gpointer g_class, gpointer class_data)
143 {
144   GObjectClass *gobject_class;
145   GstVideofilterClass *videofilter_class;
146
147   gobject_class = G_OBJECT_CLASS (g_class);
148   videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
149
150   g_object_class_install_property (gobject_class, ARG_METHOD,
151       g_param_spec_enum ("method", "method", "method",
152           GST_TYPE_VIDEOFLIP_METHOD, GST_VIDEOFLIP_METHOD_90R,
153           G_PARAM_READWRITE));
154
155   gobject_class->set_property = gst_videoflip_set_property;
156   gobject_class->get_property = gst_videoflip_get_property;
157
158   videofilter_class->setup = gst_videoflip_setup;
159 }
160
161 static void
162 gst_videoflip_init (GTypeInstance * instance, gpointer g_class)
163 {
164   GstVideoflip *videoflip = GST_VIDEOFLIP (instance);
165   GstVideofilter *videofilter;
166
167   GST_DEBUG ("gst_videoflip_init");
168
169   videofilter = GST_VIDEOFILTER (videoflip);
170
171   /* do stuff */
172 }
173
174 static void
175 gst_videoflip_set_property (GObject * object, guint prop_id,
176     const GValue * value, GParamSpec * pspec)
177 {
178   GstVideoflip *src;
179
180   /* it's not null if we got it, but it might not be ours */
181   g_return_if_fail (GST_IS_VIDEOFLIP (object));
182   src = GST_VIDEOFLIP (object);
183
184   GST_DEBUG ("gst_videoflip_set_property");
185   switch (prop_id) {
186     case ARG_METHOD:
187       src->method = g_value_get_enum (value);
188       /* FIXME is this ok? (threading issues) */
189       gst_videoflip_setup (GST_VIDEOFILTER (src));
190       break;
191     default:
192       break;
193   }
194 }
195
196 static void
197 gst_videoflip_get_property (GObject * object, guint prop_id, GValue * value,
198     GParamSpec * pspec)
199 {
200   GstVideoflip *src;
201
202   /* it's not null if we got it, but it might not be ours */
203   g_return_if_fail (GST_IS_VIDEOFLIP (object));
204   src = GST_VIDEOFLIP (object);
205
206   switch (prop_id) {
207     case ARG_METHOD:
208       g_value_set_enum (value, src->method);
209       break;
210     default:
211       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
212       break;
213   }
214 }
215
216 static gboolean
217 plugin_init (GstPlugin * plugin)
218 {
219   if (!gst_library_load ("gstvideofilter"))
220     return FALSE;
221
222   return gst_element_register (plugin, "videoflip", GST_RANK_NONE,
223       GST_TYPE_VIDEOFLIP);
224 }
225
226 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
227     GST_VERSION_MINOR,
228     "videoflip",
229     "Flips and rotates video",
230     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
231
232      static void gst_videoflip_flip (GstVideoflip * videoflip,
233     unsigned char *dest, unsigned char *src, int sw, int sh, int dw, int dh);
234
235
236      static void gst_videoflip_setup (GstVideofilter * videofilter)
237 {
238   int from_width, from_height;
239   GstVideoflip *videoflip;
240
241   GST_DEBUG ("gst_videoflip_setup");
242
243   videoflip = GST_VIDEOFLIP (videofilter);
244
245   from_width = gst_videofilter_get_input_width (videofilter);
246   from_height = gst_videofilter_get_input_height (videofilter);
247
248   if (from_width == 0 || from_height == 0) {
249     return;
250   }
251
252   switch (videoflip->method) {
253     case GST_VIDEOFLIP_METHOD_90R:
254     case GST_VIDEOFLIP_METHOD_90L:
255     case GST_VIDEOFLIP_METHOD_TRANS:
256     case GST_VIDEOFLIP_METHOD_OTHER:
257       gst_videofilter_set_output_size (videofilter, from_height, from_width);
258       break;
259     case GST_VIDEOFLIP_METHOD_IDENTITY:
260     case GST_VIDEOFLIP_METHOD_180:
261     case GST_VIDEOFLIP_METHOD_HORIZ:
262     case GST_VIDEOFLIP_METHOD_VERT:
263       gst_videofilter_set_output_size (videofilter, from_width, from_height);
264       break;
265     default:
266       g_assert_not_reached ();
267       break;
268   }
269
270   GST_DEBUG ("format=%p \"%s\" from %dx%d to %dx%d",
271       videofilter->format, videofilter->format->fourcc,
272       from_width, from_height, videofilter->to_width, videofilter->to_height);
273
274   if (videoflip->method == GST_VIDEOFLIP_METHOD_IDENTITY) {
275     GST_DEBUG ("videoflip: using passthru");
276     videofilter->passthru = TRUE;
277   } else {
278     videofilter->passthru = FALSE;
279   }
280
281   videofilter->from_buf_size =
282       (videofilter->from_width * videofilter->from_height *
283       videofilter->format->depth) / 8;
284   videofilter->to_buf_size =
285       (videofilter->to_width * videofilter->to_height *
286       videofilter->format->depth) / 8;
287
288   videofilter->inited = TRUE;
289 }
290
291 static void
292 gst_videoflip_planar411 (GstVideofilter * videofilter, void *dest, void *src)
293 {
294   GstVideoflip *videoflip;
295   int sw;
296   int sh;
297   int dw;
298   int dh;
299
300   g_return_if_fail (GST_IS_VIDEOFLIP (videofilter));
301   videoflip = GST_VIDEOFLIP (videofilter);
302
303   sw = videofilter->from_width;
304   sh = videofilter->from_height;
305   dw = videofilter->to_width;
306   dh = videofilter->to_height;
307
308   GST_DEBUG ("videoflip: scaling planar 4:1:1 %dx%d to %dx%d", sw, sh, dw, dh);
309
310   gst_videoflip_flip (videoflip, dest, src, sw, sh, dw, dh);
311
312   src += sw * sh;
313   dest += dw * dh;
314
315   dh = dh >> 1;
316   dw = dw >> 1;
317   sh = sh >> 1;
318   sw = sw >> 1;
319
320   gst_videoflip_flip (videoflip, dest, src, sw, sh, dw, dh);
321
322   src += sw * sh;
323   dest += dw * dh;
324
325   gst_videoflip_flip (videoflip, dest, src, sw, sh, dw, dh);
326 }
327
328 static void
329 gst_videoflip_flip (GstVideoflip * videoflip, unsigned char *dest,
330     unsigned char *src, int sw, int sh, int dw, int dh)
331 {
332   int x, y;
333
334   switch (videoflip->method) {
335     case GST_VIDEOFLIP_METHOD_90R:
336       for (y = 0; y < dh; y++) {
337         for (x = 0; x < dw; x++) {
338           dest[y * dw + x] = src[(sh - 1 - x) * sw + y];
339         }
340       }
341       break;
342     case GST_VIDEOFLIP_METHOD_90L:
343       for (y = 0; y < dh; y++) {
344         for (x = 0; x < dw; x++) {
345           dest[y * dw + x] = src[x * sw + (sw - 1 - y)];
346         }
347       }
348       break;
349     case GST_VIDEOFLIP_METHOD_180:
350       for (y = 0; y < dh; y++) {
351         for (x = 0; x < dw; x++) {
352           dest[y * dw + x] = src[(sh - 1 - y) * sw + (sw - 1 - x)];
353         }
354       }
355       break;
356     case GST_VIDEOFLIP_METHOD_HORIZ:
357       for (y = 0; y < dh; y++) {
358         for (x = 0; x < dw; x++) {
359           dest[y * dw + x] = src[y * sw + (sw - 1 - x)];
360         }
361       }
362       break;
363     case GST_VIDEOFLIP_METHOD_VERT:
364       for (y = 0; y < dh; y++) {
365         for (x = 0; x < dw; x++) {
366           dest[y * dw + x] = src[(sh - 1 - y) * sw + x];
367         }
368       }
369       break;
370     case GST_VIDEOFLIP_METHOD_TRANS:
371       for (y = 0; y < dh; y++) {
372         for (x = 0; x < dw; x++) {
373           dest[y * dw + x] = src[x * sw + y];
374         }
375       }
376       break;
377     case GST_VIDEOFLIP_METHOD_OTHER:
378       for (y = 0; y < dh; y++) {
379         for (x = 0; x < dw; x++) {
380           dest[y * dw + x] = src[(sh - 1 - x) * sw + (sw - 1 - y)];
381         }
382       }
383       break;
384     default:
385       /* FIXME */
386       break;
387   }
388 }