gst-indent
[platform/upstream/gst-plugins-good.git] / gst / videoflip / videoflip.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #define DEBUG_ENABLED
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <gst/gst.h>
26 #include <stdlib.h>
27 #include <math.h>
28 #include <videoflip.h>
29 #include <string.h>
30
31 #include "gstvideoflip.h"
32
33 static void gst_videoflip_planar411 (GstVideoflip * scale, unsigned char *dest,
34     unsigned char *src);
35
36 static void gst_videoflip_flip (GstVideoflip * videoflip, unsigned char *dest,
37     unsigned char *src, int sw, int sh, int dw, int dh);
38
39 struct videoflip_format_struct videoflip_formats[] = {
40   /* planar */
41   {"YV12", 12, gst_videoflip_planar411,},
42   {"I420", 12, gst_videoflip_planar411,},
43 };
44
45 int videoflip_n_formats =
46     sizeof (videoflip_formats) / sizeof (videoflip_formats[0]);
47
48 GstStructure *
49 videoflip_get_cap (struct videoflip_format_struct *format)
50 {
51   unsigned int fourcc;
52   GstStructure *structure;
53
54   if (format->scale == NULL)
55     return NULL;
56
57   fourcc =
58       GST_MAKE_FOURCC (format->fourcc[0], format->fourcc[1], format->fourcc[2],
59       format->fourcc[3]);
60
61   if (format->bpp) {
62     structure = gst_structure_new ("video/x-raw-rgb",
63         "depth", G_TYPE_INT, format->bpp,
64         "bpp", G_TYPE_INT, format->depth,
65         "endianness", G_TYPE_INT, format->endianness,
66         "red_mask", G_TYPE_INT, format->red_mask,
67         "green_mask", G_TYPE_INT, format->green_mask,
68         "blue_mask", G_TYPE_INT, format->blue_mask, NULL);
69   } else {
70     structure = gst_structure_new ("video/x-raw-yuv",
71         "format", GST_TYPE_FOURCC, fourcc, NULL);
72   }
73
74   return structure;
75 }
76
77 struct videoflip_format_struct *
78 videoflip_find_by_caps (const GstCaps * caps)
79 {
80   int i;
81
82   GST_DEBUG ("finding %p", caps);
83
84   g_return_val_if_fail (caps != NULL, NULL);
85
86   for (i = 0; i < videoflip_n_formats; i++) {
87     GstCaps *c;
88
89     c = gst_caps_new_full (videoflip_get_cap (videoflip_formats + i), NULL);
90     if (c) {
91       if (gst_caps_is_always_compatible (caps, c)) {
92         gst_caps_free (c);
93         return videoflip_formats + i;
94       }
95       gst_caps_free (c);
96     }
97   }
98
99   return NULL;
100 }
101
102 void
103 gst_videoflip_setup (GstVideoflip * videoflip)
104 {
105   if (videoflip->from_width == 0 || videoflip->from_height == 0) {
106     return;
107   }
108
109   switch (videoflip->method) {
110     case GST_VIDEOFLIP_METHOD_90R:
111     case GST_VIDEOFLIP_METHOD_90L:
112     case GST_VIDEOFLIP_METHOD_TRANS:
113     case GST_VIDEOFLIP_METHOD_OTHER:
114       videoflip->to_height = videoflip->from_width;
115       videoflip->to_width = videoflip->from_height;
116       break;
117     case GST_VIDEOFLIP_METHOD_IDENTITY:
118     case GST_VIDEOFLIP_METHOD_180:
119     case GST_VIDEOFLIP_METHOD_HORIZ:
120     case GST_VIDEOFLIP_METHOD_VERT:
121       videoflip->to_height = videoflip->from_height;
122       videoflip->to_width = videoflip->from_width;
123       break;
124     default:
125       /* FIXME */
126       break;
127   }
128
129   GST_DEBUG ("format=%p \"%s\" from %dx%d to %dx%d",
130       videoflip->format, videoflip->format->fourcc,
131       videoflip->from_width, videoflip->from_height,
132       videoflip->to_width, videoflip->to_height);
133
134   if (videoflip->method == GST_VIDEOFLIP_METHOD_IDENTITY) {
135     GST_DEBUG ("videoflip: using passthru");
136     videoflip->passthru = TRUE;
137     videoflip->inited = TRUE;
138     return;
139   }
140
141   videoflip->from_buf_size = (videoflip->from_width * videoflip->from_height
142       * videoflip->format->depth) / 8;
143   videoflip->to_buf_size = (videoflip->to_width * videoflip->to_height
144       * videoflip->format->depth) / 8;
145
146   videoflip->inited = TRUE;
147 }
148
149 static void
150 gst_videoflip_planar411 (GstVideoflip * scale, unsigned char *dest,
151     unsigned char *src)
152 {
153   int sw = scale->from_width;
154   int sh = scale->from_height;
155   int dw = scale->to_width;
156   int dh = scale->to_height;
157
158   GST_DEBUG ("videoflip: scaling planar 4:1:1 %dx%d to %dx%d", sw, sh, dw, dh);
159
160   gst_videoflip_flip (scale, dest, src, sw, sh, dw, dh);
161
162   src += sw * sh;
163   dest += dw * dh;
164
165   dh = dh >> 1;
166   dw = dw >> 1;
167   sh = sh >> 1;
168   sw = sw >> 1;
169
170   gst_videoflip_flip (scale, dest, src, sw, sh, dw, dh);
171
172   src += sw * sh;
173   dest += dw * dh;
174
175   gst_videoflip_flip (scale, dest, src, sw, sh, dw, dh);
176 }
177
178 static void
179 gst_videoflip_flip (GstVideoflip * videoflip, unsigned char *dest,
180     unsigned char *src, int sw, int sh, int dw, int dh)
181 {
182   int x, y;
183
184   switch (videoflip->method) {
185     case GST_VIDEOFLIP_METHOD_90R:
186       for (y = 0; y < dh; y++) {
187         for (x = 0; x < dw; x++) {
188           dest[y * dw + x] = src[(sh - 1 - x) * sw + y];
189         }
190       }
191       break;
192     case GST_VIDEOFLIP_METHOD_90L:
193       for (y = 0; y < dh; y++) {
194         for (x = 0; x < dw; x++) {
195           dest[y * dw + x] = src[x * sw + (sw - 1 - y)];
196         }
197       }
198       break;
199     case GST_VIDEOFLIP_METHOD_180:
200       for (y = 0; y < dh; y++) {
201         for (x = 0; x < dw; x++) {
202           dest[y * dw + x] = src[(sh - 1 - y) * sw + (sw - 1 - x)];
203         }
204       }
205       break;
206     case GST_VIDEOFLIP_METHOD_HORIZ:
207       for (y = 0; y < dh; y++) {
208         for (x = 0; x < dw; x++) {
209           dest[y * dw + x] = src[y * sw + (sw - 1 - x)];
210         }
211       }
212       break;
213     case GST_VIDEOFLIP_METHOD_VERT:
214       for (y = 0; y < dh; y++) {
215         for (x = 0; x < dw; x++) {
216           dest[y * dw + x] = src[(sh - 1 - y) * sw + x];
217         }
218       }
219       break;
220     case GST_VIDEOFLIP_METHOD_TRANS:
221       for (y = 0; y < dh; y++) {
222         for (x = 0; x < dw; x++) {
223           dest[y * dw + x] = src[x * sw + y];
224         }
225       }
226       break;
227     case GST_VIDEOFLIP_METHOD_OTHER:
228       for (y = 0; y < dh; y++) {
229         for (x = 0; x < dw; x++) {
230           dest[y * dw + x] = src[(sh - 1 - x) * sw + (sw - 1 - y)];
231         }
232       }
233       break;
234     default:
235       /* FIXME */
236       break;
237   }
238 }