videooverlaycomposition: add some _get_argb and _get_ayuv functions
[platform/upstream/gstreamer.git] / tests / check / libs / video.c
1 /* GStreamer unit test for video
2  *
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Jan Schmidt <thaytan@mad.scientist.com>
5  * Copyright (C) <2008,2011> Tim-Philipp Müller <tim centricular net>
6  * Copyright (C) <2012> Collabora Ltd. <tim.muller@collabora.co.uk>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #ifdef HAVE_VALGRIND
29 # include <valgrind/valgrind.h>
30 #endif
31
32 #include <unistd.h>
33
34 #include <gst/check/gstcheck.h>
35
36 #include <gst/video/video.h>
37 #include <gst/video/gstvideometa.h>
38 #include <gst/video/video-overlay-composition.h>
39 #include <string.h>
40
41 /* These are from the current/old videotestsrc; we check our new public API
42  * in libgstvideo against the old one to make sure the sizes and offsets
43  * end up the same */
44
45 typedef struct paintinfo_struct paintinfo;
46 struct paintinfo_struct
47 {
48   unsigned char *dest;          /* pointer to first byte of video data */
49   unsigned char *yp, *up, *vp;  /* pointers to first byte of each component
50                                  * for both packed/planar YUV and RGB */
51   unsigned char *ap;            /* pointer to first byte of alpha component */
52   unsigned char *endptr;        /* pointer to byte beyond last video data */
53   int ystride;
54   int ustride;
55   int vstride;
56   int width;
57   int height;
58 };
59
60 struct fourcc_list_struct
61 {
62   const char *fourcc;
63   const char *name;
64   int bitspp;
65   void (*paint_setup) (paintinfo * p, unsigned char *dest);
66 };
67
68 static void paint_setup_I420 (paintinfo * p, unsigned char *dest);
69 static void paint_setup_YV12 (paintinfo * p, unsigned char *dest);
70 static void paint_setup_YUY2 (paintinfo * p, unsigned char *dest);
71 static void paint_setup_UYVY (paintinfo * p, unsigned char *dest);
72 static void paint_setup_YVYU (paintinfo * p, unsigned char *dest);
73 static void paint_setup_IYU2 (paintinfo * p, unsigned char *dest);
74 static void paint_setup_Y41B (paintinfo * p, unsigned char *dest);
75 static void paint_setup_Y42B (paintinfo * p, unsigned char *dest);
76 static void paint_setup_GRAY8 (paintinfo * p, unsigned char *dest);
77 static void paint_setup_AYUV (paintinfo * p, unsigned char *dest);
78
79 #if 0
80 static void paint_setup_IMC1 (paintinfo * p, unsigned char *dest);
81 static void paint_setup_IMC2 (paintinfo * p, unsigned char *dest);
82 static void paint_setup_IMC3 (paintinfo * p, unsigned char *dest);
83 static void paint_setup_IMC4 (paintinfo * p, unsigned char *dest);
84 #endif
85 static void paint_setup_YUV9 (paintinfo * p, unsigned char *dest);
86 static void paint_setup_YVU9 (paintinfo * p, unsigned char *dest);
87
88 int fourcc_get_size (struct fourcc_list_struct *fourcc, int w, int h);
89
90 struct fourcc_list_struct fourcc_list[] = {
91 /* packed */
92   {"YUY2", "YUY2", 16, paint_setup_YUY2},
93   {"UYVY", "UYVY", 16, paint_setup_UYVY},
94   {"Y422", "Y422", 16, paint_setup_UYVY},
95   {"UYNV", "UYNV", 16, paint_setup_UYVY},       /* FIXME: UYNV? */
96   {"YVYU", "YVYU", 16, paint_setup_YVYU},
97   {"AYUV", "AYUV", 32, paint_setup_AYUV},
98
99   /* interlaced */
100   /*{   "IUYV", "IUY2", 16, paint_setup_YVYU }, */
101
102   /* inverted */
103   /*{   "cyuv", "cyuv", 16, paint_setup_YVYU }, */
104
105   /*{   "Y41P", "Y41P", 12, paint_setup_YVYU }, */
106
107   /* interlaced */
108   /*{   "IY41", "IY41", 12, paint_setup_YVYU }, */
109
110   /*{   "Y211", "Y211", 8, paint_setup_YVYU }, */
111
112   /*{   "Y41T", "Y41T", 12, paint_setup_YVYU }, */
113   /*{   "Y42P", "Y42P", 16, paint_setup_YVYU }, */
114   /*{   "CLJR", "CLJR", 8, paint_setup_YVYU }, */
115   /*{   "IYU1", "IYU1", 12, paint_setup_YVYU }, */
116   {"IYU2", "IYU2", 24, paint_setup_IYU2},
117
118 /* planar */
119   /* YVU9 */
120   {"YVU9", "YVU9", 9, paint_setup_YVU9},
121   /* YUV9 */
122   {"YUV9", "YUV9", 9, paint_setup_YUV9},
123   /* IF09 */
124   /* YV12 */
125   {"YV12", "YV12", 12, paint_setup_YV12},
126   /* I420 */
127   {"I420", "I420", 12, paint_setup_I420},
128   /* NV12 */
129   /* NV21 */
130 #if 0
131   /* IMC1 */
132   {"IMC1", "IMC1", 16, paint_setup_IMC1},
133   /* IMC2 */
134   {"IMC2", "IMC2", 12, paint_setup_IMC2},
135   /* IMC3 */
136   {"IMC3", "IMC3", 16, paint_setup_IMC3},
137   /* IMC4 */
138   {"IMC4", "IMC4", 12, paint_setup_IMC4},
139 #endif
140   /* CLPL */
141   /* Y41B */
142   {"Y41B", "Y41B", 12, paint_setup_Y41B},
143   /* Y42B */
144   {"Y42B", "Y42B", 16, paint_setup_Y42B},
145   /* GRAY8 grayscale */
146   {"GRAY8", "GRAY8", 8, paint_setup_GRAY8}
147 };
148
149 /* returns the size in bytes for one video frame of the given dimensions
150  * given the fourcc */
151 int
152 fourcc_get_size (struct fourcc_list_struct *fourcc, int w, int h)
153 {
154   paintinfo pi = { NULL, };
155   paintinfo *p = &pi;
156
157   p->width = w;
158   p->height = h;
159
160   fourcc->paint_setup (p, NULL);
161
162   return (unsigned long) p->endptr;
163 }
164
165 static void
166 paint_setup_I420 (paintinfo * p, unsigned char *dest)
167 {
168   p->yp = dest;
169   p->ystride = GST_ROUND_UP_4 (p->width);
170   p->up = p->yp + p->ystride * GST_ROUND_UP_2 (p->height);
171   p->ustride = GST_ROUND_UP_8 (p->width) / 2;
172   p->vp = p->up + p->ustride * GST_ROUND_UP_2 (p->height) / 2;
173   p->vstride = GST_ROUND_UP_8 (p->ystride) / 2;
174   p->endptr = p->vp + p->vstride * GST_ROUND_UP_2 (p->height) / 2;
175 }
176
177 static void
178 paint_setup_YV12 (paintinfo * p, unsigned char *dest)
179 {
180   p->yp = dest;
181   p->ystride = GST_ROUND_UP_4 (p->width);
182   p->vp = p->yp + p->ystride * GST_ROUND_UP_2 (p->height);
183   p->vstride = GST_ROUND_UP_8 (p->ystride) / 2;
184   p->up = p->vp + p->vstride * GST_ROUND_UP_2 (p->height) / 2;
185   p->ustride = GST_ROUND_UP_8 (p->ystride) / 2;
186   p->endptr = p->up + p->ustride * GST_ROUND_UP_2 (p->height) / 2;
187 }
188
189 static void
190 paint_setup_AYUV (paintinfo * p, unsigned char *dest)
191 {
192   p->ap = dest;
193   p->yp = dest + 1;
194   p->up = dest + 2;
195   p->vp = dest + 3;
196   p->ystride = p->width * 4;
197   p->endptr = dest + p->ystride * p->height;
198 }
199
200 static void
201 paint_setup_YUY2 (paintinfo * p, unsigned char *dest)
202 {
203   p->yp = dest;
204   p->up = dest + 1;
205   p->vp = dest + 3;
206   p->ystride = GST_ROUND_UP_2 (p->width) * 2;
207   p->endptr = dest + p->ystride * p->height;
208 }
209
210 static void
211 paint_setup_UYVY (paintinfo * p, unsigned char *dest)
212 {
213   p->yp = dest + 1;
214   p->up = dest;
215   p->vp = dest + 2;
216   p->ystride = GST_ROUND_UP_2 (p->width) * 2;
217   p->endptr = dest + p->ystride * p->height;
218 }
219
220 static void
221 paint_setup_YVYU (paintinfo * p, unsigned char *dest)
222 {
223   p->yp = dest;
224   p->up = dest + 3;
225   p->vp = dest + 1;
226   p->ystride = GST_ROUND_UP_2 (p->width) * 2;
227   p->endptr = dest + p->ystride * p->height;
228 }
229
230 static void
231 paint_setup_IYU2 (paintinfo * p, unsigned char *dest)
232 {
233   /* untested */
234   p->yp = dest + 1;
235   p->up = dest + 0;
236   p->vp = dest + 2;
237   p->ystride = GST_ROUND_UP_4 (p->width * 3);
238   p->endptr = dest + p->ystride * p->height;
239 }
240
241 static void
242 paint_setup_Y41B (paintinfo * p, unsigned char *dest)
243 {
244   p->yp = dest;
245   p->ystride = GST_ROUND_UP_4 (p->width);
246   p->up = p->yp + p->ystride * p->height;
247   p->ustride = GST_ROUND_UP_16 (p->width) / 4;
248   p->vp = p->up + p->ustride * p->height;
249   p->vstride = GST_ROUND_UP_16 (p->width) / 4;
250   p->endptr = p->vp + p->vstride * p->height;
251 }
252
253 static void
254 paint_setup_Y42B (paintinfo * p, unsigned char *dest)
255 {
256   p->yp = dest;
257   p->ystride = GST_ROUND_UP_4 (p->width);
258   p->up = p->yp + p->ystride * p->height;
259   p->ustride = GST_ROUND_UP_8 (p->width) / 2;
260   p->vp = p->up + p->ustride * p->height;
261   p->vstride = GST_ROUND_UP_8 (p->width) / 2;
262   p->endptr = p->vp + p->vstride * p->height;
263 }
264
265 static void
266 paint_setup_GRAY8 (paintinfo * p, unsigned char *dest)
267 {
268   /* untested */
269   p->yp = dest;
270   p->ystride = GST_ROUND_UP_4 (p->width);
271   p->endptr = dest + p->ystride * p->height;
272 }
273
274 #if 0
275 static void
276 paint_setup_IMC1 (paintinfo * p, unsigned char *dest)
277 {
278   p->yp = dest;
279   p->up = dest + p->width * p->height;
280   p->vp = dest + p->width * p->height + p->width * p->height / 2;
281 }
282
283 static void
284 paint_setup_IMC2 (paintinfo * p, unsigned char *dest)
285 {
286   p->yp = dest;
287   p->vp = dest + p->width * p->height;
288   p->up = dest + p->width * p->height + p->width / 2;
289 }
290
291 static void
292 paint_setup_IMC3 (paintinfo * p, unsigned char *dest)
293 {
294   p->yp = dest;
295   p->up = dest + p->width * p->height + p->width * p->height / 2;
296   p->vp = dest + p->width * p->height;
297 }
298
299 static void
300 paint_setup_IMC4 (paintinfo * p, unsigned char *dest)
301 {
302   p->yp = dest;
303   p->vp = dest + p->width * p->height + p->width / 2;
304   p->up = dest + p->width * p->height;
305 }
306 #endif
307
308 static void
309 paint_setup_YVU9 (paintinfo * p, unsigned char *dest)
310 {
311   p->yp = dest;
312   p->ystride = GST_ROUND_UP_4 (p->width);
313   p->vp = p->yp + p->ystride * p->height;
314   p->vstride = GST_ROUND_UP_4 (p->ystride / 4);
315   p->up = p->vp + p->vstride * (GST_ROUND_UP_4 (p->height) / 4);
316   p->ustride = GST_ROUND_UP_4 (p->ystride / 4);
317   p->endptr = p->up + p->ustride * (GST_ROUND_UP_4 (p->height) / 4);
318 }
319
320 static void
321 paint_setup_YUV9 (paintinfo * p, unsigned char *dest)
322 {
323   p->yp = dest;
324   p->ystride = GST_ROUND_UP_4 (p->width);
325   p->up = p->yp + p->ystride * p->height;
326   p->ustride = GST_ROUND_UP_4 (p->ystride / 4);
327   p->vp = p->up + p->ustride * (GST_ROUND_UP_4 (p->height) / 4);
328   p->vstride = GST_ROUND_UP_4 (p->ystride / 4);
329   p->endptr = p->vp + p->vstride * (GST_ROUND_UP_4 (p->height) / 4);
330 }
331
332 #define gst_video_format_is_packed video_format_is_packed
333 static gboolean
334 video_format_is_packed (GstVideoFormat fmt)
335 {
336   switch (fmt) {
337     case GST_VIDEO_FORMAT_I420:
338     case GST_VIDEO_FORMAT_YV12:
339     case GST_VIDEO_FORMAT_Y41B:
340     case GST_VIDEO_FORMAT_Y42B:
341     case GST_VIDEO_FORMAT_GRAY8:
342     case GST_VIDEO_FORMAT_YUV9:
343     case GST_VIDEO_FORMAT_YVU9:
344       return FALSE;
345     case GST_VIDEO_FORMAT_IYU1:
346     case GST_VIDEO_FORMAT_YUY2:
347     case GST_VIDEO_FORMAT_YVYU:
348     case GST_VIDEO_FORMAT_UYVY:
349     case GST_VIDEO_FORMAT_AYUV:
350     case GST_VIDEO_FORMAT_RGBx:
351     case GST_VIDEO_FORMAT_BGRx:
352     case GST_VIDEO_FORMAT_xRGB:
353     case GST_VIDEO_FORMAT_xBGR:
354     case GST_VIDEO_FORMAT_RGBA:
355     case GST_VIDEO_FORMAT_BGRA:
356     case GST_VIDEO_FORMAT_ARGB:
357     case GST_VIDEO_FORMAT_ABGR:
358     case GST_VIDEO_FORMAT_RGB:
359     case GST_VIDEO_FORMAT_BGR:
360     case GST_VIDEO_FORMAT_RGB8P:
361       return TRUE;
362     default:
363       g_return_val_if_reached (FALSE);
364   }
365   return FALSE;
366 }
367
368 GST_START_TEST (test_video_formats_all)
369 {
370   GstStructure *s;
371   const GValue *val, *list_val;
372   GstCaps *caps;
373   guint num, n, num_formats;
374
375   num_formats = 100;
376   fail_unless (gst_video_format_to_string (num_formats) == NULL);
377   while (gst_video_format_to_string (num_formats) == NULL)
378     --num_formats;
379   GST_INFO ("number of known video formats: %d", num_formats);
380
381   caps = gst_caps_from_string ("video/x-raw, format=" GST_VIDEO_FORMATS_ALL);
382   s = gst_caps_get_structure (caps, 0);
383   val = gst_structure_get_value (s, "format");
384   fail_unless (val != NULL);
385   fail_unless (GST_VALUE_HOLDS_LIST (val));
386   num = gst_value_list_get_size (val);
387   fail_unless (num > 0);
388   for (n = 0; n < num; ++n) {
389     const gchar *fmt_str;
390
391     list_val = gst_value_list_get_value (val, n);
392     fail_unless (G_VALUE_HOLDS_STRING (list_val));
393     fmt_str = g_value_get_string (list_val);
394     GST_INFO ("format: %s", fmt_str);
395     fail_if (gst_video_format_from_string (fmt_str) ==
396         GST_VIDEO_FORMAT_UNKNOWN);
397   }
398   /* Take into account GST_VIDEO_FORMAT_ENCODED */
399   fail_unless_equals_int (num, num_formats - 1);
400
401   gst_caps_unref (caps);
402 }
403
404 GST_END_TEST;
405
406 GST_START_TEST (test_video_formats)
407 {
408   guint i;
409
410   for (i = 0; i < G_N_ELEMENTS (fourcc_list); ++i) {
411     const GstVideoFormatInfo *vf_info;
412     GstVideoFormat fmt;
413     const gchar *s;
414     guint32 fourcc;
415     guint w, h;
416
417     s = fourcc_list[i].fourcc;
418     fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]);
419     fmt = gst_video_format_from_fourcc (fourcc);
420
421     if (fmt == GST_VIDEO_FORMAT_UNKNOWN) {
422       GST_DEBUG ("Unknown format %s, skipping tests", fourcc_list[i].fourcc);
423       continue;
424     }
425
426     vf_info = gst_video_format_get_info (fmt);
427     fail_unless (vf_info != NULL);
428
429     fail_unless_equals_int (GST_VIDEO_FORMAT_INFO_FORMAT (vf_info), fmt);
430
431     GST_INFO ("Fourcc %s, packed=%d", fourcc_list[i].fourcc,
432         gst_video_format_is_packed (fmt));
433
434     fail_unless (GST_VIDEO_FORMAT_INFO_IS_YUV (vf_info));
435
436     /* use any non-NULL pointer so we can compare against NULL */
437     {
438       paintinfo paintinfo = { 0, };
439       fourcc_list[i].paint_setup (&paintinfo, (unsigned char *) s);
440       if (paintinfo.ap != NULL) {
441         fail_unless (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vf_info));
442       } else {
443         fail_if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vf_info));
444       }
445     }
446
447     for (w = 1; w <= 65; ++w) {
448       for (h = 1; h <= 65; ++h) {
449         GstVideoInfo vinfo;
450         paintinfo paintinfo = { 0, };
451         guint off0, off1, off2, off3;
452         guint cs0, cs1, cs2, cs3;
453         guint size;
454
455         GST_LOG ("%s, %dx%d", fourcc_list[i].fourcc, w, h);
456
457         gst_video_info_init (&vinfo);
458         gst_video_info_set_format (&vinfo, fmt, w, h);
459
460         paintinfo.width = w;
461         paintinfo.height = h;
462         fourcc_list[i].paint_setup (&paintinfo, NULL);
463         fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 0),
464             paintinfo.ystride);
465         if (!gst_video_format_is_packed (fmt)
466             && !GST_VIDEO_INFO_N_PLANES (&vinfo) > 2) {
467           /* planar */
468           fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 1),
469               paintinfo.ustride);
470           fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 2),
471               paintinfo.vstride);
472           /* check component_width * height against offsets/size somehow? */
473         }
474
475         size = GST_VIDEO_INFO_SIZE (&vinfo);
476         off0 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 0);
477         off1 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 1);
478         off2 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 2);
479
480         GST_INFO ("size %d <> %d", size, paintinfo.endptr);
481         GST_INFO ("off0 %d <> %d", off0, paintinfo.yp);
482         GST_INFO ("off1 %d <> %d", off1, paintinfo.up);
483         GST_INFO ("off2 %d <> %d", off2, paintinfo.vp);
484
485         fail_unless_equals_int (size, (unsigned long) paintinfo.endptr);
486         fail_unless_equals_int (off0, (unsigned long) paintinfo.yp);
487         fail_unless_equals_int (off1, (unsigned long) paintinfo.up);
488         fail_unless_equals_int (off2, (unsigned long) paintinfo.vp);
489
490         /* should be 0 if there's no alpha component */
491         off3 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 3);
492         fail_unless_equals_int (off3, (unsigned long) paintinfo.ap);
493
494         cs0 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 0) *
495             GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 0);
496         cs1 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 1) *
497             GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 1);
498         cs2 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 2) *
499             GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 2);
500
501         /* GST_LOG ("cs0=%d,cs1=%d,cs2=%d,off0=%d,off1=%d,off2=%d,size=%d",
502            cs0, cs1, cs2, off0, off1, off2, size); */
503
504         if (!gst_video_format_is_packed (fmt))
505           fail_unless (cs0 <= off1);
506
507         if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vinfo.finfo)) {
508           cs3 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 3) *
509               GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 2);
510           fail_unless (cs3 < size);
511           /* U/V/alpha shouldn't take up more space than the Y component */
512           fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0);
513           fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0);
514           fail_if (cs3 > cs0, "cs3 (%d) should be <= cs0 (%d)", cs3, cs0);
515
516           /* all components together shouldn't take up more space than size */
517           fail_unless (cs0 + cs1 + cs2 + cs3 <= size);
518         } else {
519           /* U/V shouldn't take up more space than the Y component */
520           fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0);
521           fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0);
522
523           /* all components together shouldn't take up more space than size */
524           fail_unless (cs0 + cs1 + cs2 <= size,
525               "cs0 (%d) + cs1 (%d) + cs2 (%d) should be <= size (%d)",
526               cs0, cs1, cs2, size);
527         }
528       }
529     }
530   }
531 }
532
533 GST_END_TEST;
534
535 GST_START_TEST (test_video_formats_rgb)
536 {
537   GstVideoInfo vinfo;
538   gint width, height, framerate_n, framerate_d, par_n, par_d;
539   GstCaps *caps;
540   GstStructure *structure;
541
542   gst_video_info_init (&vinfo);
543   gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_RGB, 800, 600);
544   vinfo.par_n = 1;
545   vinfo.par_d = 1;
546   vinfo.fps_n = 0;
547   vinfo.fps_d = 1;
548   caps = gst_video_info_to_caps (&vinfo);
549   structure = gst_caps_get_structure (caps, 0);
550
551   fail_unless (gst_structure_get_int (structure, "width", &width));
552   fail_unless (gst_structure_get_int (structure, "height", &height));
553   fail_unless (gst_structure_get_fraction (structure, "framerate", &framerate_n,
554           &framerate_d));
555   fail_unless (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
556           &par_n, &par_d));
557
558   fail_unless (width == 800);
559   fail_unless (height == 600);
560   fail_unless (framerate_n == 0);
561   fail_unless (framerate_d == 1);
562   fail_unless (par_n == 1);
563   fail_unless (par_d == 1);
564
565   gst_caps_unref (caps);
566 }
567
568 GST_END_TEST;
569
570 GST_START_TEST (test_dar_calc)
571 {
572   guint display_ratio_n, display_ratio_d;
573
574   /* Ensure that various Display Ratio calculations are correctly done */
575   /* video 768x576, par 16/15, display par 16/15 = 4/3 */
576   fail_unless (gst_video_calculate_display_ratio (&display_ratio_n,
577           &display_ratio_d, 768, 576, 16, 15, 16, 15));
578   fail_unless (display_ratio_n == 4 && display_ratio_d == 3);
579
580   /* video 720x480, par 32/27, display par 1/1 = 16/9 */
581   fail_unless (gst_video_calculate_display_ratio (&display_ratio_n,
582           &display_ratio_d, 720, 480, 32, 27, 1, 1));
583   fail_unless (display_ratio_n == 16 && display_ratio_d == 9);
584
585   /* video 360x288, par 533333/500000, display par 16/15 = 
586    * dar 1599999/1600000 */
587   fail_unless (gst_video_calculate_display_ratio (&display_ratio_n,
588           &display_ratio_d, 360, 288, 533333, 500000, 16, 15));
589   fail_unless (display_ratio_n == 1599999 && display_ratio_d == 1280000);
590 }
591
592 GST_END_TEST;
593
594 GST_START_TEST (test_parse_caps_rgb)
595 {
596   struct
597   {
598     const gchar *tmpl_caps_string;
599     GstVideoFormat fmt;
600   } formats[] = {
601     /* 24 bit */
602     {
603     GST_VIDEO_CAPS_MAKE ("RGB"), GST_VIDEO_FORMAT_RGB}, {
604     GST_VIDEO_CAPS_MAKE ("BGR"), GST_VIDEO_FORMAT_BGR},
605         /* 32 bit (no alpha) */
606     {
607     GST_VIDEO_CAPS_MAKE ("RGBx"), GST_VIDEO_FORMAT_RGBx}, {
608     GST_VIDEO_CAPS_MAKE ("xRGB"), GST_VIDEO_FORMAT_xRGB}, {
609     GST_VIDEO_CAPS_MAKE ("BGRx"), GST_VIDEO_FORMAT_BGRx}, {
610     GST_VIDEO_CAPS_MAKE ("xBGR"), GST_VIDEO_FORMAT_xBGR},
611         /* 32 bit (with alpha) */
612     {
613     GST_VIDEO_CAPS_MAKE ("RGBA"), GST_VIDEO_FORMAT_RGBA}, {
614     GST_VIDEO_CAPS_MAKE ("ARGB"), GST_VIDEO_FORMAT_ARGB}, {
615     GST_VIDEO_CAPS_MAKE ("BGRA"), GST_VIDEO_FORMAT_BGRA}, {
616     GST_VIDEO_CAPS_MAKE ("ABGR"), GST_VIDEO_FORMAT_ABGR},
617         /* 16 bit */
618     {
619     GST_VIDEO_CAPS_MAKE ("RGB16"), GST_VIDEO_FORMAT_RGB16}, {
620     GST_VIDEO_CAPS_MAKE ("BGR16"), GST_VIDEO_FORMAT_BGR16}, {
621     GST_VIDEO_CAPS_MAKE ("RGB15"), GST_VIDEO_FORMAT_RGB15}, {
622     GST_VIDEO_CAPS_MAKE ("BGR15"), GST_VIDEO_FORMAT_BGR15}
623   };
624   gint i;
625
626   for (i = 0; i < G_N_ELEMENTS (formats); ++i) {
627     GstVideoInfo vinfo;
628     GstCaps *caps, *caps2;
629
630     caps = gst_caps_from_string (formats[i].tmpl_caps_string);
631     gst_caps_set_simple (caps, "width", G_TYPE_INT, 2 * (i + 1), "height",
632         G_TYPE_INT, i + 1, "framerate", GST_TYPE_FRACTION, 15, 1,
633         "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
634         "interlace-mode", G_TYPE_STRING, "progressive",
635         "colorimetry", G_TYPE_STRING, "1:1:0:0", NULL);
636     g_assert (gst_caps_is_fixed (caps));
637
638     GST_DEBUG ("testing caps: %" GST_PTR_FORMAT, caps);
639
640     gst_video_info_init (&vinfo);
641     fail_unless (gst_video_info_from_caps (&vinfo, caps));
642     fail_unless_equals_int (GST_VIDEO_INFO_FORMAT (&vinfo), formats[i].fmt);
643     fail_unless_equals_int (GST_VIDEO_INFO_WIDTH (&vinfo), 2 * (i + 1));
644     fail_unless_equals_int (GST_VIDEO_INFO_HEIGHT (&vinfo), i + 1);
645
646     /* make sure they're serialised back correctly */
647     caps2 = gst_video_info_to_caps (&vinfo);
648     fail_unless (caps != NULL);
649     fail_unless (gst_caps_is_equal (caps, caps2),
650         "caps [%" GST_PTR_FORMAT "] not equal to caps2 [%" GST_PTR_FORMAT "]",
651         caps, caps2);
652
653     gst_caps_unref (caps);
654     gst_caps_unref (caps2);
655   }
656 }
657
658 GST_END_TEST;
659
660 GST_START_TEST (test_events)
661 {
662   GstEvent *e;
663   gboolean in_still;
664
665   e = gst_video_event_new_still_frame (TRUE);
666   fail_if (e == NULL, "Failed to create still frame event");
667   fail_unless (gst_video_event_parse_still_frame (e, &in_still),
668       "Failed to parse still frame event");
669   fail_unless (gst_video_event_parse_still_frame (e, NULL),
670       "Failed to parse still frame event w/ in_still == NULL");
671   fail_unless (in_still == TRUE);
672   gst_event_unref (e);
673
674   e = gst_video_event_new_still_frame (FALSE);
675   fail_if (e == NULL, "Failed to create still frame event");
676   fail_unless (gst_video_event_parse_still_frame (e, &in_still),
677       "Failed to parse still frame event");
678   fail_unless (gst_video_event_parse_still_frame (e, NULL),
679       "Failed to parse still frame event w/ in_still == NULL");
680   fail_unless (in_still == FALSE);
681   gst_event_unref (e);
682 }
683
684 GST_END_TEST;
685
686 GST_START_TEST (test_convert_frame)
687 {
688   GstVideoInfo vinfo;
689   GstCaps *from_caps, *to_caps;
690   GstBuffer *from_buffer;
691   GstSample *from_sample, *to_sample;
692   GError *error = NULL;
693   gint i;
694   GstMapInfo map;
695
696   gst_debug_set_threshold_for_name ("default", GST_LEVEL_NONE);
697
698   from_buffer = gst_buffer_new_and_alloc (640 * 480 * 4);
699
700   gst_buffer_map (from_buffer, &map, GST_MAP_WRITE);
701   for (i = 0; i < 640 * 480; i++) {
702     map.data[4 * i + 0] = 0;    /* x */
703     map.data[4 * i + 1] = 255;  /* R */
704     map.data[4 * i + 2] = 0;    /* G */
705     map.data[4 * i + 3] = 0;    /* B */
706   }
707   gst_buffer_unmap (from_buffer, &map);
708
709   gst_video_info_init (&vinfo);
710   gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_xRGB, 640, 480);
711   vinfo.fps_n = 25;
712   vinfo.fps_d = 1;
713   vinfo.par_n = 1;
714   vinfo.par_d = 1;
715   from_caps = gst_video_info_to_caps (&vinfo);
716
717   from_sample = gst_sample_new (from_buffer, from_caps, NULL, NULL);
718
719   to_caps =
720       gst_caps_from_string
721       ("something/that, does=(string)not, exist=(boolean)FALSE");
722
723   to_sample =
724       gst_video_convert_sample (from_sample, to_caps,
725       GST_CLOCK_TIME_NONE, &error);
726   fail_if (to_sample != NULL);
727   fail_unless (error != NULL);
728   g_error_free (error);
729   error = NULL;
730
731   gst_caps_unref (to_caps);
732   gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_I420, 240, 320);
733   vinfo.fps_n = 25;
734   vinfo.fps_d = 1;
735   vinfo.par_n = 1;
736   vinfo.par_d = 2;
737   to_caps = gst_video_info_to_caps (&vinfo);
738
739   to_sample =
740       gst_video_convert_sample (from_sample, to_caps,
741       GST_CLOCK_TIME_NONE, &error);
742   fail_unless (to_sample != NULL);
743   fail_unless (error == NULL);
744
745   gst_buffer_unref (from_buffer);
746   gst_caps_unref (from_caps);
747   gst_sample_unref (from_sample);
748   gst_sample_unref (to_sample);
749   gst_caps_unref (to_caps);
750 }
751
752 GST_END_TEST;
753
754 typedef struct
755 {
756   GMainLoop *loop;
757   GstSample *sample;
758   GError *error;
759 } ConvertFrameContext;
760
761 static void
762 convert_sample_async_callback (GstSample * sample, GError * err,
763     ConvertFrameContext * cf_data)
764 {
765   cf_data->sample = sample;
766   cf_data->error = err;
767
768   g_main_loop_quit (cf_data->loop);
769 }
770
771 GST_START_TEST (test_convert_frame_async)
772 {
773   GstVideoInfo vinfo;
774   GstCaps *from_caps, *to_caps;
775   GstBuffer *from_buffer;
776   GstSample *from_sample;
777   gint i;
778   GstMapInfo map;
779   GMainLoop *loop;
780   ConvertFrameContext cf_data = { NULL, NULL, NULL };
781
782   gst_debug_set_threshold_for_name ("default", GST_LEVEL_NONE);
783
784   from_buffer = gst_buffer_new_and_alloc (640 * 480 * 4);
785
786   gst_buffer_map (from_buffer, &map, GST_MAP_WRITE);
787   for (i = 0; i < 640 * 480; i++) {
788     map.data[4 * i + 0] = 0;    /* x */
789     map.data[4 * i + 1] = 255;  /* R */
790     map.data[4 * i + 2] = 0;    /* G */
791     map.data[4 * i + 3] = 0;    /* B */
792   }
793   gst_buffer_unmap (from_buffer, &map);
794
795   gst_video_info_init (&vinfo);
796   gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_xRGB, 640, 470);
797   vinfo.par_n = 1;
798   vinfo.par_d = 1;
799   vinfo.fps_n = 25;
800   vinfo.fps_d = 1;
801   from_caps = gst_video_info_to_caps (&vinfo);
802
803   to_caps =
804       gst_caps_from_string
805       ("something/that, does=(string)not, exist=(boolean)FALSE");
806
807   loop = cf_data.loop = g_main_loop_new (NULL, FALSE);
808
809   from_sample = gst_sample_new (from_buffer, from_caps, NULL, NULL);
810   gst_buffer_unref (from_buffer);
811   gst_caps_unref (from_caps);
812
813   gst_video_convert_sample_async (from_sample, to_caps,
814       GST_CLOCK_TIME_NONE,
815       (GstVideoConvertSampleCallback) convert_sample_async_callback, &cf_data,
816       NULL);
817
818   g_main_loop_run (loop);
819
820   fail_if (cf_data.sample != NULL);
821   fail_unless (cf_data.error != NULL);
822   g_error_free (cf_data.error);
823   cf_data.error = NULL;
824
825   gst_caps_unref (to_caps);
826   gst_video_info_init (&vinfo);
827   gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_I420, 240, 320);
828   vinfo.par_n = 1;
829   vinfo.par_d = 2;
830   vinfo.fps_n = 25;
831   vinfo.fps_d = 1;
832   to_caps = gst_video_info_to_caps (&vinfo);
833   gst_video_convert_sample_async (from_sample, to_caps,
834       GST_CLOCK_TIME_NONE,
835       (GstVideoConvertSampleCallback) convert_sample_async_callback, &cf_data,
836       NULL);
837   g_main_loop_run (loop);
838   fail_unless (cf_data.sample != NULL);
839   fail_unless (cf_data.error == NULL);
840
841   gst_sample_unref (cf_data.sample);
842   gst_caps_unref (to_caps);
843   gst_sample_unref (from_sample);
844
845   g_main_loop_unref (loop);
846 }
847
848 GST_END_TEST;
849
850 GST_START_TEST (test_video_size_from_caps)
851 {
852   GstVideoInfo vinfo;
853   GstCaps *caps;
854
855   caps = gst_caps_new_simple ("video/x-raw",
856       "format", G_TYPE_STRING, "YV12",
857       "width", G_TYPE_INT, 640,
858       "height", G_TYPE_INT, 480, "framerate", GST_TYPE_FRACTION, 25, 1, NULL);
859
860   gst_video_info_init (&vinfo);
861   fail_unless (gst_video_info_from_caps (&vinfo, caps));
862   fail_unless (GST_VIDEO_INFO_SIZE (&vinfo) == (640 * 480 * 12 / 8));
863
864   gst_caps_unref (caps);
865 }
866
867 GST_END_TEST;
868
869 GST_START_TEST (test_overlay_composition)
870 {
871   GstVideoOverlayComposition *comp1, *comp2;
872   GstVideoOverlayRectangle *rect1, *rect2;
873   GstVideoOverlayCompositionMeta *ometa;
874   GstBuffer *pix1, *pix2, *buf;
875   GstVideoMeta *vmeta;
876   guint seq1, seq2;
877   guint w, h, stride;
878   gint x, y;
879   guint8 val;
880
881   pix1 = gst_buffer_new_and_alloc (200 * sizeof (guint32) * 50);
882   gst_buffer_memset (pix1, 0, 0, gst_buffer_get_size (pix1));
883
884   gst_buffer_add_video_meta (pix1, GST_VIDEO_FRAME_FLAG_NONE,
885       GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB, 200, 50);
886   rect1 = gst_video_overlay_rectangle_new_raw (pix1,
887       600, 50, 300, 50, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
888
889   gst_buffer_unref (pix1);
890   pix1 = NULL;
891
892   comp1 = gst_video_overlay_composition_new (rect1);
893   fail_unless (gst_video_overlay_composition_n_rectangles (comp1) == 1);
894   fail_unless (gst_video_overlay_composition_get_rectangle (comp1, 0) == rect1);
895   fail_unless (gst_video_overlay_composition_get_rectangle (comp1, 1) == NULL);
896
897   /* rectangle was created first, sequence number should be smaller */
898   seq1 = gst_video_overlay_rectangle_get_seqnum (rect1);
899   seq2 = gst_video_overlay_composition_get_seqnum (comp1);
900   fail_unless (seq1 < seq2);
901
902   /* composition took own ref, so refcount is 2 now, so this should fail */
903   ASSERT_CRITICAL (gst_video_overlay_rectangle_set_render_rectangle (rect1, 50,
904           600, 300, 50));
905
906   /* drop our ref, so refcount is 1 (we know it will continue to be valid) */
907   gst_video_overlay_rectangle_unref (rect1);
908   gst_video_overlay_rectangle_set_render_rectangle (rect1, 50, 600, 300, 50);
909
910   comp2 = gst_video_overlay_composition_new (rect1);
911   fail_unless (gst_video_overlay_composition_n_rectangles (comp2) == 1);
912   fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 0) == rect1);
913   fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 1) == NULL);
914
915   fail_unless (seq1 < gst_video_overlay_composition_get_seqnum (comp2));
916   fail_unless (seq2 < gst_video_overlay_composition_get_seqnum (comp2));
917
918   /* now refcount is 2 again because comp2 has also taken a ref, so must fail */
919   ASSERT_CRITICAL (gst_video_overlay_rectangle_set_render_rectangle (rect1, 0,
920           0, 1, 1));
921
922   /* this should make a copy of the rectangles so drop the original
923    * second ref on rect1 */
924   comp2 = gst_video_overlay_composition_make_writable (comp2);
925   gst_video_overlay_rectangle_set_render_rectangle (rect1, 51, 601, 301, 51);
926
927   rect2 = gst_video_overlay_composition_get_rectangle (comp2, 0);
928   fail_unless (gst_video_overlay_composition_n_rectangles (comp2) == 1);
929   fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 0) == rect2);
930   fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 1) == NULL);
931   fail_unless (rect1 != rect2);
932
933   gst_video_overlay_composition_add_rectangle (comp1, rect2);
934   gst_video_overlay_composition_ref (comp1);
935   ASSERT_CRITICAL (gst_video_overlay_composition_add_rectangle (comp1, rect2));
936   gst_video_overlay_composition_unref (comp1);
937
938   /* make sure the copy really worked */
939   gst_video_overlay_rectangle_get_render_rectangle (rect1, &x, &y, &w, &h);
940   fail_unless_equals_int (x, 51);
941   fail_unless_equals_int (y, 601);
942   fail_unless_equals_int (w, 301);
943   fail_unless_equals_int (h, 51);
944
945   /* get scaled pixbuf and touch last byte */
946   pix1 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
947       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
948   stride = 4 * w;
949   fail_unless (gst_buffer_get_size (pix1) > ((h - 1) * stride + (w * 4) - 1),
950       "size %u vs. last pixel offset %u", gst_buffer_get_size (pix1),
951       ((h - 1) * stride + (w * 4) - 1));
952   gst_buffer_extract (pix1, ((h - 1) * stride + (w * 4) - 1), &val, 1);
953   fail_unless_equals_int (val, 0);
954
955   gst_video_overlay_rectangle_get_render_rectangle (rect2, &x, &y, &w, &h);
956   fail_unless_equals_int (x, 50);
957   fail_unless_equals_int (y, 600);
958   fail_unless_equals_int (w, 300);
959   fail_unless_equals_int (h, 50);
960
961   /* get scaled pixbuf and touch last byte */
962   pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect2,
963       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
964   stride = 4 * w;
965   fail_unless (gst_buffer_get_size (pix2) > ((h - 1) * stride + (w * 4) - 1),
966       "size %u vs. last pixel offset %u", gst_buffer_get_size (pix1),
967       ((h - 1) * stride + (w * 4) - 1));
968   gst_buffer_extract (pix2, ((h - 1) * stride + (w * 4) - 1), &val, 1);
969   fail_unless_equals_int (val, 0);
970
971   /* get scaled pixbuf again, should be the same buffer as before (caching) */
972   pix1 = gst_video_overlay_rectangle_get_pixels_raw (rect2,
973       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
974   fail_unless (pix1 == pix2);
975
976   /* get in different format */
977   pix1 = gst_video_overlay_rectangle_get_pixels_ayuv (rect2,
978       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
979   fail_unless (pix1 != pix2);
980   /* get it again, should be same (caching) */
981   pix2 = gst_video_overlay_rectangle_get_pixels_ayuv (rect2,
982       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
983   fail_unless (pix1 == pix2);
984   /* get unscaled, should be different */
985   pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_ayuv (rect2,
986       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
987   fail_unless (pix1 != pix2);
988   /* but should be cached */
989   pix1 = gst_video_overlay_rectangle_get_pixels_unscaled_ayuv (rect2,
990       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
991   fail_unless (pix1 == pix2);
992
993   vmeta = gst_buffer_get_video_meta (pix1);
994   fail_unless (vmeta != NULL);
995   w = vmeta->width;
996   h = vmeta->height;
997   fail_unless_equals_int (w, 200);
998   fail_unless_equals_int (h, 50);
999   fail_unless_equals_int (vmeta->format,
1000       GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_YUV);
1001   fail_unless (gst_buffer_get_size (pix1) == w * h * 4);
1002   gst_buffer_extract (pix1, 0, &seq1, 4);
1003   fail_unless (seq1 != 0);
1004
1005   /* now compare the original unscaled ones */
1006   pix1 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1007       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1008   pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect2,
1009       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1010
1011   vmeta = gst_buffer_get_video_meta (pix2);
1012   fail_unless (vmeta != NULL);
1013   w = vmeta->width;
1014   h = vmeta->height;
1015
1016   /* the original pixel buffers should be identical */
1017   fail_unless (pix1 == pix2);
1018   fail_unless_equals_int (w, 200);
1019   fail_unless_equals_int (h, 50);
1020   stride = 4 * w;
1021
1022   /* touch last byte */
1023   fail_unless (gst_buffer_get_size (pix1) > ((h - 1) * stride + (w * 4) - 1),
1024       "size %u vs. last pixel offset %u", gst_buffer_get_size (pix1),
1025       ((h - 1) * stride + (w * 4) - 1));
1026   gst_buffer_extract (pix1, ((h - 1) * stride + (w * 4) - 1), &val, 1);
1027   fail_unless_equals_int (val, 0);
1028
1029   /* test attaching and retrieving of compositions to/from buffers */
1030   buf = gst_buffer_new ();
1031   fail_unless (gst_buffer_get_video_overlay_composition_meta (buf) == NULL);
1032
1033   gst_buffer_ref (buf);
1034   /* buffer now has refcount of 2, so its metadata is not writable.
1035    * only check this if we are not running in valgrind, as it leaks */
1036 #ifdef HAVE_VALGRIND
1037   if (!RUNNING_ON_VALGRIND) {
1038     ASSERT_CRITICAL (gst_buffer_add_video_overlay_composition_meta (buf,
1039             comp1));
1040   }
1041 #endif
1042   gst_buffer_unref (buf);
1043   gst_buffer_add_video_overlay_composition_meta (buf, comp1);
1044   ometa = gst_buffer_get_video_overlay_composition_meta (buf);
1045   fail_unless (ometa != NULL);
1046   fail_unless (ometa->overlay == comp1);
1047   fail_unless (gst_buffer_remove_video_overlay_composition_meta (buf, ometa));
1048   gst_buffer_add_video_overlay_composition_meta (buf, comp2);
1049   ometa = gst_buffer_get_video_overlay_composition_meta (buf);
1050   fail_unless (ometa->overlay == comp2);
1051   fail_unless (gst_buffer_remove_video_overlay_composition_meta (buf, ometa));
1052   fail_unless (gst_buffer_get_video_overlay_composition_meta (buf) == NULL);
1053
1054   /* make sure the buffer cleans up its composition ref when unreffed */
1055   gst_buffer_add_video_overlay_composition_meta (buf, comp2);
1056   gst_buffer_unref (buf);
1057
1058   gst_video_overlay_composition_unref (comp2);
1059   gst_video_overlay_composition_unref (comp1);
1060 }
1061
1062 GST_END_TEST;
1063
1064 GST_START_TEST (test_overlay_composition_premultiplied_alpha)
1065 {
1066   GstVideoOverlayRectangle *rect1;
1067   GstVideoMeta *vmeta;
1068   GstBuffer *pix1, *pix2, *pix3, *pix4, *pix5;
1069   GstBuffer *pix6, *pix7, *pix8, *pix9, *pix10;
1070   guint8 *data5, *data7;
1071   guint w, h, w2, h2;
1072   GstMapInfo map;
1073
1074   pix1 = gst_buffer_new_and_alloc (200 * sizeof (guint32) * 50);
1075   gst_buffer_memset (pix1, 0, 0x80, gst_buffer_get_size (pix1));
1076
1077   gst_buffer_add_video_meta (pix1, GST_VIDEO_FRAME_FLAG_NONE,
1078       GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB, 200, 50);
1079   rect1 = gst_video_overlay_rectangle_new_raw (pix1,
1080       600, 50, 300, 50, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1081   gst_buffer_unref (pix1);
1082
1083   /* same flags, unscaled, should be the same buffer */
1084   pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1085       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1086   fail_unless (pix1 == pix2);
1087
1088   /* same flags, but scaled */
1089   pix3 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1090       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1091   fail_if (pix3 == pix1 || pix3 == pix2);
1092
1093   /* same again, should hopefully get the same (cached) buffer as before */
1094   pix4 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1095       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1096   fail_unless (pix4 == pix3);
1097
1098   /* just to update the vars */
1099   pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1100       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1101
1102   vmeta = gst_buffer_get_video_meta (pix2);
1103   fail_unless (vmeta != NULL);
1104   w = vmeta->width;
1105   h = vmeta->height;
1106
1107   /* now, let's try to get premultiplied alpha from the unpremultiplied input */
1108   pix5 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1109       GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1110   fail_if (pix5 == pix1 || pix5 == pix2 || pix5 == pix3);
1111   vmeta = gst_buffer_get_video_meta (pix5);
1112   fail_unless (vmeta != NULL);
1113   w2 = vmeta->width;
1114   h2 = vmeta->height;
1115   fail_unless_equals_int (w, w2);
1116   fail_unless_equals_int (h, h2);
1117   fail_unless_equals_int (gst_buffer_get_size (pix2),
1118       gst_buffer_get_size (pix5));
1119   gst_buffer_map (pix5, &map, GST_MAP_READ);
1120   fail_if (gst_buffer_memcmp (pix2, 0, map.data, map.size) == 0);
1121   /* make sure it actually did what we expected it to do (input=0x80808080) */
1122   data5 = map.data;
1123 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1124   /* B - G - R - A */
1125   fail_unless_equals_int (data5[0], 0x40);
1126   fail_unless_equals_int (data5[1], 0x40);
1127   fail_unless_equals_int (data5[2], 0x40);
1128   fail_unless_equals_int (data5[3], 0x80);
1129 #else
1130   /* A - R - G - B */
1131   fail_unless_equals_int (data5[0], 0x40);
1132   fail_unless_equals_int (data5[1], 0x40);
1133   fail_unless_equals_int (data5[2], 0x40);
1134   fail_unless_equals_int (data5[3], 0x80);
1135 #endif
1136   gst_buffer_unmap (pix5, &map);
1137
1138   /* same again, now we should be getting back the same buffer as before,
1139    * as it should have been cached */
1140   pix6 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1141       GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1142   fail_unless (pix6 == pix5);
1143
1144   /* just to update the stride var */
1145   pix3 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1146       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1147   fail_unless (pix3 == pix4);
1148
1149   /* now try to get scaled premultiplied alpha from unpremultiplied input */
1150   pix7 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1151       GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1152   fail_if (pix7 == pix1 || pix7 == pix2 || pix7 == pix3 || pix7 == pix5);
1153
1154   gst_buffer_map (pix7, &map, GST_MAP_READ);
1155   data7 = map.data;
1156   /* make sure it actually did what we expected it to do (input=0x80808080)
1157    * hoping that the scaling didn't mess up our values */
1158 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1159   /* B - G - R - A */
1160   fail_unless_equals_int (data7[0], 0x40);
1161   fail_unless_equals_int (data7[1], 0x40);
1162   fail_unless_equals_int (data7[2], 0x40);
1163   fail_unless_equals_int (data7[3], 0x80);
1164 #else
1165   /* A - R - G - B */
1166   fail_unless_equals_int (data7[0], 0x40);
1167   fail_unless_equals_int (data7[1], 0x40);
1168   fail_unless_equals_int (data7[2], 0x40);
1169   fail_unless_equals_int (data7[3], 0x80);
1170 #endif
1171   gst_buffer_unmap (pix7, &map);
1172
1173   /* and the same again, it should be cached now */
1174   pix8 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1175       GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1176   fail_unless (pix8 == pix7);
1177
1178   /* make sure other cached stuff is still there */
1179   pix9 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1180       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1181   fail_unless (pix9 == pix3);
1182   pix10 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1183       GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1184   fail_unless (pix10 == pix5);
1185
1186   gst_video_overlay_rectangle_unref (rect1);
1187 }
1188
1189 GST_END_TEST;
1190
1191 GST_START_TEST (test_overlay_composition_global_alpha)
1192 {
1193   GstVideoOverlayRectangle *rect1;
1194   GstBuffer *pix1, *pix2, *pix3, *pix4, *pix5;
1195   GstVideoMeta *vmeta;
1196   guint8 *data2, *data4, *data5;
1197   guint w, h, w4, h4;
1198   guint seq1, seq2;
1199   gfloat ga1, ga2;
1200   GstVideoOverlayFormatFlags flags1;
1201   GstMapInfo map;
1202
1203   pix1 = gst_buffer_new_and_alloc (200 * sizeof (guint32) * 50);
1204   gst_buffer_memset (pix1, 0, 0x80, gst_buffer_get_size (pix1));
1205
1206   gst_buffer_add_video_meta (pix1, GST_VIDEO_FRAME_FLAG_NONE,
1207       GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB, 200, 50);
1208   rect1 = gst_video_overlay_rectangle_new_raw (pix1,
1209       600, 50, 300, 50, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1210   gst_buffer_unref (pix1);
1211
1212   /* same flags, unscaled, should be the same buffer */
1213   pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1214       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1215   fail_unless (pix1 == pix2);
1216
1217   vmeta = gst_buffer_get_video_meta (pix2);
1218   fail_unless (vmeta != NULL);
1219   w = vmeta->width;
1220   h = vmeta->height;
1221
1222   /* same flags, but scaled */
1223   pix3 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1224       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1225   fail_if (pix3 == pix1 || pix3 == pix2);
1226
1227   /* get unscaled premultiplied data, new cached rectangle should be created */
1228   pix4 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1229       GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1230   fail_if (pix4 == pix2 || pix4 == pix3);
1231   vmeta = gst_buffer_get_video_meta (pix4);
1232   fail_unless (vmeta != NULL);
1233   w4 = vmeta->width;
1234   h4 = vmeta->height;
1235   fail_unless_equals_int (w, w4);
1236   fail_unless_equals_int (h, h4);
1237   fail_unless_equals_int (gst_buffer_get_size (pix2),
1238       gst_buffer_get_size (pix4));
1239   gst_buffer_map (pix4, &map, GST_MAP_READ);
1240   fail_if (gst_buffer_memcmp (pix1, 0, map.data, map.size) == 0);
1241   /* make sure it actually did what we expected it to do (input=0x80808080) */
1242   data4 = map.data;
1243 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1244   /* B - G - R - A */
1245   fail_unless_equals_int (data4[0], 0x40);
1246   fail_unless_equals_int (data4[1], 0x40);
1247   fail_unless_equals_int (data4[2], 0x40);
1248   fail_unless_equals_int (data4[3], 0x80);
1249 #else
1250   /* A - R - G - B */
1251   fail_unless_equals_int (data4[0], 0x80);
1252   fail_unless_equals_int (data4[1], 0x40);
1253   fail_unless_equals_int (data4[2], 0x40);
1254   fail_unless_equals_int (data4[3], 0x40);
1255 #endif
1256   gst_buffer_unmap (pix4, &map);
1257
1258   /* now premultiplied and scaled, again a new cached rectangle should be cached */
1259   pix5 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1260       GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1261   fail_if (pix5 == pix2 || pix5 == pix3 || pix5 == pix4);
1262   /* stride and size should be equal to the first scaled rect */
1263   fail_unless_equals_int (gst_buffer_get_size (pix5),
1264       gst_buffer_get_size (pix3));
1265   /* data should be different (premutliplied) though */
1266   gst_buffer_map (pix5, &map, GST_MAP_READ);
1267   fail_if (gst_buffer_memcmp (pix3, 0, map.data, map.size) == 0);
1268   /* make sure it actually did what we expected it to do (input=0x80808080) */
1269   data5 = map.data;
1270 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1271   /* B - G - R - A */
1272   fail_unless_equals_int (data5[0], 0x40);
1273   fail_unless_equals_int (data5[1], 0x40);
1274   fail_unless_equals_int (data5[2], 0x40);
1275   fail_unless_equals_int (data5[3], 0x80);
1276 #else
1277   /* A - R - G - B */
1278   fail_unless_equals_int (data5[0], 0x80);
1279   fail_unless_equals_int (data5[1], 0x40);
1280   fail_unless_equals_int (data5[2], 0x40);
1281   fail_unless_equals_int (data5[3], 0x40);
1282 #endif
1283   gst_buffer_unmap (pix5, &map);
1284
1285   /* global_alpha should initially be 1.0 */
1286   ga1 = gst_video_overlay_rectangle_get_global_alpha (rect1);
1287   fail_unless_equals_float (ga1, 1.0);
1288
1289   /* now set global_alpha */
1290   seq1 = gst_video_overlay_rectangle_get_seqnum (rect1);
1291   gst_video_overlay_rectangle_set_global_alpha (rect1, 0.5);
1292   ga2 = gst_video_overlay_rectangle_get_global_alpha (rect1);
1293   fail_unless_equals_float (ga2, 0.5);
1294
1295   /* seqnum should have changed */
1296   seq2 = gst_video_overlay_rectangle_get_seqnum (rect1);
1297   fail_unless (seq1 < seq2);
1298
1299   /* internal flags should have been set */
1300   flags1 = gst_video_overlay_rectangle_get_flags (rect1);
1301   fail_unless_equals_int (flags1, GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1302
1303   /* request unscaled pixel-data, global-alpha not applied */
1304   pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1305       GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1306   /* this should just return the same buffer */
1307   fail_unless (pix2 == pix1);
1308   /* make sure we got the initial data (input=0x80808080) */
1309   gst_buffer_map (pix2, &map, GST_MAP_READ);
1310   data2 = map.data;
1311 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1312   /* B - G - R - A */
1313   fail_unless_equals_int (data2[0], 0x80);
1314   fail_unless_equals_int (data2[1], 0x80);
1315   fail_unless_equals_int (data2[2], 0x80);
1316   fail_unless_equals_int (data2[3], 0x80);
1317 #else
1318   /* A - R - G - B */
1319   fail_unless_equals_int (data2[0], 0x80);
1320   fail_unless_equals_int (data2[1], 0x80);
1321   fail_unless_equals_int (data2[2], 0x80);
1322   fail_unless_equals_int (data2[3], 0x80);
1323 #endif
1324   gst_buffer_unmap (pix2, &map);
1325
1326   /* unscaled pixel-data, global-alpha applied */
1327   pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1328       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1329   /* this should be the same buffer with on-the-fly modified alpha-channel */
1330   fail_unless (pix2 == pix1);
1331   gst_buffer_map (pix2, &map, GST_MAP_READ);
1332   data2 = map.data;
1333   /* make sure we got the initial data with adjusted alpha-channel */
1334 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1335   /* B - G - R - A */
1336   fail_unless_equals_int (data2[0], 0x80);
1337   fail_unless_equals_int (data2[1], 0x80);
1338   fail_unless_equals_int (data2[2], 0x80);
1339   fail_unless_equals_int (data2[3], 0x40);
1340 #else
1341   /* A - R - G - B */
1342   fail_unless_equals_int (data2[0], 0x40);
1343   fail_unless_equals_int (data2[1], 0x80);
1344   fail_unless_equals_int (data2[2], 0x80);
1345   fail_unless_equals_int (data2[3], 0x80);
1346 #endif
1347   gst_buffer_unmap (pix2, &map);
1348
1349   /* adjust global_alpha once more */
1350   gst_video_overlay_rectangle_set_global_alpha (rect1, 0.25);
1351   ga2 = gst_video_overlay_rectangle_get_global_alpha (rect1);
1352   fail_unless_equals_float (ga2, 0.25);
1353   /* and again request unscaled pixel-data, global-alpha applied */
1354   pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1355       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1356   fail_unless (pix2 == pix1);
1357   /* make sure we got the initial data with adjusted alpha-channel */
1358   gst_buffer_map (pix2, &map, GST_MAP_READ);
1359   data2 = map.data;
1360 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1361   /* B - G - R - A */
1362   fail_unless_equals_int (data2[0], 0x80);
1363   fail_unless_equals_int (data2[1], 0x80);
1364   fail_unless_equals_int (data2[2], 0x80);
1365   fail_unless_equals_int (data2[3], 0x20);
1366 #else
1367   /* A - R - G - B */
1368   fail_unless_equals_int (data2[0], 0x20);
1369   fail_unless_equals_int (data2[1], 0x80);
1370   fail_unless_equals_int (data2[2], 0x80);
1371   fail_unless_equals_int (data2[3], 0x80);
1372 #endif
1373   gst_buffer_unmap (pix2, &map);
1374
1375   /* again: unscaled pixel-data, global-alpha not applied,
1376    * this should revert alpha-channel to initial values */
1377   pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1378       GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1379   fail_unless (pix2 == pix1);
1380   /* make sure we got the initial data (input=0x80808080) */
1381   gst_buffer_map (pix2, &map, GST_MAP_READ);
1382   data2 = map.data;
1383 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1384   /* B - G - R - A */
1385   fail_unless_equals_int (data2[0], 0x80);
1386   fail_unless_equals_int (data2[1], 0x80);
1387   fail_unless_equals_int (data2[2], 0x80);
1388   fail_unless_equals_int (data2[3], 0x80);
1389 #else
1390   /* A - R - G - B */
1391   fail_unless_equals_int (data2[0], 0x80);
1392   fail_unless_equals_int (data2[1], 0x80);
1393   fail_unless_equals_int (data2[2], 0x80);
1394   fail_unless_equals_int (data2[3], 0x80);
1395 #endif
1396   gst_buffer_unmap (pix2, &map);
1397
1398   /* now scaled, global-alpha not applied */
1399   pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1400       GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1401   /* this should just return the rect/buffer, that was cached for these
1402    * scaling dimensions */
1403   fail_unless (pix2 == pix3);
1404   /* make sure we got the initial data (input=0x80808080) */
1405   gst_buffer_map (pix2, &map, GST_MAP_READ);
1406   data2 = map.data;
1407 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1408   /* B - G - R - A */
1409   fail_unless_equals_int (data2[0], 0x80);
1410   fail_unless_equals_int (data2[1], 0x80);
1411   fail_unless_equals_int (data2[2], 0x80);
1412   fail_unless_equals_int (data2[3], 0x80);
1413 #else
1414   /* A - R - G - B */
1415   fail_unless_equals_int (data2[0], 0x80);
1416   fail_unless_equals_int (data2[1], 0x80);
1417   fail_unless_equals_int (data2[2], 0x80);
1418   fail_unless_equals_int (data2[3], 0x80);
1419 #endif
1420   gst_buffer_unmap (pix2, &map);
1421
1422   /* scaled, global-alpha (0.25) applied */
1423   pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1424       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1425   /* this should just return the rect/buffer, that was cached for these
1426    * scaling dimensions with modified alpha channel */
1427   fail_unless (pix2 == pix3);
1428   /* make sure we got the data we expect for global-alpha=0.25 */
1429   gst_buffer_map (pix2, &map, GST_MAP_READ);
1430   data2 = map.data;
1431 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1432   /* B - G - R - A */
1433   fail_unless_equals_int (data2[0], 0x80);
1434   fail_unless_equals_int (data2[1], 0x80);
1435   fail_unless_equals_int (data2[2], 0x80);
1436   fail_unless_equals_int (data2[3], 0x20);
1437 #else
1438   /* A - R - G - B */
1439   fail_unless_equals_int (data2[0], 0x20);
1440   fail_unless_equals_int (data2[1], 0x80);
1441   fail_unless_equals_int (data2[2], 0x80);
1442   fail_unless_equals_int (data2[3], 0x80);
1443 #endif
1444   gst_buffer_unmap (pix2, &map);
1445
1446   /* now unscaled premultiplied data, global-alpha not applied,
1447    * is this really a valid use case?*/
1448   pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1449       GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA |
1450       GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1451   /* this should just return the rect/buffer, that was cached for the
1452    * premultiplied data */
1453   fail_unless (pix2 == pix4);
1454   /* make sure we got what we expected */
1455   gst_buffer_map (pix2, &map, GST_MAP_READ);
1456   data2 = map.data;
1457 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1458   /* B - G - R - A */
1459   fail_unless_equals_int (data2[0], 0x40);
1460   fail_unless_equals_int (data2[1], 0x40);
1461   fail_unless_equals_int (data2[2], 0x40);
1462   fail_unless_equals_int (data2[3], 0x80);
1463 #else
1464   /* A - R - G - B */
1465   fail_unless_equals_int (data2[0], 0x80);
1466   fail_unless_equals_int (data2[1], 0x40);
1467   fail_unless_equals_int (data2[2], 0x40);
1468   fail_unless_equals_int (data2[3], 0x40);
1469 #endif
1470   gst_buffer_unmap (pix2, &map);
1471
1472   /* unscaled premultiplied data, global-alpha (0.25) applied */
1473   pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1474       GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1475   /* this should just return the rect/buffer, that was cached for the
1476    * premultiplied data */
1477   fail_unless (pix2 == pix4);
1478   /* make sure we got what we expected:
1479    * (0x40 / (0x80/0xFF) * (0x20/0xFF) = 0x10
1480    * NOTE: unless we are using round() for the premultiplied case
1481    * in gst_video_overlay_rectangle_apply_global_alpha() we get rounding
1482    * error, i.e. 0x0F here */
1483   gst_buffer_map (pix2, &map, GST_MAP_READ);
1484   data2 = map.data;
1485 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1486   /* B - G - R - A */
1487   fail_unless_equals_int (data2[0], 0x0F);
1488   fail_unless_equals_int (data2[1], 0x0F);
1489   fail_unless_equals_int (data2[2], 0x0F);
1490   fail_unless_equals_int (data2[3], 0x20);
1491 #else
1492   /* A - R - G - B */
1493   fail_unless_equals_int (data2[0], 0x20);
1494   fail_unless_equals_int (data2[1], 0x0F);
1495   fail_unless_equals_int (data2[2], 0x0F);
1496   fail_unless_equals_int (data2[3], 0x0F);
1497 #endif
1498   gst_buffer_unmap (pix2, &map);
1499
1500   /* set global_alpha once more */
1501   gst_video_overlay_rectangle_set_global_alpha (rect1, 0.75);
1502   /* and verify that also premultiplied data is adjusted
1503    * correspondingly (though with increasing rounding errors) */
1504   pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1505       GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1506   /* this should just return the rect/buffer, that was cached for the
1507    * premultiplied data */
1508   fail_unless (pix2 == pix4);
1509   /* make sure we got what we expected:
1510    * (0x0F / (0x20/0xFF) * (0x60/0xFF) = 0x2D
1511    * NOTE: using floats everywhere we would get 0x30
1512    * here we will actually end up with 0x2C */
1513   gst_buffer_map (pix2, &map, GST_MAP_READ);
1514   data2 = map.data;
1515 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1516   /* B - G - R - A */
1517   fail_unless_equals_int (data2[0], 0x2C);
1518   fail_unless_equals_int (data2[1], 0x2C);
1519   fail_unless_equals_int (data2[2], 0x2C);
1520   fail_unless_equals_int (data2[3], 0x60);
1521 #else
1522   /* A - R - G - B */
1523   fail_unless_equals_int (data2[0], 0x60);
1524   fail_unless_equals_int (data2[1], 0x2C);
1525   fail_unless_equals_int (data2[2], 0x2C);
1526   fail_unless_equals_int (data2[3], 0x2C);
1527 #endif
1528   gst_buffer_unmap (pix2, &map);
1529
1530   /* now scaled and premultiplied data, global-alpha not applied,
1531    * is this really a valid use case?*/
1532   pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1533       GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA |
1534       GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1535   /* this should just return the rect/buffer, that was cached for the
1536    * first premultiplied+scaled rect*/
1537   fail_unless (pix2 == pix5);
1538   /* make sure we got what we expected */
1539   gst_buffer_map (pix2, &map, GST_MAP_READ);
1540   data2 = map.data;
1541 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1542   /* B - G - R - A */
1543   fail_unless_equals_int (data2[0], 0x40);
1544   fail_unless_equals_int (data2[1], 0x40);
1545   fail_unless_equals_int (data2[2], 0x40);
1546   fail_unless_equals_int (data2[3], 0x80);
1547 #else
1548   /* A - R - G - B */
1549   fail_unless_equals_int (data2[0], 0x80);
1550   fail_unless_equals_int (data2[1], 0x40);
1551   fail_unless_equals_int (data2[2], 0x40);
1552   fail_unless_equals_int (data2[3], 0x40);
1553 #endif
1554   gst_buffer_unmap (pix2, &map);
1555
1556   /* scaled and premultiplied data, global-alpha applied */
1557   pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1558       GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1559   /* this should just return the rect/buffer, that was cached for the
1560    * first premultiplied+scaled rect*/
1561   fail_unless (pix2 == pix5);
1562   /* make sure we got what we expected; see above note about rounding errors! */
1563   gst_buffer_map (pix2, &map, GST_MAP_READ);
1564   data2 = map.data;
1565 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1566   /* B - G - R - A */
1567   fail_unless_equals_int (data2[0], 0x2F);
1568   fail_unless_equals_int (data2[1], 0x2F);
1569   fail_unless_equals_int (data2[2], 0x2F);
1570   fail_unless_equals_int (data2[3], 0x60);
1571 #else
1572   /* A - R - G - B */
1573   fail_unless_equals_int (data2[0], 0x60);
1574   fail_unless_equals_int (data2[1], 0x2F);
1575   fail_unless_equals_int (data2[2], 0x2F);
1576   fail_unless_equals_int (data2[3], 0x2F);
1577 #endif
1578   gst_buffer_unmap (pix2, &map);
1579
1580   gst_video_overlay_rectangle_unref (rect1);
1581 }
1582
1583 GST_END_TEST;
1584
1585 static Suite *
1586 video_suite (void)
1587 {
1588   Suite *s = suite_create ("video support library");
1589   TCase *tc_chain = tcase_create ("general");
1590
1591   suite_add_tcase (s, tc_chain);
1592   tcase_add_test (tc_chain, test_video_formats);
1593   tcase_add_test (tc_chain, test_video_formats_rgb);
1594   tcase_add_test (tc_chain, test_video_formats_all);
1595   tcase_add_test (tc_chain, test_dar_calc);
1596   tcase_add_test (tc_chain, test_parse_caps_rgb);
1597   tcase_add_test (tc_chain, test_events);
1598   tcase_add_test (tc_chain, test_convert_frame);
1599   tcase_add_test (tc_chain, test_convert_frame_async);
1600   tcase_add_test (tc_chain, test_video_size_from_caps);
1601   tcase_add_test (tc_chain, test_overlay_composition);
1602   tcase_add_test (tc_chain, test_overlay_composition_premultiplied_alpha);
1603   tcase_add_test (tc_chain, test_overlay_composition_global_alpha);
1604
1605   return s;
1606 }
1607
1608 GST_CHECK_MAIN (video);