base:tizenmemory: Export gst_tizen_video_meta_map/unmap API and fix memory leak
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / 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  * Copyright (C) <2010> Sebastian Dröge <sebastian.droege@collabora.co.uk>
5  * Copyright (C) <2011> Youness Alaoui <youness.alaoui@collabora.co.uk>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 /*
24  * This file was (probably) generated from gstvideoflip.c,
25  * gstvideoflip.c,v 1.7 2003/11/08 02:48:59 dschleef Exp
26  */
27 /**
28  * SECTION:element-videoflip
29  * @title: videoflip
30  *
31  * Flips and rotates video.
32  *
33  * ## Example launch line
34  * |[
35  * gst-launch-1.0 videotestsrc ! videoflip method=clockwise ! videoconvert ! ximagesink
36  * ]| This pipeline flips the test image 90 degrees clockwise.
37  *
38  */
39
40
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44
45 #include "gstvideoflip.h"
46
47 #include <string.h>
48 #include <gst/gst.h>
49 #include <gst/video/video.h>
50 #ifdef TIZEN_FEATURE_VIDEOFLIP_TBM_SUPPORT
51 #include <gst/allocators/gsttizenbufferpool.h>
52 #endif
53
54 /* GstVideoFlip properties */
55 enum
56 {
57   PROP_0,
58   PROP_METHOD,
59   PROP_VIDEO_DIRECTION
60       /* FILL ME */
61 };
62
63 #define PROP_METHOD_DEFAULT GST_VIDEO_FLIP_METHOD_IDENTITY
64 #ifdef TIZEN_FEATURE_VIDEOFLIP_TBM_SUPPORT
65 #define TIZEN_BUFFER_POOL_MIN_BUFFERS   4
66 #define TIZEN_BUFFER_POOL_MAX_BUFFERS   10
67 #endif
68
69 GST_DEBUG_CATEGORY_STATIC (video_flip_debug);
70 #define GST_CAT_DEFAULT video_flip_debug
71
72 static GstStaticPadTemplate gst_video_flip_src_template =
73 GST_STATIC_PAD_TEMPLATE ("src",
74     GST_PAD_SRC,
75     GST_PAD_ALWAYS,
76     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
77             "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, RGBx, xBGR, BGRx, "
78             "RGB, BGR, I420, YV12, IYUV, YUY2, UYVY, YVYU, NV12, NV21, "
79 #ifdef TIZEN_FEATURE_VIDEOFLIP_TBM_SUPPORT
80             "SN12, "
81 #endif
82             "GRAY8, GRAY16_BE, GRAY16_LE, I420_10LE, I420_10BE, I420_12LE, I420_12BE, "
83             "I422_10LE, I422_10BE, I422_12LE, I422_12BE, Y444_10LE, Y444_10BE, Y444_12LE, Y444_12BE }"))
84     );
85
86 static GstStaticPadTemplate gst_video_flip_sink_template =
87 GST_STATIC_PAD_TEMPLATE ("sink",
88     GST_PAD_SINK,
89     GST_PAD_ALWAYS,
90     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
91             "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, RGBx, xBGR, BGRx, "
92             "RGB, BGR, I420, YV12, IYUV, YUY2, UYVY, YVYU, NV12, NV21, "
93 #ifdef TIZEN_FEATURE_VIDEOFLIP_TBM_SUPPORT
94             "SN12, "
95 #endif
96             "GRAY8, GRAY16_BE, GRAY16_LE, I420_10LE, I420_10BE, I420_12LE, I420_12BE, "
97             "I422_10LE, I422_10BE, I422_12LE, I422_12BE, Y444_10LE, Y444_10BE, Y444_12LE, Y444_12BE }"))
98     );
99
100 #define GST_TYPE_VIDEO_FLIP_METHOD (gst_video_flip_method_get_type())
101
102 static const GEnumValue video_flip_methods[] = {
103   {GST_VIDEO_FLIP_METHOD_IDENTITY, "Identity (no rotation)", "none"},
104   {GST_VIDEO_FLIP_METHOD_90R, "Rotate clockwise 90 degrees", "clockwise"},
105   {GST_VIDEO_FLIP_METHOD_180, "Rotate 180 degrees", "rotate-180"},
106   {GST_VIDEO_FLIP_METHOD_90L, "Rotate counter-clockwise 90 degrees",
107       "counterclockwise"},
108   {GST_VIDEO_FLIP_METHOD_HORIZ, "Flip horizontally", "horizontal-flip"},
109   {GST_VIDEO_FLIP_METHOD_VERT, "Flip vertically", "vertical-flip"},
110   {GST_VIDEO_FLIP_METHOD_TRANS,
111       "Flip across upper left/lower right diagonal", "upper-left-diagonal"},
112   {GST_VIDEO_FLIP_METHOD_OTHER,
113       "Flip across upper right/lower left diagonal", "upper-right-diagonal"},
114   {GST_VIDEO_FLIP_METHOD_AUTO,
115       "Select flip method based on image-orientation tag", "automatic"},
116   {0, NULL, NULL},
117 };
118
119 static GType
120 gst_video_flip_method_get_type (void)
121 {
122   static GType video_flip_method_type = 0;
123
124   if (!video_flip_method_type) {
125     video_flip_method_type = g_enum_register_static ("GstVideoFlipMethod",
126         video_flip_methods);
127   }
128   return video_flip_method_type;
129 }
130
131 static void
132 gst_video_flip_video_direction_interface_init (GstVideoDirectionInterface *
133     iface)
134 {
135   /* We implement the video-direction property */
136 }
137
138 #define gst_video_flip_parent_class parent_class
139 G_DEFINE_TYPE_WITH_CODE (GstVideoFlip, gst_video_flip, GST_TYPE_VIDEO_FILTER,
140     G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_DIRECTION,
141         gst_video_flip_video_direction_interface_init));
142 GST_ELEMENT_REGISTER_DEFINE (videoflip, "videoflip", GST_RANK_NONE,
143     GST_TYPE_VIDEO_FLIP);
144
145 static GstCaps *
146 gst_video_flip_transform_caps (GstBaseTransform * trans,
147     GstPadDirection direction, GstCaps * caps, GstCaps * filter)
148 {
149   GstVideoFlip *videoflip = GST_VIDEO_FLIP (trans);
150   GstCaps *ret;
151   gint width, height, i;
152
153   ret = gst_caps_copy (caps);
154
155   GST_OBJECT_LOCK (videoflip);
156
157   if (videoflip->change_configuring_method) {
158     GEnumValue *configuring_method_enum, *method_enum;
159     GEnumClass *enum_class =
160         g_type_class_ref (GST_TYPE_VIDEO_ORIENTATION_METHOD);
161
162     configuring_method_enum =
163         g_enum_get_value (enum_class, videoflip->configuring_method);
164     method_enum = g_enum_get_value (enum_class, videoflip->proposed_method);
165     GST_LOG_OBJECT (videoflip,
166         "Changing configuring method from %s to proposed %s",
167         configuring_method_enum ? configuring_method_enum->value_nick : "(nil)",
168         method_enum ? method_enum->value_nick : "(nil)");
169     g_type_class_unref (enum_class);
170
171     videoflip->configuring_method = videoflip->proposed_method;
172   }
173   videoflip->change_configuring_method = FALSE;
174
175   for (i = 0; i < gst_caps_get_size (ret); i++) {
176     GstStructure *structure = gst_caps_get_structure (ret, i);
177     gint par_n, par_d;
178
179     if (gst_structure_get_int (structure, "width", &width) &&
180         gst_structure_get_int (structure, "height", &height)) {
181
182       switch (videoflip->configuring_method) {
183         case GST_VIDEO_ORIENTATION_90R:
184         case GST_VIDEO_ORIENTATION_90L:
185         case GST_VIDEO_ORIENTATION_UL_LR:
186         case GST_VIDEO_ORIENTATION_UR_LL:
187           gst_structure_set (structure, "width", G_TYPE_INT, height,
188               "height", G_TYPE_INT, width, NULL);
189           if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
190                   &par_n, &par_d)) {
191             if (par_n != 1 || par_d != 1) {
192               GValue val = { 0, };
193
194               g_value_init (&val, GST_TYPE_FRACTION);
195               gst_value_set_fraction (&val, par_d, par_n);
196               gst_structure_set_value (structure, "pixel-aspect-ratio", &val);
197               g_value_unset (&val);
198             }
199           }
200           break;
201         case GST_VIDEO_ORIENTATION_IDENTITY:
202         case GST_VIDEO_ORIENTATION_180:
203         case GST_VIDEO_ORIENTATION_HORIZ:
204         case GST_VIDEO_ORIENTATION_VERT:
205           gst_structure_set (structure, "width", G_TYPE_INT, width,
206               "height", G_TYPE_INT, height, NULL);
207           break;
208         case GST_VIDEO_ORIENTATION_CUSTOM:
209           GST_WARNING_OBJECT (videoflip, "unsupported custom orientation");
210           break;
211         default:
212           g_assert_not_reached ();
213           break;
214       }
215     }
216   }
217   GST_OBJECT_UNLOCK (videoflip);
218
219   GST_DEBUG_OBJECT (videoflip, "transformed %" GST_PTR_FORMAT " to %"
220       GST_PTR_FORMAT, caps, ret);
221
222   if (filter) {
223     GstCaps *intersection;
224
225     GST_DEBUG_OBJECT (videoflip, "Using filter caps %" GST_PTR_FORMAT, filter);
226     intersection =
227         gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
228     gst_caps_unref (ret);
229     ret = intersection;
230     GST_DEBUG_OBJECT (videoflip, "Intersection %" GST_PTR_FORMAT, ret);
231   }
232
233   return ret;
234 }
235
236 static void
237 gst_video_flip_planar_yuv (GstVideoFlip * videoflip, GstVideoFrame * dest,
238     const GstVideoFrame * src)
239 {
240   gint x, y;
241   guint8 const *s;
242   guint8 *d;
243   gint src_y_stride, src_u_stride, src_v_stride;
244   gint src_y_height, src_u_height, src_v_height;
245   gint src_y_width, src_u_width, src_v_width;
246   gint dest_y_stride, dest_u_stride, dest_v_stride;
247   gint dest_y_height, dest_u_height, dest_v_height;
248   gint dest_y_width, dest_u_width, dest_v_width;
249
250   src_y_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src, 0);
251   src_u_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src, 1);
252   src_v_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src, 2);
253
254   dest_y_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest, 0);
255   dest_u_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest, 1);
256   dest_v_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest, 2);
257
258   src_y_width = GST_VIDEO_FRAME_COMP_WIDTH (src, 0);
259   src_u_width = GST_VIDEO_FRAME_COMP_WIDTH (src, 1);
260   src_v_width = GST_VIDEO_FRAME_COMP_WIDTH (src, 2);
261
262   dest_y_width = GST_VIDEO_FRAME_COMP_WIDTH (dest, 0);
263   dest_u_width = GST_VIDEO_FRAME_COMP_WIDTH (dest, 1);
264   dest_v_width = GST_VIDEO_FRAME_COMP_WIDTH (dest, 2);
265
266   src_y_height = GST_VIDEO_FRAME_COMP_HEIGHT (src, 0);
267   src_u_height = GST_VIDEO_FRAME_COMP_HEIGHT (src, 1);
268   src_v_height = GST_VIDEO_FRAME_COMP_HEIGHT (src, 2);
269
270   dest_y_height = GST_VIDEO_FRAME_COMP_HEIGHT (dest, 0);
271   dest_u_height = GST_VIDEO_FRAME_COMP_HEIGHT (dest, 1);
272   dest_v_height = GST_VIDEO_FRAME_COMP_HEIGHT (dest, 2);
273
274   switch (videoflip->active_method) {
275     case GST_VIDEO_ORIENTATION_90R:
276       /* Flip Y */
277       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
278       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
279       for (y = 0; y < dest_y_height; y++) {
280         for (x = 0; x < dest_y_width; x++) {
281           d[y * dest_y_stride + x] =
282               s[(src_y_height - 1 - x) * src_y_stride + y];
283         }
284       }
285       /* Flip U */
286       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
287       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
288       for (y = 0; y < dest_u_height; y++) {
289         for (x = 0; x < dest_u_width; x++) {
290           d[y * dest_u_stride + x] =
291               s[(src_u_height - 1 - x) * src_u_stride + y];
292         }
293       }
294       /* Flip V */
295       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
296       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
297       for (y = 0; y < dest_v_height; y++) {
298         for (x = 0; x < dest_v_width; x++) {
299           d[y * dest_v_stride + x] =
300               s[(src_v_height - 1 - x) * src_v_stride + y];
301         }
302       }
303       break;
304     case GST_VIDEO_ORIENTATION_90L:
305       /* Flip Y */
306       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
307       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
308       for (y = 0; y < dest_y_height; y++) {
309         for (x = 0; x < dest_y_width; x++) {
310           d[y * dest_y_stride + x] =
311               s[x * src_y_stride + (src_y_width - 1 - y)];
312         }
313       }
314       /* Flip U */
315       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
316       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
317       for (y = 0; y < dest_u_height; y++) {
318         for (x = 0; x < dest_u_width; x++) {
319           d[y * dest_u_stride + x] =
320               s[x * src_u_stride + (src_u_width - 1 - y)];
321         }
322       }
323       /* Flip V */
324       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
325       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
326       for (y = 0; y < dest_v_height; y++) {
327         for (x = 0; x < dest_v_width; x++) {
328           d[y * dest_v_stride + x] =
329               s[x * src_v_stride + (src_v_width - 1 - y)];
330         }
331       }
332       break;
333     case GST_VIDEO_ORIENTATION_180:
334       /* Flip Y */
335       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
336       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
337       for (y = 0; y < dest_y_height; y++) {
338         for (x = 0; x < dest_y_width; x++) {
339           d[y * dest_y_stride + x] =
340               s[(src_y_height - 1 - y) * src_y_stride + (src_y_width - 1 - x)];
341         }
342       }
343       /* Flip U */
344       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
345       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
346       for (y = 0; y < dest_u_height; y++) {
347         for (x = 0; x < dest_u_width; x++) {
348           d[y * dest_u_stride + x] =
349               s[(src_u_height - 1 - y) * src_u_stride + (src_u_width - 1 - x)];
350         }
351       }
352       /* Flip V */
353       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
354       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
355       for (y = 0; y < dest_v_height; y++) {
356         for (x = 0; x < dest_v_width; x++) {
357           d[y * dest_v_stride + x] =
358               s[(src_v_height - 1 - y) * src_v_stride + (src_v_width - 1 - x)];
359         }
360       }
361       break;
362     case GST_VIDEO_ORIENTATION_HORIZ:
363       /* Flip Y */
364       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
365       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
366       for (y = 0; y < dest_y_height; y++) {
367         for (x = 0; x < dest_y_width; x++) {
368           d[y * dest_y_stride + x] =
369               s[y * src_y_stride + (src_y_width - 1 - x)];
370         }
371       }
372       /* Flip U */
373       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
374       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
375       for (y = 0; y < dest_u_height; y++) {
376         for (x = 0; x < dest_u_width; x++) {
377           d[y * dest_u_stride + x] =
378               s[y * src_u_stride + (src_u_width - 1 - x)];
379         }
380       }
381       /* Flip V */
382       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
383       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
384       for (y = 0; y < dest_v_height; y++) {
385         for (x = 0; x < dest_v_width; x++) {
386           d[y * dest_v_stride + x] =
387               s[y * src_v_stride + (src_v_width - 1 - x)];
388         }
389       }
390       break;
391     case GST_VIDEO_ORIENTATION_VERT:
392       /* Flip Y */
393       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
394       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
395       for (y = 0; y < dest_y_height; y++) {
396         for (x = 0; x < dest_y_width; x++) {
397           d[y * dest_y_stride + x] =
398               s[(src_y_height - 1 - y) * src_y_stride + x];
399         }
400       }
401       /* Flip U */
402       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
403       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
404       for (y = 0; y < dest_u_height; y++) {
405         for (x = 0; x < dest_u_width; x++) {
406           d[y * dest_u_stride + x] =
407               s[(src_u_height - 1 - y) * src_u_stride + x];
408         }
409       }
410       /* Flip V */
411       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
412       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
413       for (y = 0; y < dest_v_height; y++) {
414         for (x = 0; x < dest_v_width; x++) {
415           d[y * dest_v_stride + x] =
416               s[(src_v_height - 1 - y) * src_v_stride + x];
417         }
418       }
419       break;
420     case GST_VIDEO_ORIENTATION_UL_LR:
421       /* Flip Y */
422       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
423       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
424       for (y = 0; y < dest_y_height; y++) {
425         for (x = 0; x < dest_y_width; x++) {
426           d[y * dest_y_stride + x] = s[x * src_y_stride + y];
427         }
428       }
429       /* Flip U */
430       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
431       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
432       for (y = 0; y < dest_u_height; y++) {
433         for (x = 0; x < dest_u_width; x++) {
434           d[y * dest_u_stride + x] = s[x * src_u_stride + y];
435         }
436       }
437       /* Flip V */
438       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
439       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
440       for (y = 0; y < dest_v_height; y++) {
441         for (x = 0; x < dest_v_width; x++) {
442           d[y * dest_v_stride + x] = s[x * src_v_stride + y];
443         }
444       }
445       break;
446     case GST_VIDEO_ORIENTATION_UR_LL:
447       /* Flip Y */
448       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
449       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
450       for (y = 0; y < dest_y_height; y++) {
451         for (x = 0; x < dest_y_width; x++) {
452           d[y * dest_y_stride + x] =
453               s[(src_y_height - 1 - x) * src_y_stride + (src_y_width - 1 - y)];
454         }
455       }
456       /* Flip U */
457       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
458       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
459       for (y = 0; y < dest_u_height; y++) {
460         for (x = 0; x < dest_u_width; x++) {
461           d[y * dest_u_stride + x] =
462               s[(src_u_height - 1 - x) * src_u_stride + (src_u_width - 1 - y)];
463         }
464       }
465       /* Flip V */
466       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
467       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
468       for (y = 0; y < dest_v_height; y++) {
469         for (x = 0; x < dest_v_width; x++) {
470           d[y * dest_v_stride + x] =
471               s[(src_v_height - 1 - x) * src_v_stride + (src_v_width - 1 - y)];
472         }
473       }
474       break;
475     case GST_VIDEO_ORIENTATION_IDENTITY:
476       gst_video_frame_copy (dest, src);
477       break;
478     default:
479       g_assert_not_reached ();
480       break;
481   }
482 }
483
484 static void
485 gst_video_flip_planar_yuv_16bit (GstVideoFlip * videoflip, GstVideoFrame * dest,
486     const GstVideoFrame * src)
487 {
488   gint x, y;
489   guint16 const *s;
490   guint16 *d;
491   gint src_y_stride, src_u_stride, src_v_stride;
492   gint src_y_height, src_u_height, src_v_height;
493   gint src_y_width, src_u_width, src_v_width;
494   gint dest_y_stride, dest_u_stride, dest_v_stride;
495   gint dest_y_height, dest_u_height, dest_v_height;
496   gint dest_y_width, dest_u_width, dest_v_width;
497
498   /* Divide strides by 2 because we're operating on guint16's */
499   src_y_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src, 0) / 2;
500   src_u_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src, 1) / 2;
501   src_v_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src, 2) / 2;
502
503   dest_y_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest, 0) / 2;
504   dest_u_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest, 1) / 2;
505   dest_v_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest, 2) / 2;
506
507   src_y_width = GST_VIDEO_FRAME_COMP_WIDTH (src, 0);
508   src_u_width = GST_VIDEO_FRAME_COMP_WIDTH (src, 1);
509   src_v_width = GST_VIDEO_FRAME_COMP_WIDTH (src, 2);
510
511   dest_y_width = GST_VIDEO_FRAME_COMP_WIDTH (dest, 0);
512   dest_u_width = GST_VIDEO_FRAME_COMP_WIDTH (dest, 1);
513   dest_v_width = GST_VIDEO_FRAME_COMP_WIDTH (dest, 2);
514
515   src_y_height = GST_VIDEO_FRAME_COMP_HEIGHT (src, 0);
516   src_u_height = GST_VIDEO_FRAME_COMP_HEIGHT (src, 1);
517   src_v_height = GST_VIDEO_FRAME_COMP_HEIGHT (src, 2);
518
519   dest_y_height = GST_VIDEO_FRAME_COMP_HEIGHT (dest, 0);
520   dest_u_height = GST_VIDEO_FRAME_COMP_HEIGHT (dest, 1);
521   dest_v_height = GST_VIDEO_FRAME_COMP_HEIGHT (dest, 2);
522
523   switch (videoflip->active_method) {
524     case GST_VIDEO_ORIENTATION_90R:
525       /* Flip Y */
526       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
527       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
528       for (y = 0; y < dest_y_height; y++) {
529         for (x = 0; x < dest_y_width; x++) {
530           d[y * dest_y_stride + x] =
531               s[(src_y_height - 1 - x) * src_y_stride + y];
532         }
533       }
534       /* Flip U */
535       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
536       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
537       for (y = 0; y < dest_u_height; y++) {
538         for (x = 0; x < dest_u_width; x++) {
539           d[y * dest_u_stride + x] =
540               s[(src_u_height - 1 - x) * src_u_stride + y];
541         }
542       }
543       /* Flip V */
544       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
545       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
546       for (y = 0; y < dest_v_height; y++) {
547         for (x = 0; x < dest_v_width; x++) {
548           d[y * dest_v_stride + x] =
549               s[(src_v_height - 1 - x) * src_v_stride + y];
550         }
551       }
552       break;
553     case GST_VIDEO_ORIENTATION_90L:
554       /* Flip Y */
555       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
556       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
557       for (y = 0; y < dest_y_height; y++) {
558         for (x = 0; x < dest_y_width; x++) {
559           d[y * dest_y_stride + x] =
560               s[x * src_y_stride + (src_y_width - 1 - y)];
561         }
562       }
563       /* Flip U */
564       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
565       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
566       for (y = 0; y < dest_u_height; y++) {
567         for (x = 0; x < dest_u_width; x++) {
568           d[y * dest_u_stride + x] =
569               s[x * src_u_stride + (src_u_width - 1 - y)];
570         }
571       }
572       /* Flip V */
573       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
574       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
575       for (y = 0; y < dest_v_height; y++) {
576         for (x = 0; x < dest_v_width; x++) {
577           d[y * dest_v_stride + x] =
578               s[x * src_v_stride + (src_v_width - 1 - y)];
579         }
580       }
581       break;
582     case GST_VIDEO_ORIENTATION_180:
583       /* Flip Y */
584       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
585       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
586       for (y = 0; y < dest_y_height; y++) {
587         for (x = 0; x < dest_y_width; x++) {
588           d[y * dest_y_stride + x] =
589               s[(src_y_height - 1 - y) * src_y_stride + (src_y_width - 1 - x)];
590         }
591       }
592       /* Flip U */
593       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
594       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
595       for (y = 0; y < dest_u_height; y++) {
596         for (x = 0; x < dest_u_width; x++) {
597           d[y * dest_u_stride + x] =
598               s[(src_u_height - 1 - y) * src_u_stride + (src_u_width - 1 - x)];
599         }
600       }
601       /* Flip V */
602       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
603       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
604       for (y = 0; y < dest_v_height; y++) {
605         for (x = 0; x < dest_v_width; x++) {
606           d[y * dest_v_stride + x] =
607               s[(src_v_height - 1 - y) * src_v_stride + (src_v_width - 1 - x)];
608         }
609       }
610       break;
611     case GST_VIDEO_ORIENTATION_HORIZ:
612       /* Flip Y */
613       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
614       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
615       for (y = 0; y < dest_y_height; y++) {
616         for (x = 0; x < dest_y_width; x++) {
617           d[y * dest_y_stride + x] =
618               s[y * src_y_stride + (src_y_width - 1 - x)];
619         }
620       }
621       /* Flip U */
622       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
623       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
624       for (y = 0; y < dest_u_height; y++) {
625         for (x = 0; x < dest_u_width; x++) {
626           d[y * dest_u_stride + x] =
627               s[y * src_u_stride + (src_u_width - 1 - x)];
628         }
629       }
630       /* Flip V */
631       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
632       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
633       for (y = 0; y < dest_v_height; y++) {
634         for (x = 0; x < dest_v_width; x++) {
635           d[y * dest_v_stride + x] =
636               s[y * src_v_stride + (src_v_width - 1 - x)];
637         }
638       }
639       break;
640     case GST_VIDEO_ORIENTATION_VERT:
641       /* Flip Y */
642       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
643       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
644       for (y = 0; y < dest_y_height; y++) {
645         for (x = 0; x < dest_y_width; x++) {
646           d[y * dest_y_stride + x] =
647               s[(src_y_height - 1 - y) * src_y_stride + x];
648         }
649       }
650       /* Flip U */
651       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
652       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
653       for (y = 0; y < dest_u_height; y++) {
654         for (x = 0; x < dest_u_width; x++) {
655           d[y * dest_u_stride + x] =
656               s[(src_u_height - 1 - y) * src_u_stride + x];
657         }
658       }
659       /* Flip V */
660       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
661       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
662       for (y = 0; y < dest_v_height; y++) {
663         for (x = 0; x < dest_v_width; x++) {
664           d[y * dest_v_stride + x] =
665               s[(src_v_height - 1 - y) * src_v_stride + x];
666         }
667       }
668       break;
669     case GST_VIDEO_ORIENTATION_UL_LR:
670       /* Flip Y */
671       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
672       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
673       for (y = 0; y < dest_y_height; y++) {
674         for (x = 0; x < dest_y_width; x++) {
675           d[y * dest_y_stride + x] = s[x * src_y_stride + y];
676         }
677       }
678       /* Flip U */
679       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
680       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
681       for (y = 0; y < dest_u_height; y++) {
682         for (x = 0; x < dest_u_width; x++) {
683           d[y * dest_u_stride + x] = s[x * src_u_stride + y];
684         }
685       }
686       /* Flip V */
687       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
688       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
689       for (y = 0; y < dest_v_height; y++) {
690         for (x = 0; x < dest_v_width; x++) {
691           d[y * dest_v_stride + x] = s[x * src_v_stride + y];
692         }
693       }
694       break;
695     case GST_VIDEO_ORIENTATION_UR_LL:
696       /* Flip Y */
697       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
698       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
699       for (y = 0; y < dest_y_height; y++) {
700         for (x = 0; x < dest_y_width; x++) {
701           d[y * dest_y_stride + x] =
702               s[(src_y_height - 1 - x) * src_y_stride + (src_y_width - 1 - y)];
703         }
704       }
705       /* Flip U */
706       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
707       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
708       for (y = 0; y < dest_u_height; y++) {
709         for (x = 0; x < dest_u_width; x++) {
710           d[y * dest_u_stride + x] =
711               s[(src_u_height - 1 - x) * src_u_stride + (src_u_width - 1 - y)];
712         }
713       }
714       /* Flip V */
715       s = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
716       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 2);
717       for (y = 0; y < dest_v_height; y++) {
718         for (x = 0; x < dest_v_width; x++) {
719           d[y * dest_v_stride + x] =
720               s[(src_v_height - 1 - x) * src_v_stride + (src_v_width - 1 - y)];
721         }
722       }
723       break;
724     case GST_VIDEO_ORIENTATION_IDENTITY:
725       gst_video_frame_copy (dest, src);
726       break;
727     default:
728       g_assert_not_reached ();
729       break;
730   }
731 }
732
733 static inline void
734 rotate_yuv422_plane (GstVideoFrame * dest, const GstVideoFrame * src,
735     gint plane_index, GstVideoOrientationMethod method,
736     gboolean is_chroma, gboolean is_le)
737 {
738   gint src_stride, src_height, src_width;
739   gint dest_stride, dest_height, dest_width;
740   gint x, y;
741   guint scale;
742   guint16 const *s, *addr;
743   guint16 *d;
744   guint16 val, val2;
745
746   s = GST_VIDEO_FRAME_PLANE_DATA (src, plane_index);
747   d = GST_VIDEO_FRAME_PLANE_DATA (dest, plane_index);
748
749   /* Divide strides by 2 because we're operating on guint16's */
750   src_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src, plane_index) / 2;
751   src_height = GST_VIDEO_FRAME_COMP_HEIGHT (src, plane_index);
752   src_width = GST_VIDEO_FRAME_COMP_WIDTH (src, plane_index);
753
754   dest_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest, plane_index) / 2;
755   dest_height = GST_VIDEO_FRAME_COMP_HEIGHT (dest, plane_index);
756   dest_width = GST_VIDEO_FRAME_COMP_WIDTH (dest, plane_index);
757
758   scale = is_chroma ? 2 : 1;
759
760   switch (method) {
761     case GST_VIDEO_ORIENTATION_90R:
762       if (is_le) {
763         for (y = 0; y < dest_height; y++) {
764           for (x = 0; x < dest_width; x++) {
765             addr = s + (src_height - 1 - x * scale) * src_stride + y / scale;
766             val = GST_READ_UINT16_LE (addr);
767
768             if (is_chroma && x * 2 + 1 < src_height) {
769               addr = s + (src_height - 1 - (x * 2 + 1)) * src_stride + y / 2;
770               val2 = GST_READ_UINT16_LE (addr);
771               val = (val + val2) / 2;
772             }
773
774             GST_WRITE_UINT16_LE (d + y * dest_stride + x, val);
775           }
776         }
777       } else {
778         for (y = 0; y < dest_height; y++) {
779           for (x = 0; x < dest_width; x++) {
780             addr = s + (src_height - 1 - x * scale) * src_stride + y / scale;
781             val = GST_READ_UINT16_BE (addr);
782
783             if (is_chroma && x * 2 + 1 < src_height) {
784               addr = s + (src_height - 1 - (x * 2 + 1)) * src_stride + y / 2;
785               val2 = GST_READ_UINT16_BE (addr);
786               val = (val + val2) / 2;
787             }
788
789             GST_WRITE_UINT16_BE (d + y * dest_stride + x, val);
790           }
791         }
792       }
793       break;
794     case GST_VIDEO_ORIENTATION_90L:
795       if (is_le) {
796         for (y = 0; y < dest_height; y++) {
797           for (x = 0; x < dest_width; x++) {
798             addr = s + x * scale * src_stride + (src_width - 1 - y / scale);
799             val = GST_READ_UINT16_LE (addr);
800
801             if (is_chroma && x * 2 + 1 < src_width) {
802               addr = s + (x * 2 + 1) * src_stride + (src_width - 1 - y / 2);
803               val2 = GST_READ_UINT16_LE (addr);
804               val = (val + val2) / 2;
805             }
806
807             GST_WRITE_UINT16_LE (d + y * dest_stride + x, val);
808           }
809         }
810       } else {
811         for (y = 0; y < dest_height; y++) {
812           for (x = 0; x < dest_width; x++) {
813             addr = s + x * scale * src_stride + (src_width - 1 - y / scale);
814             val = GST_READ_UINT16_BE (addr);
815
816             if (is_chroma && x * 2 + 1 < src_width) {
817               addr = s + (x * 2 + 1) * src_stride + (src_width - 1 - y / 2);
818               val2 = GST_READ_UINT16_BE (addr);
819               val = (val + val2) / 2;
820             }
821
822             GST_WRITE_UINT16_BE (d + y * dest_stride + x, val);
823           }
824         }
825       }
826       break;
827     case GST_VIDEO_ORIENTATION_180:
828       for (y = 0; y < dest_height; y++) {
829         for (x = 0; x < dest_width; x++) {
830           d[y * dest_stride + x] =
831               s[(src_height - 1 - y) * src_stride + (src_width - 1 - x)];
832         }
833       }
834       break;
835     case GST_VIDEO_ORIENTATION_HORIZ:
836       for (y = 0; y < dest_height; y++) {
837         for (x = 0; x < dest_width; x++) {
838           d[y * dest_stride + x] = s[y * src_stride + (src_width - 1 - x)];
839         }
840       }
841       break;
842     case GST_VIDEO_ORIENTATION_VERT:
843       for (y = 0; y < dest_height; y++) {
844         for (x = 0; x < dest_width; x++) {
845           d[y * dest_stride + x] = s[(src_height - 1 - y) * src_stride + x];
846         }
847       }
848       break;
849     case GST_VIDEO_ORIENTATION_UL_LR:
850       if (is_le) {
851         for (y = 0; y < dest_height; y++) {
852           for (x = 0; x < dest_width; x++) {
853             addr = s + x * scale * src_stride + y / scale;
854             val = GST_READ_UINT16_LE (addr);
855
856             if (is_chroma && x * 2 + 1 < src_width) {
857               addr = s + (x * 2 + 1) * src_stride + y / 2;
858               val2 = GST_READ_UINT16_LE (addr);
859               val = (val + val2) / 2;
860             }
861
862             GST_WRITE_UINT16_LE (d + y * dest_stride + x, val);
863           }
864         }
865       } else {
866         for (y = 0; y < dest_height; y++) {
867           for (x = 0; x < dest_width; x++) {
868             addr = s + x * scale * src_stride + y / scale;
869             val = GST_READ_UINT16_BE (addr);
870
871             if (is_chroma && x * 2 + 1 < src_width) {
872               addr = s + (x * 2 + 1) * src_stride + y / 2;
873               val2 = GST_READ_UINT16_BE (addr);
874               val = (val + val2) / 2;
875             }
876
877             GST_WRITE_UINT16_BE (d + y * dest_stride + x, val);
878           }
879         }
880       }
881       break;
882     case GST_VIDEO_ORIENTATION_UR_LL:
883       if (is_le) {
884         for (y = 0; y < dest_height; y++) {
885           for (x = 0; x < dest_width; x++) {
886             addr = s
887                 + (src_height - 1 - x * scale) * src_stride
888                 + (src_width - 1 - y / scale);
889             val = GST_READ_UINT16_LE (addr);
890
891             if (is_chroma && x * 2 + 1 < src_width) {
892               addr = s
893                   + (src_height - 1 - (x * 2 + 1)) * src_stride
894                   + (src_width - 1 - y / 2);
895               val2 = GST_READ_UINT16_LE (addr);
896               val = (val + val2) / 2;
897             }
898
899             GST_WRITE_UINT16_LE (d + y * dest_stride + x, val);
900           }
901         }
902       } else {
903         for (y = 0; y < dest_height; y++) {
904           for (x = 0; x < dest_width; x++) {
905             addr = s
906                 + (src_height - 1 - x * scale) * src_stride
907                 + (src_width - 1 - y / scale);
908             val = GST_READ_UINT16_BE (addr);
909
910             if (is_chroma && x * 2 + 1 < src_width) {
911               addr = s
912                   + (src_height - 1 - (x * 2 + 1)) * src_stride
913                   + (src_width - 1 - y / 2);
914               val2 = GST_READ_UINT16_BE (addr);
915               val = (val + val2) / 2;
916             }
917
918             GST_WRITE_UINT16_BE (d + y * dest_stride + x, val);
919           }
920         }
921       }
922       break;
923     case GST_VIDEO_ORIENTATION_IDENTITY:
924       gst_video_frame_copy (dest, src);
925       break;
926     default:
927       g_assert_not_reached ();
928       break;
929   }
930 }
931
932 static void
933 gst_video_flip_planar_yuv_422_16bit (GstVideoFlip * videoflip,
934     GstVideoFrame * dest, const GstVideoFrame * src)
935 {
936   gboolean format_is_le;
937
938   /* We need to consider the endianness during transforms
939    * which need average chrominance values between two pixels */
940   format_is_le = GST_VIDEO_FORMAT_INFO_IS_LE (dest->info.finfo);
941
942   /* Attempt to get the compiler to inline specialized variants of this function 
943    * to avoid too much branching due to endianness checks */
944   if (format_is_le) {
945     rotate_yuv422_plane (dest, src, 0, videoflip->active_method, FALSE, TRUE);
946     rotate_yuv422_plane (dest, src, 1, videoflip->active_method, TRUE, TRUE);
947     rotate_yuv422_plane (dest, src, 2, videoflip->active_method, TRUE, TRUE);
948   } else {
949     rotate_yuv422_plane (dest, src, 0, videoflip->active_method, FALSE, FALSE);
950     rotate_yuv422_plane (dest, src, 1, videoflip->active_method, TRUE, FALSE);
951     rotate_yuv422_plane (dest, src, 2, videoflip->active_method, TRUE, FALSE);
952   }
953 }
954
955 static void
956 gst_video_flip_semi_planar_yuv (GstVideoFlip * videoflip, GstVideoFrame * dest,
957     const GstVideoFrame * src)
958 {
959   gint x, y;
960   guint8 const *s;
961   guint8 *d;
962   gint s_off, d_off;
963   gint src_y_stride, src_uv_stride;
964   gint src_y_height, src_uv_height;
965   gint src_y_width, src_uv_width;
966   gint dest_y_stride, dest_uv_stride;
967   gint dest_y_height, dest_uv_height;
968   gint dest_y_width, dest_uv_width;
969
970
971   src_y_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src, 0);
972   src_uv_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src, 1);
973
974   dest_y_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest, 0);
975   dest_uv_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest, 1);
976
977   src_y_width = GST_VIDEO_FRAME_COMP_WIDTH (src, 0);
978   src_uv_width = GST_VIDEO_FRAME_COMP_WIDTH (src, 1);
979
980   dest_y_width = GST_VIDEO_FRAME_COMP_WIDTH (dest, 0);
981   dest_uv_width = GST_VIDEO_FRAME_COMP_WIDTH (dest, 1);
982
983   src_y_height = GST_VIDEO_FRAME_COMP_HEIGHT (src, 0);
984   src_uv_height = GST_VIDEO_FRAME_COMP_HEIGHT (src, 1);
985
986   dest_y_height = GST_VIDEO_FRAME_COMP_HEIGHT (dest, 0);
987   dest_uv_height = GST_VIDEO_FRAME_COMP_HEIGHT (dest, 1);
988
989   switch (videoflip->active_method) {
990     case GST_VIDEO_ORIENTATION_90R:
991       /* Flip Y */
992       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
993       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
994       for (y = 0; y < dest_y_height; y++) {
995         for (x = 0; x < dest_y_width; x++) {
996           d[y * dest_y_stride + x] =
997               s[(src_y_height - 1 - x) * src_y_stride + y];
998         }
999       }
1000       /* Flip UV */
1001       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
1002       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
1003       for (y = 0; y < dest_uv_height; y++) {
1004         for (x = 0; x < dest_uv_width; x++) {
1005           d_off = y * dest_uv_stride + x * 2;
1006           s_off = (src_uv_height - 1 - x) * src_uv_stride + y * 2;
1007           d[d_off] = s[s_off];
1008           d[d_off + 1] = s[s_off + 1];
1009         }
1010       }
1011       break;
1012     case GST_VIDEO_ORIENTATION_90L:
1013       /* Flip Y */
1014       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
1015       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
1016       for (y = 0; y < dest_y_height; y++) {
1017         for (x = 0; x < dest_y_width; x++) {
1018           d[y * dest_y_stride + x] =
1019               s[x * src_y_stride + (src_y_width - 1 - y)];
1020         }
1021       }
1022       /* Flip UV */
1023       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
1024       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
1025       for (y = 0; y < dest_uv_height; y++) {
1026         for (x = 0; x < dest_uv_width; x++) {
1027           d_off = y * dest_uv_stride + x * 2;
1028           s_off = x * src_uv_stride + (src_uv_width - 1 - y) * 2;
1029           d[d_off] = s[s_off];
1030           d[d_off + 1] = s[s_off + 1];
1031         }
1032       }
1033       break;
1034     case GST_VIDEO_ORIENTATION_180:
1035       /* Flip Y */
1036       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
1037       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
1038       for (y = 0; y < dest_y_height; y++) {
1039         for (x = 0; x < dest_y_width; x++) {
1040           d[y * dest_y_stride + x] =
1041               s[(src_y_height - 1 - y) * src_y_stride + (src_y_width - 1 - x)];
1042         }
1043       }
1044       /* Flip UV */
1045       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
1046       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
1047       for (y = 0; y < dest_uv_height; y++) {
1048         for (x = 0; x < dest_uv_width; x++) {
1049           d_off = y * dest_uv_stride + x * 2;
1050           s_off = (src_uv_height - 1 - y) * src_uv_stride + (src_uv_width - 1 -
1051               x) * 2;
1052           d[d_off] = s[s_off];
1053           d[d_off + 1] = s[s_off + 1];
1054         }
1055       }
1056       break;
1057     case GST_VIDEO_ORIENTATION_HORIZ:
1058       /* Flip Y */
1059       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
1060       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
1061       for (y = 0; y < dest_y_height; y++) {
1062         for (x = 0; x < dest_y_width; x++) {
1063           d[y * dest_y_stride + x] =
1064               s[y * src_y_stride + (src_y_width - 1 - x)];
1065         }
1066       }
1067       /* Flip UV */
1068       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
1069       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
1070       for (y = 0; y < dest_uv_height; y++) {
1071         for (x = 0; x < dest_uv_width; x++) {
1072           d_off = y * dest_uv_stride + x * 2;
1073           s_off = y * src_uv_stride + (src_uv_width - 1 - x) * 2;
1074           d[d_off] = s[s_off];
1075           d[d_off + 1] = s[s_off + 1];
1076         }
1077       }
1078       break;
1079     case GST_VIDEO_ORIENTATION_VERT:
1080       /* Flip Y */
1081       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
1082       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
1083       for (y = 0; y < dest_y_height; y++) {
1084         for (x = 0; x < dest_y_width; x++) {
1085           d[y * dest_y_stride + x] =
1086               s[(src_y_height - 1 - y) * src_y_stride + x];
1087         }
1088       }
1089       /* Flip UV */
1090       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
1091       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
1092       for (y = 0; y < dest_uv_height; y++) {
1093         for (x = 0; x < dest_uv_width; x++) {
1094           d_off = y * dest_uv_stride + x * 2;
1095           s_off = (src_uv_height - 1 - y) * src_uv_stride + x * 2;
1096           d[d_off] = s[s_off];
1097           d[d_off + 1] = s[s_off + 1];
1098         }
1099       }
1100       break;
1101     case GST_VIDEO_ORIENTATION_UL_LR:
1102       /* Flip Y */
1103       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
1104       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
1105       for (y = 0; y < dest_y_height; y++) {
1106         for (x = 0; x < dest_y_width; x++) {
1107           d[y * dest_y_stride + x] = s[x * src_y_stride + y];
1108         }
1109       }
1110       /* Flip UV */
1111       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
1112       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
1113       for (y = 0; y < dest_uv_height; y++) {
1114         for (x = 0; x < dest_uv_width; x++) {
1115           d_off = y * dest_uv_stride + x * 2;
1116           s_off = x * src_uv_stride + y * 2;
1117           d[d_off] = s[s_off];
1118           d[d_off + 1] = s[s_off + 1];
1119         }
1120       }
1121       break;
1122     case GST_VIDEO_ORIENTATION_UR_LL:
1123       /* Flip Y */
1124       s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
1125       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
1126       for (y = 0; y < dest_y_height; y++) {
1127         for (x = 0; x < dest_y_width; x++) {
1128           d[y * dest_y_stride + x] =
1129               s[(src_y_height - 1 - x) * src_y_stride + (src_y_width - 1 - y)];
1130         }
1131       }
1132       /* Flip UV */
1133       s = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
1134       d = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
1135       for (y = 0; y < dest_uv_height; y++) {
1136         for (x = 0; x < dest_uv_width; x++) {
1137           d_off = y * dest_uv_stride + x * 2;
1138           s_off = (src_uv_height - 1 - x) * src_uv_stride + (src_uv_width - 1 -
1139               y) * 2;
1140           d[d_off] = s[s_off];
1141           d[d_off + 1] = s[s_off + 1];
1142         }
1143       }
1144       break;
1145     case GST_VIDEO_ORIENTATION_IDENTITY:
1146       gst_video_frame_copy (dest, src);
1147       break;
1148     default:
1149       g_assert_not_reached ();
1150       break;
1151   }
1152 }
1153
1154 static void
1155 gst_video_flip_packed_simple (GstVideoFlip * videoflip, GstVideoFrame * dest,
1156     const GstVideoFrame * src)
1157 {
1158   gint x, y, z;
1159   guint8 const *s;
1160   guint8 *d;
1161   gint sw = GST_VIDEO_FRAME_WIDTH (src);
1162   gint sh = GST_VIDEO_FRAME_HEIGHT (src);
1163   gint dw = GST_VIDEO_FRAME_WIDTH (dest);
1164   gint dh = GST_VIDEO_FRAME_HEIGHT (dest);
1165   gint src_stride, dest_stride;
1166   gint bpp;
1167
1168   s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
1169   d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
1170
1171   src_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src, 0);
1172   dest_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest, 0);
1173   /* This is only true for non-subsampled formats! */
1174   bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (src, 0);
1175
1176   switch (videoflip->active_method) {
1177     case GST_VIDEO_ORIENTATION_90R:
1178       for (y = 0; y < dh; y++) {
1179         for (x = 0; x < dw; x++) {
1180           for (z = 0; z < bpp; z++) {
1181             d[y * dest_stride + x * bpp + z] =
1182                 s[(sh - 1 - x) * src_stride + y * bpp + z];
1183           }
1184         }
1185       }
1186       break;
1187     case GST_VIDEO_ORIENTATION_90L:
1188       for (y = 0; y < dh; y++) {
1189         for (x = 0; x < dw; x++) {
1190           for (z = 0; z < bpp; z++) {
1191             d[y * dest_stride + x * bpp + z] =
1192                 s[x * src_stride + (sw - 1 - y) * bpp + z];
1193           }
1194         }
1195       }
1196       break;
1197     case GST_VIDEO_ORIENTATION_180:
1198       for (y = 0; y < dh; y++) {
1199         for (x = 0; x < dw; x++) {
1200           for (z = 0; z < bpp; z++) {
1201             d[y * dest_stride + x * bpp + z] =
1202                 s[(sh - 1 - y) * src_stride + (sw - 1 - x) * bpp + z];
1203           }
1204         }
1205       }
1206       break;
1207     case GST_VIDEO_ORIENTATION_HORIZ:
1208       for (y = 0; y < dh; y++) {
1209         for (x = 0; x < dw; x++) {
1210           for (z = 0; z < bpp; z++) {
1211             d[y * dest_stride + x * bpp + z] =
1212                 s[y * src_stride + (sw - 1 - x) * bpp + z];
1213           }
1214         }
1215       }
1216       break;
1217     case GST_VIDEO_ORIENTATION_VERT:
1218       for (y = 0; y < dh; y++) {
1219         for (x = 0; x < dw; x++) {
1220           for (z = 0; z < bpp; z++) {
1221             d[y * dest_stride + x * bpp + z] =
1222                 s[(sh - 1 - y) * src_stride + x * bpp + z];
1223           }
1224         }
1225       }
1226       break;
1227     case GST_VIDEO_ORIENTATION_UL_LR:
1228       for (y = 0; y < dh; y++) {
1229         for (x = 0; x < dw; x++) {
1230           for (z = 0; z < bpp; z++) {
1231             d[y * dest_stride + x * bpp + z] = s[x * src_stride + y * bpp + z];
1232           }
1233         }
1234       }
1235       break;
1236     case GST_VIDEO_ORIENTATION_UR_LL:
1237       for (y = 0; y < dh; y++) {
1238         for (x = 0; x < dw; x++) {
1239           for (z = 0; z < bpp; z++) {
1240             d[y * dest_stride + x * bpp + z] =
1241                 s[(sh - 1 - x) * src_stride + (sw - 1 - y) * bpp + z];
1242           }
1243         }
1244       }
1245       break;
1246     case GST_VIDEO_ORIENTATION_IDENTITY:
1247       gst_video_frame_copy (dest, src);
1248       break;
1249     default:
1250       g_assert_not_reached ();
1251       break;
1252   }
1253 }
1254
1255 static void
1256 gst_video_flip_y422 (GstVideoFlip * videoflip, GstVideoFrame * dest,
1257     const GstVideoFrame * src)
1258 {
1259   gint x, y;
1260   guint8 const *s;
1261   guint8 *d;
1262   gint sw = GST_VIDEO_FRAME_WIDTH (src);
1263   gint sh = GST_VIDEO_FRAME_HEIGHT (src);
1264   gint dw = GST_VIDEO_FRAME_WIDTH (dest);
1265   gint dh = GST_VIDEO_FRAME_HEIGHT (dest);
1266   gint src_stride, dest_stride;
1267   gint bpp;
1268   gint y_offset;
1269   gint u_offset;
1270   gint v_offset;
1271   gint y_stride;
1272
1273   s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
1274   d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
1275
1276   src_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src, 0);
1277   dest_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest, 0);
1278
1279   y_offset = GST_VIDEO_FRAME_COMP_OFFSET (src, 0);
1280   u_offset = GST_VIDEO_FRAME_COMP_OFFSET (src, 1);
1281   v_offset = GST_VIDEO_FRAME_COMP_OFFSET (src, 2);
1282   y_stride = GST_VIDEO_FRAME_COMP_PSTRIDE (src, 0);
1283   bpp = y_stride;
1284
1285   switch (videoflip->active_method) {
1286     case GST_VIDEO_ORIENTATION_90R:
1287       for (y = 0; y < dh; y++) {
1288         for (x = 0; x < dw; x += 2) {
1289           guint8 u;
1290           guint8 v;
1291           /* u/v must be calculated using the offset of the even column */
1292           gint even_y = (y & ~1);
1293
1294           u = s[(sh - 1 - x) * src_stride + even_y * bpp + u_offset];
1295           if (x + 1 < dw)
1296             u = (s[(sh - 1 - (x + 1)) * src_stride + even_y * bpp + u_offset]
1297                 + u) >> 1;
1298           v = s[(sh - 1 - x) * src_stride + even_y * bpp + v_offset];
1299           if (x + 1 < dw)
1300             v = (s[(sh - 1 - (x + 1)) * src_stride + even_y * bpp + v_offset]
1301                 + v) >> 1;
1302
1303           d[y * dest_stride + x * bpp + u_offset] = u;
1304           d[y * dest_stride + x * bpp + v_offset] = v;
1305           d[y * dest_stride + x * bpp + y_offset] =
1306               s[(sh - 1 - x) * src_stride + y * bpp + y_offset];
1307           if (x + 1 < dw)
1308             d[y * dest_stride + (x + 1) * bpp + y_offset] =
1309                 s[(sh - 1 - (x + 1)) * src_stride + y * bpp + y_offset];
1310         }
1311       }
1312       break;
1313     case GST_VIDEO_ORIENTATION_90L:
1314       for (y = 0; y < dh; y++) {
1315         for (x = 0; x < dw; x += 2) {
1316           guint8 u;
1317           guint8 v;
1318           /* u/v must be calculated using the offset of the even column */
1319           gint even_y = ((sw - 1 - y) & ~1);
1320
1321           u = s[x * src_stride + even_y * bpp + u_offset];
1322           if (x + 1 < dw)
1323             u = (s[(x + 1) * src_stride + even_y * bpp + u_offset] + u) >> 1;
1324           v = s[x * src_stride + even_y * bpp + v_offset];
1325           if (x + 1 < dw)
1326             v = (s[(x + 1) * src_stride + even_y * bpp + v_offset] + v) >> 1;
1327
1328           d[y * dest_stride + x * bpp + u_offset] = u;
1329           d[y * dest_stride + x * bpp + v_offset] = v;
1330           d[y * dest_stride + x * bpp + y_offset] =
1331               s[x * src_stride + (sw - 1 - y) * bpp + y_offset];
1332           if (x + 1 < dw)
1333             d[y * dest_stride + (x + 1) * bpp + y_offset] =
1334                 s[(x + 1) * src_stride + (sw - 1 - y) * bpp + y_offset];
1335         }
1336       }
1337       break;
1338     case GST_VIDEO_ORIENTATION_180:
1339       for (y = 0; y < dh; y++) {
1340         for (x = 0; x < dw; x += 2) {
1341           guint8 u;
1342           guint8 v;
1343           /* u/v must be calculated using the offset of the even column */
1344           gint even_x = ((sw - 1 - x) & ~1);
1345
1346           u = (s[(sh - 1 - y) * src_stride + even_x * bpp + u_offset] +
1347               s[(sh - 1 - y) * src_stride + even_x * bpp + u_offset]) / 2;
1348           v = (s[(sh - 1 - y) * src_stride + even_x * bpp + v_offset] +
1349               s[(sh - 1 - y) * src_stride + even_x * bpp + v_offset]) / 2;
1350
1351           d[y * dest_stride + x * bpp + u_offset] = u;
1352           d[y * dest_stride + x * bpp + v_offset] = v;
1353           d[y * dest_stride + x * bpp + y_offset] =
1354               s[(sh - 1 - y) * src_stride + (sw - 1 - x) * bpp + y_offset];
1355           if (x + 1 < dw)
1356             d[y * dest_stride + (x + 1) * bpp + y_offset] =
1357                 s[(sh - 1 - y) * src_stride + (sw - 1 - (x + 1)) * bpp +
1358                 y_offset];
1359         }
1360       }
1361       break;
1362     case GST_VIDEO_ORIENTATION_HORIZ:
1363       for (y = 0; y < dh; y++) {
1364         for (x = 0; x < dw; x += 2) {
1365           guint8 u;
1366           guint8 v;
1367           /* u/v must be calculated using the offset of the even column */
1368           gint even_x = ((sw - 1 - x) & ~1);
1369
1370           u = (s[y * src_stride + even_x * bpp + u_offset] +
1371               s[y * src_stride + even_x * bpp + u_offset]) / 2;
1372           v = (s[y * src_stride + even_x * bpp + v_offset] +
1373               s[y * src_stride + even_x * bpp + v_offset]) / 2;
1374
1375           d[y * dest_stride + x * bpp + u_offset] = u;
1376           d[y * dest_stride + x * bpp + v_offset] = v;
1377           d[y * dest_stride + x * bpp + y_offset] =
1378               s[y * src_stride + (sw - 1 - x) * bpp + y_offset];
1379           if (x + 1 < dw)
1380             d[y * dest_stride + (x + 1) * bpp + y_offset] =
1381                 s[y * src_stride + (sw - 1 - (x + 1)) * bpp + y_offset];
1382         }
1383       }
1384       break;
1385     case GST_VIDEO_ORIENTATION_VERT:
1386       for (y = 0; y < dh; y++) {
1387         for (x = 0; x < dw; x += 2) {
1388           guint8 u;
1389           guint8 v;
1390           /* u/v must be calculated using the offset of the even column */
1391           gint even_x = (x & ~1);
1392
1393           u = (s[(sh - 1 - y) * src_stride + even_x * bpp + u_offset] +
1394               s[(sh - 1 - y) * src_stride + even_x * bpp + u_offset]) / 2;
1395           v = (s[(sh - 1 - y) * src_stride + even_x * bpp + v_offset] +
1396               s[(sh - 1 - y) * src_stride + even_x * bpp + v_offset]) / 2;
1397
1398           d[y * dest_stride + x * bpp + u_offset] = u;
1399           d[y * dest_stride + x * bpp + v_offset] = v;
1400           d[y * dest_stride + x * bpp + y_offset] =
1401               s[(sh - 1 - y) * src_stride + x * bpp + y_offset];
1402           if (x + 1 < dw)
1403             d[y * dest_stride + (x + 1) * bpp + y_offset] =
1404                 s[(sh - 1 - y) * src_stride + (x + 1) * bpp + y_offset];
1405         }
1406       }
1407       break;
1408     case GST_VIDEO_ORIENTATION_UL_LR:
1409       for (y = 0; y < dh; y++) {
1410         for (x = 0; x < dw; x += 2) {
1411           guint8 u;
1412           guint8 v;
1413           /* u/v must be calculated using the offset of the even column */
1414           gint even_y = (y & ~1);
1415
1416           u = s[x * src_stride + even_y * bpp + u_offset];
1417           if (x + 1 < dw)
1418             u = (s[(x + 1) * src_stride + even_y * bpp + u_offset] + u) >> 1;
1419           v = s[x * src_stride + even_y * bpp + v_offset];
1420           if (x + 1 < dw)
1421             v = (s[(x + 1) * src_stride + even_y * bpp + v_offset] + v) >> 1;
1422
1423           d[y * dest_stride + x * bpp + u_offset] = u;
1424           d[y * dest_stride + x * bpp + v_offset] = v;
1425           d[y * dest_stride + x * bpp + y_offset] =
1426               s[x * src_stride + y * bpp + y_offset];
1427           if (x + 1 < dw)
1428             d[y * dest_stride + (x + 1) * bpp + y_offset] =
1429                 s[(x + 1) * src_stride + y * bpp + y_offset];
1430         }
1431       }
1432       break;
1433     case GST_VIDEO_ORIENTATION_UR_LL:
1434       for (y = 0; y < dh; y++) {
1435         for (x = 0; x < dw; x += 2) {
1436           guint8 u;
1437           guint8 v;
1438           /* u/v must be calculated using the offset of the even column */
1439           gint even_y = ((sw - 1 - y) & ~1);
1440
1441           u = s[(sh - 1 - x) * src_stride + even_y * bpp + u_offset];
1442           if (x + 1 < dw)
1443             u = (s[(sh - 1 - (x + 1)) * src_stride + even_y * bpp + u_offset]
1444                 + u) >> 1;
1445           v = s[(sh - 1 - x) * src_stride + even_y * bpp + v_offset];
1446           if (x + 1 < dw)
1447             v = (s[(sh - 1 - (x + 1)) * src_stride + even_y * bpp + v_offset]
1448                 + v) >> 1;
1449
1450           d[y * dest_stride + x * bpp + u_offset] = u;
1451           d[y * dest_stride + x * bpp + v_offset] = v;
1452           d[y * dest_stride + x * bpp + y_offset] =
1453               s[(sh - 1 - x) * src_stride + (sw - 1 - y) * bpp + y_offset];
1454           if (x + 1 < dw)
1455             d[y * dest_stride + (x + 1) * bpp + y_offset] =
1456                 s[(sh - 1 - (x + 1)) * src_stride + (sw - 1 - y) * bpp +
1457                 y_offset];
1458         }
1459       }
1460       break;
1461     case GST_VIDEO_ORIENTATION_IDENTITY:
1462       gst_video_frame_copy (dest, src);
1463       break;
1464     default:
1465       g_assert_not_reached ();
1466       break;
1467   }
1468 }
1469
1470 static void
1471 gst_video_flip_configure_process (GstVideoFlip * vf)
1472 {
1473   switch (vf->v_format) {
1474     case GST_VIDEO_FORMAT_I420:
1475     case GST_VIDEO_FORMAT_YV12:
1476     case GST_VIDEO_FORMAT_Y444:
1477       vf->process = gst_video_flip_planar_yuv;
1478       break;
1479     case GST_VIDEO_FORMAT_I420_10LE:
1480     case GST_VIDEO_FORMAT_I420_10BE:
1481     case GST_VIDEO_FORMAT_I420_12LE:
1482     case GST_VIDEO_FORMAT_I420_12BE:
1483     case GST_VIDEO_FORMAT_Y444_10LE:
1484     case GST_VIDEO_FORMAT_Y444_10BE:
1485     case GST_VIDEO_FORMAT_Y444_12LE:
1486     case GST_VIDEO_FORMAT_Y444_12BE:
1487       vf->process = gst_video_flip_planar_yuv_16bit;
1488       break;
1489     case GST_VIDEO_FORMAT_I422_10LE:
1490     case GST_VIDEO_FORMAT_I422_10BE:
1491     case GST_VIDEO_FORMAT_I422_12LE:
1492     case GST_VIDEO_FORMAT_I422_12BE:
1493       vf->process = gst_video_flip_planar_yuv_422_16bit;
1494       break;
1495     case GST_VIDEO_FORMAT_YUY2:
1496     case GST_VIDEO_FORMAT_UYVY:
1497     case GST_VIDEO_FORMAT_YVYU:
1498       vf->process = gst_video_flip_y422;
1499       break;
1500     case GST_VIDEO_FORMAT_AYUV:
1501     case GST_VIDEO_FORMAT_ARGB:
1502     case GST_VIDEO_FORMAT_ABGR:
1503     case GST_VIDEO_FORMAT_RGBA:
1504     case GST_VIDEO_FORMAT_BGRA:
1505     case GST_VIDEO_FORMAT_xRGB:
1506     case GST_VIDEO_FORMAT_xBGR:
1507     case GST_VIDEO_FORMAT_RGBx:
1508     case GST_VIDEO_FORMAT_BGRx:
1509     case GST_VIDEO_FORMAT_RGB:
1510     case GST_VIDEO_FORMAT_BGR:
1511     case GST_VIDEO_FORMAT_GRAY8:
1512     case GST_VIDEO_FORMAT_GRAY16_BE:
1513     case GST_VIDEO_FORMAT_GRAY16_LE:
1514       vf->process = gst_video_flip_packed_simple;
1515       break;
1516     case GST_VIDEO_FORMAT_NV12:
1517     case GST_VIDEO_FORMAT_NV21:
1518 #ifdef TIZEN_FEATURE_VIDEOFLIP_TBM_SUPPORT
1519     case GST_VIDEO_FORMAT_SN12:
1520 #endif
1521       vf->process = gst_video_flip_semi_planar_yuv;
1522       break;
1523     default:
1524       break;
1525   }
1526 }
1527
1528 static gboolean
1529 gst_video_flip_set_info (GstVideoFilter * vfilter, GstCaps * incaps,
1530     GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info)
1531 {
1532   GstVideoFlip *vf = GST_VIDEO_FLIP (vfilter);
1533   gboolean ret = FALSE, need_reconfigure = FALSE;
1534
1535   vf->process = NULL;
1536
1537   if (GST_VIDEO_INFO_FORMAT (in_info) != GST_VIDEO_INFO_FORMAT (out_info))
1538     goto invalid_caps;
1539
1540   /* Check that they are correct */
1541   GST_OBJECT_LOCK (vf);
1542   switch (vf->configuring_method) {
1543     case GST_VIDEO_ORIENTATION_90R:
1544     case GST_VIDEO_ORIENTATION_90L:
1545     case GST_VIDEO_ORIENTATION_UL_LR:
1546     case GST_VIDEO_ORIENTATION_UR_LL:
1547       if ((in_info->width != out_info->height) ||
1548           (in_info->height != out_info->width)) {
1549         GST_ERROR_OBJECT (vf, "we are inverting width and height but caps "
1550             "are not correct : %dx%d to %dx%d", in_info->width,
1551             in_info->height, out_info->width, out_info->height);
1552         goto beach;
1553       }
1554       break;
1555     case GST_VIDEO_ORIENTATION_IDENTITY:
1556     case GST_VIDEO_ORIENTATION_180:
1557     case GST_VIDEO_ORIENTATION_HORIZ:
1558     case GST_VIDEO_ORIENTATION_VERT:
1559       if ((in_info->width != out_info->width) ||
1560           (in_info->height != out_info->height)) {
1561         GST_ERROR_OBJECT (vf, "we are keeping width and height but caps "
1562             "are not correct : %dx%d to %dx%d", in_info->width,
1563             in_info->height, out_info->width, out_info->height);
1564         goto beach;
1565       }
1566       break;
1567     default:
1568       g_assert_not_reached ();
1569       break;
1570   }
1571
1572   ret = TRUE;
1573
1574   {
1575     GEnumValue *active_method_enum, *method_enum;
1576     GEnumClass *enum_class =
1577         g_type_class_ref (GST_TYPE_VIDEO_ORIENTATION_METHOD);
1578
1579     active_method_enum = g_enum_get_value (enum_class, vf->active_method);
1580     method_enum = g_enum_get_value (enum_class, vf->configuring_method);
1581     GST_LOG_OBJECT (vf, "Changing active method from %s to configuring %s",
1582         active_method_enum ? active_method_enum->value_nick : "(nil)",
1583         method_enum ? method_enum->value_nick : "(nil)");
1584     g_type_class_unref (enum_class);
1585   }
1586   vf->active_method = vf->configuring_method;
1587   vf->change_configuring_method = TRUE;
1588   if (vf->active_method != vf->proposed_method)
1589     need_reconfigure = TRUE;
1590
1591   vf->v_format = GST_VIDEO_INFO_FORMAT (in_info);
1592   gst_video_flip_configure_process (vf);
1593
1594 beach:
1595   GST_OBJECT_UNLOCK (vf);
1596   if (need_reconfigure) {
1597     gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM (vf));
1598   }
1599
1600   return ret && (vf->process != NULL);
1601
1602 invalid_caps:
1603   GST_ERROR_OBJECT (vf, "Invalid caps: %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT,
1604       incaps, outcaps);
1605   return FALSE;
1606 }
1607
1608 static void
1609 gst_video_flip_set_method (GstVideoFlip * videoflip,
1610     GstVideoOrientationMethod method, gboolean from_tag)
1611 {
1612   GST_OBJECT_LOCK (videoflip);
1613
1614   if (method == GST_VIDEO_ORIENTATION_CUSTOM) {
1615     GST_WARNING_OBJECT (videoflip, "unsupported custom orientation");
1616     GST_OBJECT_UNLOCK (videoflip);
1617     return;
1618   }
1619
1620   /* Store updated method */
1621   if (from_tag)
1622     videoflip->tag_method = method;
1623   else
1624     videoflip->method = method;
1625
1626   /* Get the new method */
1627   if (videoflip->method == GST_VIDEO_ORIENTATION_AUTO)
1628     method = videoflip->tag_method;
1629   else
1630     method = videoflip->method;
1631
1632   if (method != videoflip->proposed_method) {
1633     GEnumValue *active_method_enum, *method_enum;
1634     GstBaseTransform *btrans = GST_BASE_TRANSFORM (videoflip);
1635     GEnumClass *enum_class =
1636         g_type_class_ref (GST_TYPE_VIDEO_ORIENTATION_METHOD);
1637
1638     active_method_enum =
1639         g_enum_get_value (enum_class, videoflip->active_method);
1640     method_enum = g_enum_get_value (enum_class, method);
1641     GST_LOG_OBJECT (videoflip, "Changing method from %s to %s",
1642         active_method_enum ? active_method_enum->value_nick : "(nil)",
1643         method_enum ? method_enum->value_nick : "(nil)");
1644     g_type_class_unref (enum_class);
1645
1646     videoflip->proposed_method = method;
1647     videoflip->change_configuring_method = TRUE;
1648
1649     GST_OBJECT_UNLOCK (videoflip);
1650
1651     gst_base_transform_set_passthrough (btrans,
1652         method == GST_VIDEO_ORIENTATION_IDENTITY);
1653     gst_base_transform_reconfigure_src (btrans);
1654   } else {
1655     GST_OBJECT_UNLOCK (videoflip);
1656   }
1657 }
1658
1659 static void
1660 gst_video_flip_before_transform (GstBaseTransform * trans, GstBuffer * in)
1661 {
1662   GstVideoFlip *videoflip = GST_VIDEO_FLIP (trans);
1663   GstClockTime timestamp, stream_time;
1664
1665   timestamp = GST_BUFFER_TIMESTAMP (in);
1666   stream_time =
1667       gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME, timestamp);
1668
1669   GST_DEBUG_OBJECT (videoflip, "sync to %" GST_TIME_FORMAT,
1670       GST_TIME_ARGS (timestamp));
1671
1672   if (GST_CLOCK_TIME_IS_VALID (stream_time))
1673     gst_object_sync_values (GST_OBJECT (videoflip), stream_time);
1674 }
1675
1676 static GstFlowReturn
1677 gst_video_flip_transform_frame (GstVideoFilter * vfilter,
1678     GstVideoFrame * in_frame, GstVideoFrame * out_frame)
1679 {
1680   GEnumClass *enum_class;
1681   GstVideoOrientationMethod active, proposed;
1682   GEnumValue *active_method_enum;
1683   GstVideoFlip *videoflip = GST_VIDEO_FLIP (vfilter);
1684
1685   GST_OBJECT_LOCK (videoflip);
1686   if (G_UNLIKELY (videoflip->process == NULL))
1687     goto not_negotiated;
1688
1689   if (videoflip->configuring_method != videoflip->active_method) {
1690     videoflip->active_method = videoflip->configuring_method;
1691     gst_video_flip_configure_process (videoflip);
1692   }
1693
1694   enum_class = g_type_class_ref (GST_TYPE_VIDEO_ORIENTATION_METHOD);
1695   active_method_enum = g_enum_get_value (enum_class, videoflip->active_method);
1696   GST_LOG_OBJECT (videoflip,
1697       "videoflip: flipping (%s), input %ux%u output %ux%u",
1698       active_method_enum ? active_method_enum->value_nick : "(nil)",
1699       GST_VIDEO_FRAME_WIDTH (in_frame), GST_VIDEO_FRAME_HEIGHT (in_frame),
1700       GST_VIDEO_FRAME_WIDTH (out_frame), GST_VIDEO_FRAME_HEIGHT (out_frame));
1701   g_type_class_unref (enum_class);
1702
1703   videoflip->process (videoflip, out_frame, in_frame);
1704
1705   proposed = videoflip->proposed_method;
1706   active = videoflip->active_method;
1707   videoflip->change_configuring_method = TRUE;
1708   GST_OBJECT_UNLOCK (videoflip);
1709
1710   if (proposed != active) {
1711     gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (videoflip),
1712         proposed == GST_VIDEO_ORIENTATION_IDENTITY);
1713     gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM (videoflip));
1714   }
1715
1716   return GST_FLOW_OK;
1717
1718 not_negotiated:
1719   {
1720     GST_OBJECT_UNLOCK (videoflip);
1721     GST_ERROR_OBJECT (videoflip, "Not negotiated yet");
1722     return GST_FLOW_NOT_NEGOTIATED;
1723   }
1724 }
1725
1726 static gboolean
1727 gst_video_flip_src_event (GstBaseTransform * trans, GstEvent * event)
1728 {
1729   GstVideoFlip *vf = GST_VIDEO_FLIP (trans);
1730   gdouble new_x, new_y, x, y;
1731   gboolean ret;
1732   GstVideoInfo *out_info = &GST_VIDEO_FILTER (trans)->out_info;
1733
1734   GST_DEBUG_OBJECT (vf, "handling %s event", GST_EVENT_TYPE_NAME (event));
1735
1736   switch (GST_EVENT_TYPE (event)) {
1737     case GST_EVENT_NAVIGATION:
1738       event = gst_event_make_writable (event);
1739
1740       if (gst_navigation_event_get_coordinates (event, &x, &y)) {
1741         GST_DEBUG_OBJECT (vf, "converting %fx%f", x, y);
1742         GST_OBJECT_LOCK (vf);
1743         switch (vf->active_method) {
1744           case GST_VIDEO_ORIENTATION_90R:
1745             new_x = y;
1746             new_y = out_info->width - x;
1747             break;
1748           case GST_VIDEO_ORIENTATION_90L:
1749             new_x = out_info->height - y;
1750             new_y = x;
1751             break;
1752           case GST_VIDEO_ORIENTATION_UR_LL:
1753             new_x = out_info->height - y;
1754             new_y = out_info->width - x;
1755             break;
1756           case GST_VIDEO_ORIENTATION_UL_LR:
1757             new_x = y;
1758             new_y = x;
1759             break;
1760           case GST_VIDEO_ORIENTATION_180:
1761             new_x = out_info->width - x;
1762             new_y = out_info->height - y;
1763             break;
1764           case GST_VIDEO_ORIENTATION_HORIZ:
1765             new_x = out_info->width - x;
1766             new_y = y;
1767             break;
1768           case GST_VIDEO_ORIENTATION_VERT:
1769             new_x = x;
1770             new_y = out_info->height - y;
1771             break;
1772           default:
1773             new_x = x;
1774             new_y = y;
1775             break;
1776         }
1777         GST_OBJECT_UNLOCK (vf);
1778         GST_DEBUG_OBJECT (vf, "to %fx%f", new_x, new_y);
1779         gst_navigation_event_set_coordinates (event, new_x, new_y);
1780       }
1781       break;
1782     default:
1783       break;
1784   }
1785
1786   ret = GST_BASE_TRANSFORM_CLASS (parent_class)->src_event (trans, event);
1787
1788   return ret;
1789 }
1790
1791 static gboolean
1792 gst_video_flip_sink_event (GstBaseTransform * trans, GstEvent * event)
1793 {
1794   GstVideoFlip *vf = GST_VIDEO_FLIP (trans);
1795   GstTagList *taglist;
1796   GstVideoOrientationMethod method;
1797   gboolean ret;
1798
1799   GST_DEBUG_OBJECT (vf, "handling %s event", GST_EVENT_TYPE_NAME (event));
1800
1801   switch (GST_EVENT_TYPE (event)) {
1802     case GST_EVENT_TAG:
1803       gst_event_parse_tag (event, &taglist);
1804
1805       if (gst_video_orientation_from_tag (taglist, &method)) {
1806         gst_video_flip_set_method (vf, method, TRUE);
1807       }
1808       break;
1809     default:
1810       break;
1811   }
1812
1813   ret = GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
1814
1815   return ret;
1816 }
1817
1818 static void
1819 gst_video_flip_set_property (GObject * object, guint prop_id,
1820     const GValue * value, GParamSpec * pspec)
1821 {
1822   GstVideoFlip *videoflip = GST_VIDEO_FLIP (object);
1823
1824   switch (prop_id) {
1825     case PROP_METHOD:
1826     case PROP_VIDEO_DIRECTION:
1827       gst_video_flip_set_method (videoflip, g_value_get_enum (value), FALSE);
1828       break;
1829     default:
1830       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1831       break;
1832   }
1833 }
1834
1835 static void
1836 gst_video_flip_get_property (GObject * object, guint prop_id, GValue * value,
1837     GParamSpec * pspec)
1838 {
1839   GstVideoFlip *videoflip = GST_VIDEO_FLIP (object);
1840
1841   switch (prop_id) {
1842     case PROP_METHOD:
1843     case PROP_VIDEO_DIRECTION:
1844       g_value_set_enum (value, videoflip->method);
1845       break;
1846     default:
1847       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1848       break;
1849   }
1850 }
1851
1852 #ifdef TIZEN_FEATURE_VIDEOFLIP_TBM_SUPPORT
1853 static gboolean
1854 gst_video_flip_decide_allocation (GstBaseTransform * trans,
1855     GstQuery * query)
1856 {
1857   GstVideoFlip *videoflip = GST_VIDEO_FLIP (trans);
1858   GstVideoFilter *filter = GST_VIDEO_FILTER_CAST (trans);
1859
1860   GST_WARNING_OBJECT (videoflip, "format[%s]", filter->out_info.finfo->name);
1861
1862   if (filter->out_info.finfo->format == GST_VIDEO_FORMAT_SN12) {
1863     guint size;
1864     GstStructure *config;
1865     GstCaps *caps = NULL;
1866     GstVideoInfo vinfo;
1867
1868     gst_query_parse_allocation (query, &caps, NULL);
1869     if (!caps) {
1870       GST_WARNING_OBJECT (videoflip, "caps failed");
1871       return FALSE;
1872     }
1873
1874     gst_video_info_init (&vinfo);
1875     gst_video_info_from_caps (&vinfo, caps);
1876
1877     size = vinfo.size;
1878
1879     videoflip->pool = gst_tizen_buffer_pool_new ();
1880     config = gst_buffer_pool_get_config (videoflip->pool);
1881
1882     gst_buffer_pool_config_set_params (config, caps, size,
1883       TIZEN_BUFFER_POOL_MIN_BUFFERS, TIZEN_BUFFER_POOL_MAX_BUFFERS);
1884     gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
1885     gst_buffer_pool_set_config (videoflip->pool, config);
1886
1887     if (!gst_buffer_pool_set_active (videoflip->pool, TRUE)) {
1888       gst_object_unref (videoflip->pool);
1889       videoflip->pool = NULL;
1890       GST_WARNING_OBJECT (videoflip, "Failed to activate pool");
1891       return FALSE;
1892     }
1893
1894     GST_WARNING_OBJECT (videoflip, "new buffer pool[%p]", videoflip->pool);
1895   }
1896
1897   return GST_BASE_TRANSFORM_CLASS (parent_class)->decide_allocation (trans, query);
1898 }
1899
1900 static GstFlowReturn
1901 gst_video_flip_prepare_output_buffer (GstBaseTransform * trans,
1902     GstBuffer *input, GstBuffer **outbuf)
1903 {
1904   GstVideoFlip *videoflip = GST_VIDEO_FLIP (trans);
1905   GstBuffer *buf = NULL;
1906
1907   if (!videoflip->pool)
1908     return GST_BASE_TRANSFORM_CLASS (parent_class)->prepare_output_buffer (trans, input, outbuf);
1909
1910   if (gst_buffer_pool_acquire_buffer (videoflip->pool, &buf, 0) != GST_FLOW_OK) {
1911     GST_ERROR_OBJECT (trans, "Buffer acquire failed");
1912     return GST_FLOW_ERROR;
1913   }
1914
1915   GST_DEBUG_OBJECT (videoflip, "acquired buffer[%p]", buf);
1916
1917   if (input != buf)
1918     GST_BASE_TRANSFORM_CLASS (parent_class)->copy_metadata (trans, input, buf);
1919
1920   *outbuf = buf;
1921
1922   return GST_FLOW_OK;
1923 }
1924
1925 static void
1926 gst_video_flip_finalize (GstVideoFlip * videoflip)
1927 {
1928   if (videoflip->pool) {
1929     GST_WARNING_OBJECT (videoflip, "free buffer pool[%p]", videoflip->pool);
1930     gst_buffer_pool_set_active (videoflip->pool, FALSE);
1931     gst_object_unref (videoflip->pool);
1932     videoflip->pool = NULL;
1933   }
1934
1935   G_OBJECT_CLASS (parent_class)->finalize (G_OBJECT (videoflip));
1936 }
1937 #endif
1938
1939 static void
1940 gst_video_flip_class_init (GstVideoFlipClass * klass)
1941 {
1942   GObjectClass *gobject_class = (GObjectClass *) klass;
1943   GstElementClass *gstelement_class = (GstElementClass *) klass;
1944   GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass;
1945   GstVideoFilterClass *vfilter_class = (GstVideoFilterClass *) klass;
1946   GParamSpec *pspec;
1947
1948   GST_DEBUG_CATEGORY_INIT (video_flip_debug, "videoflip", 0, "videoflip");
1949
1950   gobject_class->set_property = gst_video_flip_set_property;
1951   gobject_class->get_property = gst_video_flip_get_property;
1952
1953   g_object_class_install_property (gobject_class, PROP_METHOD,
1954       g_param_spec_enum ("method", "method",
1955           "method (deprecated, use video-direction instead)",
1956           GST_TYPE_VIDEO_FLIP_METHOD, PROP_METHOD_DEFAULT,
1957           GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING |
1958           G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
1959   g_object_class_override_property (gobject_class, PROP_VIDEO_DIRECTION,
1960       "video-direction");
1961   /* override the overriden property's flags to include the mutable in playing
1962    * flag */
1963   pspec = g_object_class_find_property (gobject_class, "video-direction");
1964   pspec->flags |= GST_PARAM_MUTABLE_PLAYING;
1965
1966   gst_element_class_set_static_metadata (gstelement_class, "Video flipper",
1967       "Filter/Effect/Video",
1968       "Flips and rotates video", "David Schleef <ds@schleef.org>");
1969
1970   gst_element_class_add_static_pad_template (gstelement_class,
1971       &gst_video_flip_sink_template);
1972   gst_element_class_add_static_pad_template (gstelement_class,
1973       &gst_video_flip_src_template);
1974
1975   trans_class->transform_caps =
1976       GST_DEBUG_FUNCPTR (gst_video_flip_transform_caps);
1977   trans_class->before_transform =
1978       GST_DEBUG_FUNCPTR (gst_video_flip_before_transform);
1979   trans_class->src_event = GST_DEBUG_FUNCPTR (gst_video_flip_src_event);
1980   trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_video_flip_sink_event);
1981
1982   vfilter_class->set_info = GST_DEBUG_FUNCPTR (gst_video_flip_set_info);
1983   vfilter_class->transform_frame =
1984       GST_DEBUG_FUNCPTR (gst_video_flip_transform_frame);
1985 #ifdef TIZEN_FEATURE_VIDEOFLIP_TBM_SUPPORT
1986   trans_class->decide_allocation = gst_video_flip_decide_allocation;
1987   trans_class->prepare_output_buffer = gst_video_flip_prepare_output_buffer;
1988   gobject_class->finalize = gst_video_flip_finalize;
1989 #endif
1990
1991   gst_type_mark_as_plugin_api (GST_TYPE_VIDEO_FLIP_METHOD, 0);
1992 }
1993
1994 static void
1995 gst_video_flip_init (GstVideoFlip * videoflip)
1996 {
1997   /* AUTO is not valid for active method, this is just to ensure we setup the
1998    * method in gst_video_flip_set_method() */
1999   videoflip->active_method = GST_VIDEO_ORIENTATION_AUTO;
2000   videoflip->proposed_method = GST_VIDEO_ORIENTATION_IDENTITY;
2001   videoflip->configuring_method = GST_VIDEO_ORIENTATION_IDENTITY;
2002 }