recommmit to get the make_filter tag correct
[platform/upstream/gst-plugins-good.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   /* FILL ME */
37   LAST_SIGNAL
38 };
39
40 enum {
41   ARG_0,
42   ARG_METHOD,
43   /* FILL ME */
44 };
45
46 static void     gst_videoflip_base_init (gpointer g_class);
47 static void     gst_videoflip_class_init        (gpointer g_class, gpointer class_data);
48 static void     gst_videoflip_init              (GTypeInstance *instance, gpointer g_class);
49
50 static void     gst_videoflip_set_property              (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
51 static void     gst_videoflip_get_property              (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
52
53 static void gst_videoflip_planar411(GstVideofilter *videofilter, void *dest, void *src);
54 static void gst_videoflip_setup(GstVideofilter *videofilter);
55
56 #define GST_TYPE_VIDEOFLIP_METHOD (gst_videoflip_method_get_type())
57
58 static GType
59 gst_videoflip_method_get_type(void)
60 {
61   static GType videoflip_method_type = 0;
62   static GEnumValue videoflip_methods[] = {
63     { GST_VIDEOFLIP_METHOD_IDENTITY,   "0", "Identity (no rotation)" },
64     { GST_VIDEOFLIP_METHOD_90R,                "1", "Rotate clockwise 90 degrees" },
65     { GST_VIDEOFLIP_METHOD_180,                "2", "Rotate 180 degrees" },
66     { GST_VIDEOFLIP_METHOD_90L,                "3", "Rotate counter-clockwise 90 degrees" },
67     { GST_VIDEOFLIP_METHOD_HORIZ,      "4", "Flip horizontally" },
68     { GST_VIDEOFLIP_METHOD_VERT,       "5", "Flip vertically" },
69     { GST_VIDEOFLIP_METHOD_TRANS,      "6", "Flip across upper left/lower right diagonal" },
70     { GST_VIDEOFLIP_METHOD_OTHER,      "7", "Flip across upper right/lower left diagonal" },
71     { 0, NULL, NULL },
72   };
73   if(!videoflip_method_type){
74     videoflip_method_type = g_enum_register_static("GstVideoflipMethod",
75        videoflip_methods);
76   }
77   return videoflip_method_type;
78 }
79
80 GType
81 gst_videoflip_get_type (void)
82 {
83   static GType videoflip_type = 0;
84
85   if (!videoflip_type) {
86     static const GTypeInfo videoflip_info = {
87       sizeof(GstVideoflipClass),
88       gst_videoflip_base_init,
89       NULL,
90       gst_videoflip_class_init,
91       NULL,
92       NULL,
93       sizeof(GstVideoflip),
94       0,
95       gst_videoflip_init,
96     };
97     videoflip_type = g_type_register_static(GST_TYPE_VIDEOFILTER,
98         "GstVideoflip", &videoflip_info, 0);
99   }
100   return videoflip_type;
101 }
102
103 static GstVideofilterFormat gst_videoflip_formats[] = {
104   /* planar */
105   { "YV12", 12, gst_videoflip_planar411, },
106   { "I420", 12, gst_videoflip_planar411, },
107   { "IYUV", 12, gst_videoflip_planar411, },
108 };
109
110 static void
111 gst_videoflip_base_init (gpointer g_class)
112 {
113   static GstElementDetails videoflip_details = GST_ELEMENT_DETAILS (
114     "Video Flipper",
115     "Filter/Video",
116     "Flips and rotates video",
117     "David Schleef <ds@schleef.org>"
118   );
119   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
120   GstVideofilterClass *videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
121   int i;
122   
123   gst_element_class_set_details (element_class, &videoflip_details);
124
125   for(i=0;i<G_N_ELEMENTS(gst_videoflip_formats);i++){
126     gst_videofilter_class_add_format(videofilter_class,
127         gst_videoflip_formats + i);
128   }
129
130   gst_videofilter_class_add_pad_templates (GST_VIDEOFILTER_CLASS (g_class));
131 }
132
133 static void
134 gst_videoflip_class_init (gpointer g_class, gpointer class_data)
135 {
136   GObjectClass *gobject_class;
137   GstVideofilterClass *videofilter_class;
138
139   gobject_class = G_OBJECT_CLASS (g_class);
140   videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
141
142   g_object_class_install_property(gobject_class, ARG_METHOD,
143       g_param_spec_enum("method","method","method",
144       GST_TYPE_VIDEOFLIP_METHOD, GST_VIDEOFLIP_METHOD_90R,
145       G_PARAM_READWRITE));
146
147   gobject_class->set_property = gst_videoflip_set_property;
148   gobject_class->get_property = gst_videoflip_get_property;
149
150   videofilter_class->setup = gst_videoflip_setup;
151 }
152
153 static void
154 gst_videoflip_init (GTypeInstance *instance, gpointer g_class)
155 {
156   GstVideoflip *videoflip = GST_VIDEOFLIP (instance);
157   GstVideofilter *videofilter;
158
159   GST_DEBUG("gst_videoflip_init");
160
161   videofilter = GST_VIDEOFILTER(videoflip);
162
163   /* do stuff */
164 }
165
166 static void
167 gst_videoflip_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
168 {
169   GstVideoflip *src;
170
171   /* it's not null if we got it, but it might not be ours */
172   g_return_if_fail(GST_IS_VIDEOFLIP(object));
173   src = GST_VIDEOFLIP(object);
174
175   GST_DEBUG("gst_videoflip_set_property");
176   switch (prop_id) {
177     case ARG_METHOD:
178       src->method = g_value_get_enum (value);
179       /* FIXME is this ok? (threading issues) */
180       gst_videoflip_setup(GST_VIDEOFILTER(src));
181       break;
182     default:
183       break;
184   }
185 }
186
187 static void
188 gst_videoflip_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
189 {
190   GstVideoflip *src;
191
192   /* it's not null if we got it, but it might not be ours */
193   g_return_if_fail(GST_IS_VIDEOFLIP(object));
194   src = GST_VIDEOFLIP(object);
195
196   switch (prop_id) {
197     case ARG_METHOD:
198       g_value_set_enum (value, src->method);
199       break;
200     default:
201       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
202       break;
203   }
204 }
205
206 static gboolean plugin_init (GstPlugin *plugin)
207 {
208   if(!gst_library_load("gstvideofilter"))
209     return FALSE;
210
211   return gst_element_register (plugin, "videoflip", GST_RANK_NONE,
212       GST_TYPE_VIDEOFLIP);
213 }
214
215 GST_PLUGIN_DEFINE (
216   GST_VERSION_MAJOR,
217   GST_VERSION_MINOR,
218   "videoflip",
219   "Flips and rotates video",
220   plugin_init,
221   VERSION,
222   GST_LICENSE,
223   GST_COPYRIGHT,
224   GST_PACKAGE,
225   GST_ORIGIN
226 )
227
228 static void gst_videoflip_flip(GstVideoflip *videoflip, unsigned char *dest,
229     unsigned char *src, int sw, int sh, int dw, int dh);
230
231
232 static void gst_videoflip_setup (GstVideofilter *videofilter)
233 {
234   int from_width, from_height;
235   GstVideoflip *videoflip;
236
237   GST_DEBUG("gst_videoflip_setup");
238
239   videoflip = GST_VIDEOFLIP(videofilter);
240
241   from_width = gst_videofilter_get_input_width(videofilter);
242   from_height = gst_videofilter_get_input_height(videofilter);
243
244   if(from_width==0 || from_height==0){
245     return;
246   }
247
248   switch(videoflip->method){
249     case GST_VIDEOFLIP_METHOD_90R:
250     case GST_VIDEOFLIP_METHOD_90L:
251     case GST_VIDEOFLIP_METHOD_TRANS:
252     case GST_VIDEOFLIP_METHOD_OTHER:
253       gst_videofilter_set_output_size(videofilter, from_height, from_width);
254       break;
255     case GST_VIDEOFLIP_METHOD_IDENTITY:
256     case GST_VIDEOFLIP_METHOD_180:
257     case GST_VIDEOFLIP_METHOD_HORIZ:
258     case GST_VIDEOFLIP_METHOD_VERT:
259       gst_videofilter_set_output_size(videofilter, from_width, from_height);
260       break;
261     default:
262       g_assert_not_reached();
263       break;
264   }
265
266   GST_DEBUG ("format=%p \"%s\" from %dx%d to %dx%d",
267                videofilter->format, videofilter->format->fourcc,
268                from_width, from_height,
269                videofilter->to_width, videofilter->to_height);
270
271   if(videoflip->method == GST_VIDEOFLIP_METHOD_IDENTITY){
272     GST_DEBUG ("videoflip: using passthru");
273     videofilter->passthru = TRUE;
274   }else{
275     videofilter->passthru = FALSE;
276   }
277
278   videofilter->from_buf_size = (videofilter->from_width * videofilter->from_height
279                  * videofilter->format->depth) / 8;
280   videofilter->to_buf_size = (videofilter->to_width * videofilter->to_height
281                  * videofilter->format->depth) / 8;
282
283   videofilter->inited = TRUE;
284 }
285
286 static void gst_videoflip_planar411(GstVideofilter *videofilter,
287     void *dest, void *src)
288 {
289   GstVideoflip *videoflip;
290   int sw;
291   int sh;
292   int dw;
293   int dh;
294
295   g_return_if_fail(GST_IS_VIDEOFLIP(videofilter));
296   videoflip = GST_VIDEOFLIP(videofilter);
297
298   sw = videofilter->from_width;
299   sh = videofilter->from_height;
300   dw = videofilter->to_width;
301   dh = videofilter->to_height;
302
303   GST_DEBUG ("videoflip: scaling planar 4:1:1 %dx%d to %dx%d", sw, sh, dw, dh);
304
305   gst_videoflip_flip(videoflip, dest, src, sw, sh, dw, dh);
306
307   src += sw*sh;
308   dest += dw*dh;
309
310   dh = dh>>1;
311   dw = dw>>1;
312   sh = sh>>1;
313   sw = sw>>1;
314
315   gst_videoflip_flip(videoflip, dest, src, sw, sh, dw, dh);
316
317   src += sw*sh;
318   dest += dw*dh;
319
320   gst_videoflip_flip(videoflip, dest, src, sw, sh, dw, dh);
321 }
322
323 static void
324 gst_videoflip_flip(GstVideoflip *videoflip, unsigned char *dest,
325     unsigned char *src, int sw, int sh, int dw, int dh)
326 {
327   int x,y;
328
329   switch(videoflip->method){
330     case GST_VIDEOFLIP_METHOD_90R:
331       for(y=0;y<dh;y++){
332         for(x=0;x<dw;x++){
333          dest[y*dw + x] = src[(sh - 1 - x)*sw + y];
334        }
335       }
336       break;
337     case GST_VIDEOFLIP_METHOD_90L:
338       for(y=0;y<dh;y++){
339         for(x=0;x<dw;x++){
340          dest[y*dw + x] = src[x*sw + (sw - 1 - y)];
341        }
342       }
343       break;
344     case GST_VIDEOFLIP_METHOD_180:
345       for(y=0;y<dh;y++){
346         for(x=0;x<dw;x++){
347          dest[y*dw + x] = src[(sh - 1 - y)*sw + (sw - 1 - x)];
348        }
349       }
350       break;
351     case GST_VIDEOFLIP_METHOD_HORIZ:
352       for(y=0;y<dh;y++){
353         for(x=0;x<dw;x++){
354          dest[y*dw + x] = src[y*sw + (sw - 1 - x)];
355        }
356       }
357       break;
358     case GST_VIDEOFLIP_METHOD_VERT:
359       for(y=0;y<dh;y++){
360         for(x=0;x<dw;x++){
361          dest[y*dw + x] = src[(sh - 1 - y)*sw + x];
362        }
363       }
364       break;
365     case GST_VIDEOFLIP_METHOD_TRANS:
366       for(y=0;y<dh;y++){
367         for(x=0;x<dw;x++){
368          dest[y*dw + x] = src[x*sw + y];
369        }
370       }
371       break;
372     case GST_VIDEOFLIP_METHOD_OTHER:
373       for(y=0;y<dh;y++){
374         for(x=0;x<dw;x++){
375          dest[y*dw + x] = src[(sh - 1 - x)*sw + (sw - 1 - y)];
376        }
377       }
378       break;
379     default:
380       /* FIXME */
381       break;
382   }
383 }
384
385