1 /* GStreamer unit test for video
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>
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.
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.
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., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
29 # include <valgrind/valgrind.h>
34 #include <gst/check/gstcheck.h>
36 #include <gst/video/video.h>
37 #include <gst/video/gstvideometa.h>
38 #include <gst/video/video-overlay-composition.h>
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
45 typedef struct paintinfo_struct paintinfo;
46 struct paintinfo_struct
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 */
60 struct fourcc_list_struct
65 void (*paint_setup) (paintinfo * p, unsigned char *dest);
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);
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);
85 static void paint_setup_YUV9 (paintinfo * p, unsigned char *dest);
86 static void paint_setup_YVU9 (paintinfo * p, unsigned char *dest);
88 int fourcc_get_size (struct fourcc_list_struct *fourcc, int w, int h);
90 struct fourcc_list_struct fourcc_list[] = {
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},
100 /*{ "IUYV", "IUY2", 16, paint_setup_YVYU }, */
103 /*{ "cyuv", "cyuv", 16, paint_setup_YVYU }, */
105 /*{ "Y41P", "Y41P", 12, paint_setup_YVYU }, */
108 /*{ "IY41", "IY41", 12, paint_setup_YVYU }, */
110 /*{ "Y211", "Y211", 8, paint_setup_YVYU }, */
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},
120 {"YVU9", "YVU9", 9, paint_setup_YVU9},
122 {"YUV9", "YUV9", 9, paint_setup_YUV9},
125 {"YV12", "YV12", 12, paint_setup_YV12},
127 {"I420", "I420", 12, paint_setup_I420},
132 {"IMC1", "IMC1", 16, paint_setup_IMC1},
134 {"IMC2", "IMC2", 12, paint_setup_IMC2},
136 {"IMC3", "IMC3", 16, paint_setup_IMC3},
138 {"IMC4", "IMC4", 12, paint_setup_IMC4},
142 {"Y41B", "Y41B", 12, paint_setup_Y41B},
144 {"Y42B", "Y42B", 16, paint_setup_Y42B},
145 /* GRAY8 grayscale */
146 {"GRAY8", "GRAY8", 8, paint_setup_GRAY8}
149 /* returns the size in bytes for one video frame of the given dimensions
150 * given the fourcc */
152 fourcc_get_size (struct fourcc_list_struct *fourcc, int w, int h)
154 paintinfo pi = { NULL, };
160 fourcc->paint_setup (p, NULL);
162 return (unsigned long) p->endptr;
166 paint_setup_I420 (paintinfo * p, unsigned char *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;
178 paint_setup_YV12 (paintinfo * p, unsigned char *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;
190 paint_setup_AYUV (paintinfo * p, unsigned char *dest)
196 p->ystride = p->width * 4;
197 p->endptr = dest + p->ystride * p->height;
201 paint_setup_YUY2 (paintinfo * p, unsigned char *dest)
206 p->ystride = GST_ROUND_UP_2 (p->width) * 2;
207 p->endptr = dest + p->ystride * p->height;
211 paint_setup_UYVY (paintinfo * p, unsigned char *dest)
216 p->ystride = GST_ROUND_UP_2 (p->width) * 2;
217 p->endptr = dest + p->ystride * p->height;
221 paint_setup_YVYU (paintinfo * p, unsigned char *dest)
226 p->ystride = GST_ROUND_UP_2 (p->width) * 2;
227 p->endptr = dest + p->ystride * p->height;
231 paint_setup_IYU2 (paintinfo * p, unsigned char *dest)
237 p->ystride = GST_ROUND_UP_4 (p->width * 3);
238 p->endptr = dest + p->ystride * p->height;
242 paint_setup_Y41B (paintinfo * p, unsigned char *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;
254 paint_setup_Y42B (paintinfo * p, unsigned char *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;
266 paint_setup_GRAY8 (paintinfo * p, unsigned char *dest)
270 p->ystride = GST_ROUND_UP_4 (p->width);
271 p->endptr = dest + p->ystride * p->height;
276 paint_setup_IMC1 (paintinfo * p, unsigned char *dest)
279 p->up = dest + p->width * p->height;
280 p->vp = dest + p->width * p->height + p->width * p->height / 2;
284 paint_setup_IMC2 (paintinfo * p, unsigned char *dest)
287 p->vp = dest + p->width * p->height;
288 p->up = dest + p->width * p->height + p->width / 2;
292 paint_setup_IMC3 (paintinfo * p, unsigned char *dest)
295 p->up = dest + p->width * p->height + p->width * p->height / 2;
296 p->vp = dest + p->width * p->height;
300 paint_setup_IMC4 (paintinfo * p, unsigned char *dest)
303 p->vp = dest + p->width * p->height + p->width / 2;
304 p->up = dest + p->width * p->height;
309 paint_setup_YVU9 (paintinfo * p, unsigned char *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);
321 paint_setup_YUV9 (paintinfo * p, unsigned char *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);
332 #define gst_video_format_is_packed video_format_is_packed
334 video_format_is_packed (GstVideoFormat 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:
345 case GST_VIDEO_FORMAT_IYU1:
346 case GST_VIDEO_FORMAT_IYU2:
347 case GST_VIDEO_FORMAT_YUY2:
348 case GST_VIDEO_FORMAT_YVYU:
349 case GST_VIDEO_FORMAT_UYVY:
350 case GST_VIDEO_FORMAT_VYUY:
351 case GST_VIDEO_FORMAT_AYUV:
352 case GST_VIDEO_FORMAT_RGBx:
353 case GST_VIDEO_FORMAT_BGRx:
354 case GST_VIDEO_FORMAT_xRGB:
355 case GST_VIDEO_FORMAT_xBGR:
356 case GST_VIDEO_FORMAT_RGBA:
357 case GST_VIDEO_FORMAT_BGRA:
358 case GST_VIDEO_FORMAT_ARGB:
359 case GST_VIDEO_FORMAT_ABGR:
360 case GST_VIDEO_FORMAT_RGB:
361 case GST_VIDEO_FORMAT_BGR:
362 case GST_VIDEO_FORMAT_RGB8P:
365 g_return_val_if_reached (FALSE);
371 get_num_formats (void)
373 gint num_formats = 100;
374 fail_unless (gst_video_format_to_string (num_formats) == NULL);
375 while (gst_video_format_to_string (num_formats) == NULL)
377 GST_INFO ("number of known video formats: %d", num_formats);
378 return num_formats + 1;
381 GST_START_TEST (test_video_formats_all)
384 const GValue *val, *list_val;
386 guint num, n, num_formats;
388 num_formats = get_num_formats ();
390 caps = gst_caps_from_string ("video/x-raw, format=" GST_VIDEO_FORMATS_ALL);
391 s = gst_caps_get_structure (caps, 0);
392 val = gst_structure_get_value (s, "format");
393 fail_unless (val != NULL);
394 fail_unless (GST_VALUE_HOLDS_LIST (val));
395 num = gst_value_list_get_size (val);
396 fail_unless (num > 0);
397 for (n = 0; n < num; ++n) {
398 const gchar *fmt_str;
400 list_val = gst_value_list_get_value (val, n);
401 fail_unless (G_VALUE_HOLDS_STRING (list_val));
402 fmt_str = g_value_get_string (list_val);
403 GST_INFO ("format: %s", fmt_str);
404 fail_if (gst_video_format_from_string (fmt_str) ==
405 GST_VIDEO_FORMAT_UNKNOWN);
407 /* Take into account GST_VIDEO_FORMAT_ENCODED and UNKNOWN */
408 fail_unless_equals_int (num, num_formats - 2);
410 gst_caps_unref (caps);
417 GST_START_TEST (test_video_formats_pack_unpack)
419 guint n, num_formats;
421 num_formats = get_num_formats ();
423 for (n = GST_VIDEO_FORMAT_ENCODED + 1; n < num_formats; ++n) {
424 const GstVideoFormatInfo *vfinfo, *unpackinfo;
425 GstVideoFormat fmt = n;
427 gpointer data[GST_VIDEO_MAX_PLANES];
428 gint stride[GST_VIDEO_MAX_PLANES];
429 guint8 *vdata, *unpack_data;
430 gsize vsize, unpack_size;
433 GST_INFO ("testing %s", gst_video_format_to_string (fmt));
435 vfinfo = gst_video_format_get_info (fmt);
436 fail_unless (vfinfo != NULL);
438 unpackinfo = gst_video_format_get_info (vfinfo->unpack_format);
439 fail_unless (unpackinfo != NULL);
441 gst_video_info_init (&vinfo);
442 gst_video_info_set_format (&vinfo, fmt, WIDTH, HEIGHT);
443 vsize = GST_VIDEO_INFO_SIZE (&vinfo);
444 vdata = g_malloc (vsize);
445 memset (vdata, 0x99, vsize);
447 g_assert (vfinfo->pack_lines == 1);
450 GST_VIDEO_FORMAT_INFO_BITS (unpackinfo) *
451 GST_VIDEO_FORMAT_INFO_N_COMPONENTS (unpackinfo) *
452 GST_ROUND_UP_16 (WIDTH);
453 unpack_data = g_malloc (unpack_size);
455 for (p = 0; p < GST_VIDEO_INFO_N_PLANES (&vinfo); ++p) {
456 data[p] = vdata + GST_VIDEO_INFO_PLANE_OFFSET (&vinfo, p);
457 stride[p] = GST_VIDEO_INFO_PLANE_STRIDE (&vinfo, p);
461 vfinfo->unpack_func (vfinfo, GST_VIDEO_PACK_FLAG_NONE, unpack_data, data,
462 stride, 0, 0, WIDTH);
465 vfinfo->pack_func (vfinfo, GST_VIDEO_PACK_FLAG_NONE, unpack_data,
466 unpack_size, data, stride, GST_VIDEO_CHROMA_SITE_UNKNOWN, 0, WIDTH);
469 vfinfo->unpack_func (vfinfo, GST_VIDEO_PACK_FLAG_NONE, unpack_data, data,
470 stride, 0, HEIGHT - 1, WIDTH);
473 vfinfo->pack_func (vfinfo, GST_VIDEO_PACK_FLAG_NONE, unpack_data,
474 unpack_size, data, stride, GST_VIDEO_CHROMA_SITE_UNKNOWN, HEIGHT - 1,
477 g_free (unpack_data);
486 GST_START_TEST (test_video_formats)
490 for (i = 0; i < G_N_ELEMENTS (fourcc_list); ++i) {
491 const GstVideoFormatInfo *vf_info;
497 s = fourcc_list[i].fourcc;
498 fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]);
499 fmt = gst_video_format_from_fourcc (fourcc);
501 if (fmt == GST_VIDEO_FORMAT_UNKNOWN) {
502 GST_DEBUG ("Unknown format %s, skipping tests", fourcc_list[i].fourcc);
506 vf_info = gst_video_format_get_info (fmt);
507 fail_unless (vf_info != NULL);
509 fail_unless_equals_int (GST_VIDEO_FORMAT_INFO_FORMAT (vf_info), fmt);
511 GST_INFO ("Fourcc %s, packed=%d", fourcc_list[i].fourcc,
512 gst_video_format_is_packed (fmt));
514 fail_unless (GST_VIDEO_FORMAT_INFO_IS_YUV (vf_info));
516 /* use any non-NULL pointer so we can compare against NULL */
518 paintinfo paintinfo = { 0, };
519 fourcc_list[i].paint_setup (&paintinfo, (unsigned char *) s);
520 if (paintinfo.ap != NULL) {
521 fail_unless (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vf_info));
523 fail_if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vf_info));
527 for (w = 1; w <= 65; ++w) {
528 for (h = 1; h <= 65; ++h) {
530 paintinfo paintinfo = { 0, };
531 guint off0, off1, off2, off3;
532 guint cs0, cs1, cs2, cs3;
535 GST_LOG ("%s, %dx%d", fourcc_list[i].fourcc, w, h);
537 gst_video_info_init (&vinfo);
538 gst_video_info_set_format (&vinfo, fmt, w, h);
541 paintinfo.height = h;
542 fourcc_list[i].paint_setup (&paintinfo, NULL);
543 fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 0),
545 if (!gst_video_format_is_packed (fmt)
546 && GST_VIDEO_INFO_N_PLANES (&vinfo) <= 2) {
548 fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 1),
550 fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 2),
552 /* check component_width * height against offsets/size somehow? */
555 size = GST_VIDEO_INFO_SIZE (&vinfo);
556 off0 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 0);
557 off1 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 1);
558 off2 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 2);
560 GST_INFO ("size %d <> %d", size, (int) ((guintptr) paintinfo.endptr));
561 GST_INFO ("off0 %d <> %d", off0, (int) ((guintptr) paintinfo.yp));
562 GST_INFO ("off1 %d <> %d", off1, (int) ((guintptr) paintinfo.up));
563 GST_INFO ("off2 %d <> %d", off2, (int) ((guintptr) paintinfo.vp));
565 fail_unless_equals_int (size, (unsigned long) paintinfo.endptr);
566 fail_unless_equals_int (off0, (unsigned long) paintinfo.yp);
567 fail_unless_equals_int (off1, (unsigned long) paintinfo.up);
568 fail_unless_equals_int (off2, (unsigned long) paintinfo.vp);
570 /* should be 0 if there's no alpha component */
571 off3 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 3);
572 fail_unless_equals_int (off3, (unsigned long) paintinfo.ap);
574 cs0 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 0) *
575 GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 0);
576 cs1 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 1) *
577 GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 1);
578 cs2 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 2) *
579 GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 2);
581 /* GST_LOG ("cs0=%d,cs1=%d,cs2=%d,off0=%d,off1=%d,off2=%d,size=%d",
582 cs0, cs1, cs2, off0, off1, off2, size); */
584 if (!gst_video_format_is_packed (fmt))
585 fail_unless (cs0 <= off1);
587 if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vinfo.finfo)) {
588 cs3 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 3) *
589 GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 2);
590 fail_unless (cs3 < size);
591 /* U/V/alpha shouldn't take up more space than the Y component */
592 fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0);
593 fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0);
594 fail_if (cs3 > cs0, "cs3 (%d) should be <= cs0 (%d)", cs3, cs0);
596 /* all components together shouldn't take up more space than size */
597 fail_unless (cs0 + cs1 + cs2 + cs3 <= size);
599 /* U/V shouldn't take up more space than the Y component */
600 fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0);
601 fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0);
603 /* all components together shouldn't take up more space than size */
604 fail_unless (cs0 + cs1 + cs2 <= size,
605 "cs0 (%d) + cs1 (%d) + cs2 (%d) should be <= size (%d)",
606 cs0, cs1, cs2, size);
615 GST_START_TEST (test_video_formats_overflow)
619 gst_video_info_init (&vinfo);
621 fail_unless (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, 32768,
623 /* fails due to simplification: we forbid some things that would in theory be fine.
624 * We assume a 128 byte alignment for the width currently
625 * fail_unless (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, 32767, 32768));
627 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, 32768,
630 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB,
631 G_MAXINT / 2, G_MAXINT));
632 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, G_MAXINT,
634 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB,
635 G_MAXINT / 2, G_MAXINT / 2));
636 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, G_MAXINT,
638 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB,
639 G_MAXUINT / 2, G_MAXUINT));
640 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, G_MAXUINT,
642 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB,
643 G_MAXUINT / 2, G_MAXUINT / 2));
644 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, G_MAXUINT,
647 fail_unless (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB,
648 1073741824 - 128, 1));
649 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, 1073741824,
656 GST_START_TEST (test_video_formats_rgb)
659 gint width, height, framerate_n, framerate_d, par_n, par_d;
661 GstStructure *structure;
663 gst_video_info_init (&vinfo);
664 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_RGB, 800, 600);
669 caps = gst_video_info_to_caps (&vinfo);
670 structure = gst_caps_get_structure (caps, 0);
672 fail_unless (gst_structure_get_int (structure, "width", &width));
673 fail_unless (gst_structure_get_int (structure, "height", &height));
674 fail_unless (gst_structure_get_fraction (structure, "framerate", &framerate_n,
676 fail_unless (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
679 fail_unless (width == 800);
680 fail_unless (height == 600);
681 fail_unless (framerate_n == 0);
682 fail_unless (framerate_d == 1);
683 fail_unless (par_n == 1);
684 fail_unless (par_d == 1);
686 gst_caps_unref (caps);
692 GST_START_TEST (test_video_formats_rgba_large_dimension)
695 gint width, height, framerate_n, framerate_d, par_n, par_d;
697 GstStructure *structure;
699 gst_video_info_init (&vinfo);
700 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_RGBA, 29700, 21000);
705 caps = gst_video_info_to_caps (&vinfo);
706 structure = gst_caps_get_structure (caps, 0);
708 fail_unless (gst_structure_get_int (structure, "width", &width));
709 fail_unless (gst_structure_get_int (structure, "height", &height));
710 fail_unless (gst_structure_get_fraction (structure, "framerate", &framerate_n,
712 fail_unless (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
715 fail_unless (width == 29700);
716 fail_unless (height == 21000);
717 fail_unless (framerate_n == 0);
718 fail_unless (framerate_d == 1);
719 fail_unless (par_n == 1);
720 fail_unless (par_d == 1);
721 fail_unless (vinfo.size == (gsize) 29700 * 21000 * 4);
723 gst_caps_unref (caps);
728 GST_START_TEST (test_dar_calc)
730 guint display_ratio_n, display_ratio_d;
732 /* Ensure that various Display Ratio calculations are correctly done */
733 /* video 768x576, par 16/15, display par 16/15 = 4/3 */
734 fail_unless (gst_video_calculate_display_ratio (&display_ratio_n,
735 &display_ratio_d, 768, 576, 16, 15, 16, 15));
736 fail_unless (display_ratio_n == 4 && display_ratio_d == 3);
738 /* video 720x480, par 32/27, display par 1/1 = 16/9 */
739 fail_unless (gst_video_calculate_display_ratio (&display_ratio_n,
740 &display_ratio_d, 720, 480, 32, 27, 1, 1));
741 fail_unless (display_ratio_n == 16 && display_ratio_d == 9);
743 /* video 360x288, par 533333/500000, display par 16/15 =
744 * dar 1599999/1600000 */
745 fail_unless (gst_video_calculate_display_ratio (&display_ratio_n,
746 &display_ratio_d, 360, 288, 533333, 500000, 16, 15));
747 fail_unless (display_ratio_n == 1599999 && display_ratio_d == 1280000);
752 GST_START_TEST (test_parse_caps_rgb)
756 const gchar *tmpl_caps_string;
761 GST_VIDEO_CAPS_MAKE ("RGB"), GST_VIDEO_FORMAT_RGB}, {
762 GST_VIDEO_CAPS_MAKE ("BGR"), GST_VIDEO_FORMAT_BGR},
763 /* 32 bit (no alpha) */
765 GST_VIDEO_CAPS_MAKE ("RGBx"), GST_VIDEO_FORMAT_RGBx}, {
766 GST_VIDEO_CAPS_MAKE ("xRGB"), GST_VIDEO_FORMAT_xRGB}, {
767 GST_VIDEO_CAPS_MAKE ("BGRx"), GST_VIDEO_FORMAT_BGRx}, {
768 GST_VIDEO_CAPS_MAKE ("xBGR"), GST_VIDEO_FORMAT_xBGR},
769 /* 32 bit (with alpha) */
771 GST_VIDEO_CAPS_MAKE ("RGBA"), GST_VIDEO_FORMAT_RGBA}, {
772 GST_VIDEO_CAPS_MAKE ("ARGB"), GST_VIDEO_FORMAT_ARGB}, {
773 GST_VIDEO_CAPS_MAKE ("BGRA"), GST_VIDEO_FORMAT_BGRA}, {
774 GST_VIDEO_CAPS_MAKE ("ABGR"), GST_VIDEO_FORMAT_ABGR},
777 GST_VIDEO_CAPS_MAKE ("RGB16"), GST_VIDEO_FORMAT_RGB16}, {
778 GST_VIDEO_CAPS_MAKE ("BGR16"), GST_VIDEO_FORMAT_BGR16}, {
779 GST_VIDEO_CAPS_MAKE ("RGB15"), GST_VIDEO_FORMAT_RGB15}, {
780 GST_VIDEO_CAPS_MAKE ("BGR15"), GST_VIDEO_FORMAT_BGR15}
784 for (i = 0; i < G_N_ELEMENTS (formats); ++i) {
786 GstCaps *caps, *caps2;
788 caps = gst_caps_from_string (formats[i].tmpl_caps_string);
789 fail_unless (caps != NULL);
790 gst_caps_set_simple (caps, "width", G_TYPE_INT, 2 * (i + 1), "height",
791 G_TYPE_INT, i + 1, "framerate", GST_TYPE_FRACTION, 15, 1,
792 "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
793 "interlace-mode", G_TYPE_STRING, "progressive",
794 "colorimetry", G_TYPE_STRING, "1:1:0:0",
795 "multiview-mode", G_TYPE_STRING, "mono",
796 "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET, 0,
797 GST_FLAG_SET_MASK_EXACT, NULL);
798 g_assert (gst_caps_is_fixed (caps));
800 GST_DEBUG ("testing caps: %" GST_PTR_FORMAT, caps);
802 gst_video_info_init (&vinfo);
803 fail_unless (gst_video_info_from_caps (&vinfo, caps));
804 fail_unless_equals_int (GST_VIDEO_INFO_FORMAT (&vinfo), formats[i].fmt);
805 fail_unless_equals_int (GST_VIDEO_INFO_WIDTH (&vinfo), 2 * (i + 1));
806 fail_unless_equals_int (GST_VIDEO_INFO_HEIGHT (&vinfo), i + 1);
808 /* make sure they're serialised back correctly */
809 caps2 = gst_video_info_to_caps (&vinfo);
810 fail_unless (caps2 != NULL);
811 if (!gst_caps_is_equal (caps, caps2)) {
812 gchar *caps1s = gst_caps_to_string (caps);
813 gchar *caps2s = gst_caps_to_string (caps2);
814 fail ("caps [%s] not equal to caps2 [%s]", caps1s, caps2s);
819 gst_caps_unref (caps);
820 gst_caps_unref (caps2);
826 GST_START_TEST (test_parse_caps_multiview)
829 GstVideoMultiviewMode modes[] = {
830 GST_VIDEO_MULTIVIEW_MODE_MONO,
831 GST_VIDEO_MULTIVIEW_MODE_LEFT,
832 GST_VIDEO_MULTIVIEW_MODE_RIGHT,
833 GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE,
834 GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX,
835 GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED,
836 GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED,
837 GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM,
838 GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD,
839 GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME,
840 GST_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME,
841 GST_VIDEO_MULTIVIEW_MODE_SEPARATED,
843 GstVideoMultiviewFlags flags[] = {
844 GST_VIDEO_MULTIVIEW_FLAGS_NONE,
845 GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST,
846 GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED,
847 GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED,
848 GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED,
849 GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED,
850 GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO,
851 GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO |
852 GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST,
853 GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO |
854 GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED
857 for (i = 0; i < G_N_ELEMENTS (modes); i++) {
858 for (j = 0; j < G_N_ELEMENTS (flags); j++) {
862 gst_video_info_init (&vinfo);
863 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_I420, 320, 240);
865 GST_VIDEO_INFO_MULTIVIEW_MODE (&vinfo) = modes[i];
866 GST_VIDEO_INFO_MULTIVIEW_FLAGS (&vinfo) = flags[j];
868 caps = gst_video_info_to_caps (&vinfo);
869 fail_if (caps == NULL);
870 GST_LOG ("mview mode %d flags %x -> caps %" GST_PTR_FORMAT,
871 modes[i], flags[j], caps);
873 fail_unless (gst_video_info_from_caps (&vinfo, caps));
875 GST_LOG ("mview mode %d flags %x -> info mode %d flags %x",
876 modes[i], flags[j], GST_VIDEO_INFO_MULTIVIEW_MODE (&vinfo),
877 GST_VIDEO_INFO_MULTIVIEW_FLAGS (&vinfo));
879 fail_unless (GST_VIDEO_INFO_MULTIVIEW_MODE (&vinfo) == modes[i],
880 "Expected multiview mode %d got mode %d", modes[i],
881 GST_VIDEO_INFO_MULTIVIEW_MODE (&vinfo));
882 fail_unless (GST_VIDEO_INFO_MULTIVIEW_FLAGS (&vinfo) == flags[j],
883 "Expected multiview flags 0x%x got 0x%x", flags[j],
884 GST_VIDEO_INFO_MULTIVIEW_FLAGS (&vinfo));
886 gst_caps_unref (caps);
895 const gchar *string_from;
896 const gchar *string_to;
898 GstVideoColorimetry color;
901 #define MAKE_COLORIMETRY_TEST(s1,s2,n,r,m,t,p) { s1, s2, n, \
902 { GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \
903 GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p } }
905 GST_START_TEST (test_parse_colorimetry)
907 ColorimetryTest tests[] = {
908 MAKE_COLORIMETRY_TEST ("bt601", "bt601", "bt601",
909 _16_235, BT601, BT709, SMPTE170M),
910 MAKE_COLORIMETRY_TEST ("2:4:5:4", "bt601", "bt601",
911 _16_235, BT601, BT709, SMPTE170M),
912 MAKE_COLORIMETRY_TEST ("bt709", "bt709", "bt709",
913 _16_235, BT709, BT709, BT709),
914 MAKE_COLORIMETRY_TEST ("smpte240m", "smpte240m", "smpte240m",
915 _16_235, SMPTE240M, SMPTE240M, SMPTE240M),
916 MAKE_COLORIMETRY_TEST ("sRGB", "sRGB", "sRGB",
917 _0_255, RGB, SRGB, BT709),
918 MAKE_COLORIMETRY_TEST ("bt2020", "bt2020", "bt2020",
919 _16_235, BT2020, BT2020_12, BT2020),
920 MAKE_COLORIMETRY_TEST ("1:4:0:0", "1:4:0:0", NULL,
921 _0_255, BT601, UNKNOWN, UNKNOWN),
925 for (i = 0; i < G_N_ELEMENTS (tests); i++) {
926 const ColorimetryTest *test = &tests[i];
927 GstVideoColorimetry color;
930 fail_unless (gst_video_colorimetry_from_string (&color, test->string_from));
931 fail_unless_equals_int (color.range, test->color.range);
932 fail_unless_equals_int (color.matrix, test->color.matrix);
933 fail_unless_equals_int (color.transfer, test->color.transfer);
934 fail_unless_equals_int (color.primaries, test->color.primaries);
936 string = gst_video_colorimetry_to_string (&color);
937 fail_unless_equals_string (string, test->string_to);
940 fail_unless (gst_video_colorimetry_is_equal (&color, &test->color));
943 fail_unless (gst_video_colorimetry_matches (&color, test->name));
949 GST_START_TEST (test_events)
954 e = gst_video_event_new_still_frame (TRUE);
955 fail_if (e == NULL, "Failed to create still frame event");
956 fail_unless (gst_video_event_parse_still_frame (e, &in_still),
957 "Failed to parse still frame event");
958 fail_unless (gst_video_event_parse_still_frame (e, NULL),
959 "Failed to parse still frame event w/ in_still == NULL");
960 fail_unless (in_still == TRUE);
963 e = gst_video_event_new_still_frame (FALSE);
964 fail_if (e == NULL, "Failed to create still frame event");
965 fail_unless (gst_video_event_parse_still_frame (e, &in_still),
966 "Failed to parse still frame event");
967 fail_unless (gst_video_event_parse_still_frame (e, NULL),
968 "Failed to parse still frame event w/ in_still == NULL");
969 fail_unless (in_still == FALSE);
975 GST_START_TEST (test_convert_frame)
978 GstCaps *from_caps, *to_caps;
979 GstBuffer *from_buffer;
980 GstSample *from_sample, *to_sample;
981 GError *error = NULL;
985 gst_debug_set_threshold_for_name ("default", GST_LEVEL_NONE);
987 from_buffer = gst_buffer_new_and_alloc (640 * 480 * 4);
989 gst_buffer_map (from_buffer, &map, GST_MAP_WRITE);
990 for (i = 0; i < 640 * 480; i++) {
991 map.data[4 * i + 0] = 0; /* x */
992 map.data[4 * i + 1] = 255; /* R */
993 map.data[4 * i + 2] = 0; /* G */
994 map.data[4 * i + 3] = 0; /* B */
996 gst_buffer_unmap (from_buffer, &map);
998 gst_video_info_init (&vinfo);
999 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_xRGB, 640, 480);
1004 from_caps = gst_video_info_to_caps (&vinfo);
1006 from_sample = gst_sample_new (from_buffer, from_caps, NULL, NULL);
1009 gst_caps_from_string
1010 ("something/that, does=(string)not, exist=(boolean)FALSE");
1013 gst_video_convert_sample (from_sample, to_caps,
1014 GST_CLOCK_TIME_NONE, &error);
1015 fail_if (to_sample != NULL);
1016 fail_unless (error != NULL);
1017 g_error_free (error);
1020 gst_caps_unref (to_caps);
1021 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_I420, 240, 320);
1026 to_caps = gst_video_info_to_caps (&vinfo);
1029 gst_video_convert_sample (from_sample, to_caps,
1030 GST_CLOCK_TIME_NONE, &error);
1031 fail_unless (to_sample != NULL);
1032 fail_unless (error == NULL);
1034 gst_buffer_unref (from_buffer);
1035 gst_caps_unref (from_caps);
1036 gst_sample_unref (from_sample);
1037 gst_sample_unref (to_sample);
1038 gst_caps_unref (to_caps);
1048 } ConvertFrameContext;
1051 convert_sample_async_callback (GstSample * sample, GError * err,
1052 ConvertFrameContext * cf_data)
1054 cf_data->sample = sample;
1055 cf_data->error = err;
1057 g_main_loop_quit (cf_data->loop);
1060 GST_START_TEST (test_convert_frame_async)
1063 GstCaps *from_caps, *to_caps;
1064 GstBuffer *from_buffer;
1065 GstSample *from_sample;
1069 ConvertFrameContext cf_data = { NULL, NULL, NULL };
1071 gst_debug_set_threshold_for_name ("default", GST_LEVEL_NONE);
1073 from_buffer = gst_buffer_new_and_alloc (640 * 480 * 4);
1075 gst_buffer_map (from_buffer, &map, GST_MAP_WRITE);
1076 for (i = 0; i < 640 * 480; i++) {
1077 map.data[4 * i + 0] = 0; /* x */
1078 map.data[4 * i + 1] = 255; /* R */
1079 map.data[4 * i + 2] = 0; /* G */
1080 map.data[4 * i + 3] = 0; /* B */
1082 gst_buffer_unmap (from_buffer, &map);
1084 gst_video_info_init (&vinfo);
1085 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_xRGB, 640, 470);
1090 from_caps = gst_video_info_to_caps (&vinfo);
1093 gst_caps_from_string
1094 ("something/that, does=(string)not, exist=(boolean)FALSE");
1096 loop = cf_data.loop = g_main_loop_new (NULL, FALSE);
1098 from_sample = gst_sample_new (from_buffer, from_caps, NULL, NULL);
1099 gst_buffer_unref (from_buffer);
1100 gst_caps_unref (from_caps);
1102 gst_video_convert_sample_async (from_sample, to_caps,
1103 GST_CLOCK_TIME_NONE,
1104 (GstVideoConvertSampleCallback) convert_sample_async_callback, &cf_data,
1107 g_main_loop_run (loop);
1109 fail_if (cf_data.sample != NULL);
1110 fail_unless (cf_data.error != NULL);
1111 g_error_free (cf_data.error);
1112 cf_data.error = NULL;
1114 gst_caps_unref (to_caps);
1115 gst_video_info_init (&vinfo);
1116 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_I420, 240, 320);
1121 to_caps = gst_video_info_to_caps (&vinfo);
1122 gst_video_convert_sample_async (from_sample, to_caps,
1123 GST_CLOCK_TIME_NONE,
1124 (GstVideoConvertSampleCallback) convert_sample_async_callback, &cf_data,
1126 g_main_loop_run (loop);
1127 fail_unless (cf_data.sample != NULL);
1128 fail_unless (cf_data.error == NULL);
1130 gst_sample_unref (cf_data.sample);
1131 gst_caps_unref (to_caps);
1132 gst_sample_unref (from_sample);
1134 g_main_loop_unref (loop);
1139 GST_START_TEST (test_video_size_from_caps)
1144 caps = gst_caps_new_simple ("video/x-raw",
1145 "format", G_TYPE_STRING, "YV12",
1146 "width", G_TYPE_INT, 640,
1147 "height", G_TYPE_INT, 480, "framerate", GST_TYPE_FRACTION, 25, 1, NULL);
1149 gst_video_info_init (&vinfo);
1150 fail_unless (gst_video_info_from_caps (&vinfo, caps));
1151 fail_unless (GST_VIDEO_INFO_SIZE (&vinfo) == (640 * 480 * 12 / 8));
1153 gst_caps_unref (caps);
1158 GST_START_TEST (test_overlay_composition)
1160 GstVideoOverlayComposition *comp1, *comp2;
1161 GstVideoOverlayRectangle *rect1, *rect2;
1162 GstVideoOverlayCompositionMeta *ometa;
1163 GstBuffer *pix1, *pix2, *buf;
1164 GstVideoMeta *vmeta;
1170 pix1 = gst_buffer_new_and_alloc (200 * sizeof (guint32) * 50);
1171 gst_buffer_memset (pix1, 0, 0, gst_buffer_get_size (pix1));
1173 gst_buffer_add_video_meta (pix1, GST_VIDEO_FRAME_FLAG_NONE,
1174 GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB, 200, 50);
1175 rect1 = gst_video_overlay_rectangle_new_raw (pix1,
1176 600, 50, 300, 50, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1178 gst_buffer_unref (pix1);
1181 comp1 = gst_video_overlay_composition_new (rect1);
1182 fail_unless (gst_video_overlay_composition_n_rectangles (comp1) == 1);
1183 fail_unless (gst_video_overlay_composition_get_rectangle (comp1, 0) == rect1);
1184 fail_unless (gst_video_overlay_composition_get_rectangle (comp1, 1) == NULL);
1186 /* rectangle was created first, sequence number should be smaller */
1187 seq1 = gst_video_overlay_rectangle_get_seqnum (rect1);
1188 seq2 = gst_video_overlay_composition_get_seqnum (comp1);
1189 fail_unless (seq1 < seq2);
1191 /* composition took own ref, so refcount is 2 now, so this should fail */
1192 ASSERT_CRITICAL (gst_video_overlay_rectangle_set_render_rectangle (rect1, 50,
1195 /* drop our ref, so refcount is 1 (we know it will continue to be valid) */
1196 gst_video_overlay_rectangle_unref (rect1);
1197 gst_video_overlay_rectangle_set_render_rectangle (rect1, 50, 600, 300, 50);
1199 comp2 = gst_video_overlay_composition_new (rect1);
1200 fail_unless (gst_video_overlay_composition_n_rectangles (comp2) == 1);
1201 fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 0) == rect1);
1202 fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 1) == NULL);
1204 fail_unless (seq1 < gst_video_overlay_composition_get_seqnum (comp2));
1205 fail_unless (seq2 < gst_video_overlay_composition_get_seqnum (comp2));
1207 /* now refcount is 2 again because comp2 has also taken a ref, so must fail */
1208 ASSERT_CRITICAL (gst_video_overlay_rectangle_set_render_rectangle (rect1, 0,
1211 /* this should make a copy of the rectangles so drop the original
1212 * second ref on rect1 */
1213 comp2 = gst_video_overlay_composition_make_writable (comp2);
1214 gst_video_overlay_rectangle_set_render_rectangle (rect1, 51, 601, 301, 51);
1216 rect2 = gst_video_overlay_composition_get_rectangle (comp2, 0);
1217 fail_unless (gst_video_overlay_composition_n_rectangles (comp2) == 1);
1218 fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 0) == rect2);
1219 fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 1) == NULL);
1220 fail_unless (rect1 != rect2);
1222 gst_video_overlay_composition_add_rectangle (comp1, rect2);
1223 gst_video_overlay_composition_ref (comp1);
1224 ASSERT_CRITICAL (gst_video_overlay_composition_add_rectangle (comp1, rect2));
1225 gst_video_overlay_composition_unref (comp1);
1227 /* make sure the copy really worked */
1228 gst_video_overlay_rectangle_get_render_rectangle (rect1, &x, &y, &w, &h);
1229 fail_unless_equals_int (x, 51);
1230 fail_unless_equals_int (y, 601);
1231 fail_unless_equals_int (w, 301);
1232 fail_unless_equals_int (h, 51);
1234 /* get scaled pixbuf and touch last byte */
1235 pix1 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1236 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1238 fail_unless (gst_buffer_get_size (pix1) > ((h - 1) * stride + (w * 4) - 1),
1239 "size %u vs. last pixel offset %u", gst_buffer_get_size (pix1),
1240 ((h - 1) * stride + (w * 4) - 1));
1241 gst_buffer_extract (pix1, ((h - 1) * stride + (w * 4) - 1), &val, 1);
1242 fail_unless_equals_int (val, 0);
1244 gst_video_overlay_rectangle_get_render_rectangle (rect2, &x, &y, &w, &h);
1245 fail_unless_equals_int (x, 50);
1246 fail_unless_equals_int (y, 600);
1247 fail_unless_equals_int (w, 300);
1248 fail_unless_equals_int (h, 50);
1250 /* get scaled pixbuf and touch last byte */
1251 pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect2,
1252 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1254 fail_unless (gst_buffer_get_size (pix2) > ((h - 1) * stride + (w * 4) - 1),
1255 "size %u vs. last pixel offset %u", gst_buffer_get_size (pix1),
1256 ((h - 1) * stride + (w * 4) - 1));
1257 gst_buffer_extract (pix2, ((h - 1) * stride + (w * 4) - 1), &val, 1);
1258 fail_unless_equals_int (val, 0);
1260 /* get scaled pixbuf again, should be the same buffer as before (caching) */
1261 pix1 = gst_video_overlay_rectangle_get_pixels_raw (rect2,
1262 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1263 fail_unless (pix1 == pix2);
1265 /* get in different format */
1266 pix1 = gst_video_overlay_rectangle_get_pixels_ayuv (rect2,
1267 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1268 fail_unless (pix1 != pix2);
1269 /* get it again, should be same (caching) */
1270 pix2 = gst_video_overlay_rectangle_get_pixels_ayuv (rect2,
1271 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1272 fail_unless (pix1 == pix2);
1273 /* get unscaled, should be different */
1274 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_ayuv (rect2,
1275 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1276 fail_unless (pix1 != pix2);
1277 /* but should be cached */
1278 pix1 = gst_video_overlay_rectangle_get_pixels_unscaled_ayuv (rect2,
1279 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1280 fail_unless (pix1 == pix2);
1282 vmeta = gst_buffer_get_video_meta (pix1);
1283 fail_unless (vmeta != NULL);
1286 fail_unless_equals_int (w, 200);
1287 fail_unless_equals_int (h, 50);
1288 fail_unless_equals_int (vmeta->format,
1289 GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_YUV);
1290 fail_unless (gst_buffer_get_size (pix1) == w * h * 4);
1291 gst_buffer_extract (pix1, 0, &seq1, 4);
1292 fail_unless (seq1 != 0);
1294 /* now compare the original unscaled ones */
1295 pix1 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1296 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1297 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect2,
1298 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1300 vmeta = gst_buffer_get_video_meta (pix2);
1301 fail_unless (vmeta != NULL);
1305 /* the original pixel buffers should be identical */
1306 fail_unless (pix1 == pix2);
1307 fail_unless_equals_int (w, 200);
1308 fail_unless_equals_int (h, 50);
1311 /* touch last byte */
1312 fail_unless (gst_buffer_get_size (pix1) > ((h - 1) * stride + (w * 4) - 1),
1313 "size %u vs. last pixel offset %u", gst_buffer_get_size (pix1),
1314 ((h - 1) * stride + (w * 4) - 1));
1315 gst_buffer_extract (pix1, ((h - 1) * stride + (w * 4) - 1), &val, 1);
1316 fail_unless_equals_int (val, 0);
1318 /* test attaching and retrieving of compositions to/from buffers */
1319 buf = gst_buffer_new ();
1320 fail_unless (gst_buffer_get_video_overlay_composition_meta (buf) == NULL);
1322 gst_buffer_ref (buf);
1323 /* buffer now has refcount of 2, so its metadata is not writable.
1324 * only check this if we are not running in valgrind, as it leaks */
1325 #ifdef HAVE_VALGRIND
1326 if (!RUNNING_ON_VALGRIND) {
1327 ASSERT_CRITICAL (gst_buffer_add_video_overlay_composition_meta (buf,
1331 gst_buffer_unref (buf);
1332 gst_buffer_add_video_overlay_composition_meta (buf, comp1);
1333 ometa = gst_buffer_get_video_overlay_composition_meta (buf);
1334 fail_unless (ometa != NULL);
1335 fail_unless (ometa->overlay == comp1);
1336 fail_unless (gst_buffer_remove_video_overlay_composition_meta (buf, ometa));
1337 gst_buffer_add_video_overlay_composition_meta (buf, comp2);
1338 ometa = gst_buffer_get_video_overlay_composition_meta (buf);
1339 fail_unless (ometa->overlay == comp2);
1340 fail_unless (gst_buffer_remove_video_overlay_composition_meta (buf, ometa));
1341 fail_unless (gst_buffer_get_video_overlay_composition_meta (buf) == NULL);
1343 /* make sure the buffer cleans up its composition ref when unreffed */
1344 gst_buffer_add_video_overlay_composition_meta (buf, comp2);
1345 gst_buffer_unref (buf);
1347 gst_video_overlay_composition_unref (comp2);
1348 gst_video_overlay_composition_unref (comp1);
1353 GST_START_TEST (test_overlay_composition_premultiplied_alpha)
1355 GstVideoOverlayRectangle *rect1;
1356 GstVideoMeta *vmeta;
1357 GstBuffer *pix1, *pix2, *pix3, *pix4, *pix5;
1358 GstBuffer *pix6, *pix7, *pix8, *pix9, *pix10;
1359 guint8 *data5, *data7;
1363 pix1 = gst_buffer_new_and_alloc (200 * sizeof (guint32) * 50);
1364 gst_buffer_memset (pix1, 0, 0x80, gst_buffer_get_size (pix1));
1366 gst_buffer_add_video_meta (pix1, GST_VIDEO_FRAME_FLAG_NONE,
1367 GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB, 200, 50);
1368 rect1 = gst_video_overlay_rectangle_new_raw (pix1,
1369 600, 50, 300, 50, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1370 gst_buffer_unref (pix1);
1372 /* same flags, unscaled, should be the same buffer */
1373 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1374 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1375 fail_unless (pix1 == pix2);
1377 /* same flags, but scaled */
1378 pix3 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1379 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1380 fail_if (pix3 == pix1 || pix3 == pix2);
1382 /* same again, should hopefully get the same (cached) buffer as before */
1383 pix4 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1384 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1385 fail_unless (pix4 == pix3);
1387 /* just to update the vars */
1388 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1389 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1391 vmeta = gst_buffer_get_video_meta (pix2);
1392 fail_unless (vmeta != NULL);
1396 /* now, let's try to get premultiplied alpha from the unpremultiplied input */
1397 pix5 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1398 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1399 fail_if (pix5 == pix1 || pix5 == pix2 || pix5 == pix3);
1400 vmeta = gst_buffer_get_video_meta (pix5);
1401 fail_unless (vmeta != NULL);
1404 fail_unless_equals_int (w, w2);
1405 fail_unless_equals_int (h, h2);
1406 fail_unless_equals_int (gst_buffer_get_size (pix2),
1407 gst_buffer_get_size (pix5));
1408 gst_buffer_map (pix5, &map, GST_MAP_READ);
1409 fail_if (gst_buffer_memcmp (pix2, 0, map.data, map.size) == 0);
1410 /* make sure it actually did what we expected it to do (input=0x80808080) */
1412 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1414 fail_unless_equals_int (data5[0], 0x40);
1415 fail_unless_equals_int (data5[1], 0x40);
1416 fail_unless_equals_int (data5[2], 0x40);
1417 fail_unless_equals_int (data5[3], 0x80);
1420 fail_unless_equals_int (data5[0], 0x80);
1421 fail_unless_equals_int (data5[1], 0x40);
1422 fail_unless_equals_int (data5[2], 0x40);
1423 fail_unless_equals_int (data5[3], 0x40);
1425 gst_buffer_unmap (pix5, &map);
1427 /* same again, now we should be getting back the same buffer as before,
1428 * as it should have been cached */
1429 pix6 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1430 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1431 fail_unless (pix6 == pix5);
1433 /* just to update the stride var */
1434 pix3 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1435 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1436 fail_unless (pix3 == pix4);
1438 /* now try to get scaled premultiplied alpha from unpremultiplied input */
1439 pix7 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1440 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1441 fail_if (pix7 == pix1 || pix7 == pix2 || pix7 == pix3 || pix7 == pix5);
1443 gst_buffer_map (pix7, &map, GST_MAP_READ);
1445 /* make sure it actually did what we expected it to do (input=0x80808080)
1446 * hoping that the scaling didn't mess up our values */
1447 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1449 fail_unless_equals_int (data7[0], 0x40);
1450 fail_unless_equals_int (data7[1], 0x40);
1451 fail_unless_equals_int (data7[2], 0x40);
1452 fail_unless_equals_int (data7[3], 0x80);
1455 fail_unless_equals_int (data7[0], 0x80);
1456 fail_unless_equals_int (data7[1], 0x40);
1457 fail_unless_equals_int (data7[2], 0x40);
1458 fail_unless_equals_int (data7[3], 0x40);
1460 gst_buffer_unmap (pix7, &map);
1462 /* and the same again, it should be cached now */
1463 pix8 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1464 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1465 fail_unless (pix8 == pix7);
1467 /* make sure other cached stuff is still there */
1468 pix9 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1469 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1470 fail_unless (pix9 == pix3);
1471 pix10 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1472 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1473 fail_unless (pix10 == pix5);
1475 gst_video_overlay_rectangle_unref (rect1);
1480 GST_START_TEST (test_overlay_composition_global_alpha)
1482 GstVideoOverlayRectangle *rect1;
1483 GstBuffer *pix1, *pix2, *pix3, *pix4, *pix5;
1484 GstVideoMeta *vmeta;
1485 guint8 *data2, *data4, *data5;
1489 GstVideoOverlayFormatFlags flags1;
1492 pix1 = gst_buffer_new_and_alloc (200 * sizeof (guint32) * 50);
1493 gst_buffer_memset (pix1, 0, 0x80, gst_buffer_get_size (pix1));
1495 gst_buffer_add_video_meta (pix1, GST_VIDEO_FRAME_FLAG_NONE,
1496 GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB, 200, 50);
1497 rect1 = gst_video_overlay_rectangle_new_raw (pix1,
1498 600, 50, 300, 50, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1499 gst_buffer_unref (pix1);
1501 /* same flags, unscaled, should be the same buffer */
1502 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1503 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1504 fail_unless (pix1 == pix2);
1506 vmeta = gst_buffer_get_video_meta (pix2);
1507 fail_unless (vmeta != NULL);
1511 /* same flags, but scaled */
1512 pix3 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1513 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1514 fail_if (pix3 == pix1 || pix3 == pix2);
1516 /* get unscaled premultiplied data, new cached rectangle should be created */
1517 pix4 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1518 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1519 fail_if (pix4 == pix2 || pix4 == pix3);
1520 vmeta = gst_buffer_get_video_meta (pix4);
1521 fail_unless (vmeta != NULL);
1524 fail_unless_equals_int (w, w4);
1525 fail_unless_equals_int (h, h4);
1526 fail_unless_equals_int (gst_buffer_get_size (pix2),
1527 gst_buffer_get_size (pix4));
1528 gst_buffer_map (pix4, &map, GST_MAP_READ);
1529 fail_if (gst_buffer_memcmp (pix1, 0, map.data, map.size) == 0);
1530 /* make sure it actually did what we expected it to do (input=0x80808080) */
1532 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1534 fail_unless_equals_int (data4[0], 0x40);
1535 fail_unless_equals_int (data4[1], 0x40);
1536 fail_unless_equals_int (data4[2], 0x40);
1537 fail_unless_equals_int (data4[3], 0x80);
1540 fail_unless_equals_int (data4[0], 0x80);
1541 fail_unless_equals_int (data4[1], 0x40);
1542 fail_unless_equals_int (data4[2], 0x40);
1543 fail_unless_equals_int (data4[3], 0x40);
1545 gst_buffer_unmap (pix4, &map);
1547 /* now premultiplied and scaled, again a new cached rectangle should be cached */
1548 pix5 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1549 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1550 fail_if (pix5 == pix2 || pix5 == pix3 || pix5 == pix4);
1551 /* stride and size should be equal to the first scaled rect */
1552 fail_unless_equals_int (gst_buffer_get_size (pix5),
1553 gst_buffer_get_size (pix3));
1554 /* data should be different (premutliplied) though */
1555 gst_buffer_map (pix5, &map, GST_MAP_READ);
1556 fail_if (gst_buffer_memcmp (pix3, 0, map.data, map.size) == 0);
1557 /* make sure it actually did what we expected it to do (input=0x80808080) */
1559 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1561 fail_unless_equals_int (data5[0], 0x40);
1562 fail_unless_equals_int (data5[1], 0x40);
1563 fail_unless_equals_int (data5[2], 0x40);
1564 fail_unless_equals_int (data5[3], 0x80);
1567 fail_unless_equals_int (data5[0], 0x80);
1568 fail_unless_equals_int (data5[1], 0x40);
1569 fail_unless_equals_int (data5[2], 0x40);
1570 fail_unless_equals_int (data5[3], 0x40);
1572 gst_buffer_unmap (pix5, &map);
1574 /* global_alpha should initially be 1.0 */
1575 ga1 = gst_video_overlay_rectangle_get_global_alpha (rect1);
1576 fail_unless_equals_float (ga1, 1.0);
1578 /* now set global_alpha */
1579 seq1 = gst_video_overlay_rectangle_get_seqnum (rect1);
1580 gst_video_overlay_rectangle_set_global_alpha (rect1, 0.5);
1581 ga2 = gst_video_overlay_rectangle_get_global_alpha (rect1);
1582 fail_unless_equals_float (ga2, 0.5);
1584 /* seqnum should have changed */
1585 seq2 = gst_video_overlay_rectangle_get_seqnum (rect1);
1586 fail_unless (seq1 < seq2);
1588 /* internal flags should have been set */
1589 flags1 = gst_video_overlay_rectangle_get_flags (rect1);
1590 fail_unless_equals_int (flags1, GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1592 /* request unscaled pixel-data, global-alpha not applied */
1593 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1594 GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1595 /* this should just return the same buffer */
1596 fail_unless (pix2 == pix1);
1597 /* make sure we got the initial data (input=0x80808080) */
1598 gst_buffer_map (pix2, &map, GST_MAP_READ);
1600 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1602 fail_unless_equals_int (data2[0], 0x80);
1603 fail_unless_equals_int (data2[1], 0x80);
1604 fail_unless_equals_int (data2[2], 0x80);
1605 fail_unless_equals_int (data2[3], 0x80);
1608 fail_unless_equals_int (data2[0], 0x80);
1609 fail_unless_equals_int (data2[1], 0x80);
1610 fail_unless_equals_int (data2[2], 0x80);
1611 fail_unless_equals_int (data2[3], 0x80);
1613 gst_buffer_unmap (pix2, &map);
1615 /* unscaled pixel-data, global-alpha applied */
1616 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1617 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1618 /* this should be the same buffer with on-the-fly modified alpha-channel */
1619 fail_unless (pix2 == pix1);
1620 gst_buffer_map (pix2, &map, GST_MAP_READ);
1622 /* make sure we got the initial data with adjusted alpha-channel */
1623 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1625 fail_unless_equals_int (data2[0], 0x80);
1626 fail_unless_equals_int (data2[1], 0x80);
1627 fail_unless_equals_int (data2[2], 0x80);
1628 fail_unless_equals_int (data2[3], 0x40);
1631 fail_unless_equals_int (data2[0], 0x40);
1632 fail_unless_equals_int (data2[1], 0x80);
1633 fail_unless_equals_int (data2[2], 0x80);
1634 fail_unless_equals_int (data2[3], 0x80);
1636 gst_buffer_unmap (pix2, &map);
1638 /* adjust global_alpha once more */
1639 gst_video_overlay_rectangle_set_global_alpha (rect1, 0.25);
1640 ga2 = gst_video_overlay_rectangle_get_global_alpha (rect1);
1641 fail_unless_equals_float (ga2, 0.25);
1642 /* and again request unscaled pixel-data, global-alpha applied */
1643 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1644 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1645 fail_unless (pix2 == pix1);
1646 /* make sure we got the initial data with adjusted alpha-channel */
1647 gst_buffer_map (pix2, &map, GST_MAP_READ);
1649 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1651 fail_unless_equals_int (data2[0], 0x80);
1652 fail_unless_equals_int (data2[1], 0x80);
1653 fail_unless_equals_int (data2[2], 0x80);
1654 fail_unless_equals_int (data2[3], 0x20);
1657 fail_unless_equals_int (data2[0], 0x20);
1658 fail_unless_equals_int (data2[1], 0x80);
1659 fail_unless_equals_int (data2[2], 0x80);
1660 fail_unless_equals_int (data2[3], 0x80);
1662 gst_buffer_unmap (pix2, &map);
1664 /* again: unscaled pixel-data, global-alpha not applied,
1665 * this should revert alpha-channel to initial values */
1666 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1667 GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1668 fail_unless (pix2 == pix1);
1669 /* make sure we got the initial data (input=0x80808080) */
1670 gst_buffer_map (pix2, &map, GST_MAP_READ);
1672 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1674 fail_unless_equals_int (data2[0], 0x80);
1675 fail_unless_equals_int (data2[1], 0x80);
1676 fail_unless_equals_int (data2[2], 0x80);
1677 fail_unless_equals_int (data2[3], 0x80);
1680 fail_unless_equals_int (data2[0], 0x80);
1681 fail_unless_equals_int (data2[1], 0x80);
1682 fail_unless_equals_int (data2[2], 0x80);
1683 fail_unless_equals_int (data2[3], 0x80);
1685 gst_buffer_unmap (pix2, &map);
1687 /* now scaled, global-alpha not applied */
1688 pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1689 GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1690 /* this should just return the rect/buffer, that was cached for these
1691 * scaling dimensions */
1692 fail_unless (pix2 == pix3);
1693 /* make sure we got the initial data (input=0x80808080) */
1694 gst_buffer_map (pix2, &map, GST_MAP_READ);
1696 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1698 fail_unless_equals_int (data2[0], 0x80);
1699 fail_unless_equals_int (data2[1], 0x80);
1700 fail_unless_equals_int (data2[2], 0x80);
1701 fail_unless_equals_int (data2[3], 0x80);
1704 fail_unless_equals_int (data2[0], 0x80);
1705 fail_unless_equals_int (data2[1], 0x80);
1706 fail_unless_equals_int (data2[2], 0x80);
1707 fail_unless_equals_int (data2[3], 0x80);
1709 gst_buffer_unmap (pix2, &map);
1711 /* scaled, global-alpha (0.25) applied */
1712 pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1713 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1714 /* this should just return the rect/buffer, that was cached for these
1715 * scaling dimensions with modified alpha channel */
1716 fail_unless (pix2 == pix3);
1717 /* make sure we got the data we expect for global-alpha=0.25 */
1718 gst_buffer_map (pix2, &map, GST_MAP_READ);
1720 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1722 fail_unless_equals_int (data2[0], 0x80);
1723 fail_unless_equals_int (data2[1], 0x80);
1724 fail_unless_equals_int (data2[2], 0x80);
1725 fail_unless_equals_int (data2[3], 0x20);
1728 fail_unless_equals_int (data2[0], 0x20);
1729 fail_unless_equals_int (data2[1], 0x80);
1730 fail_unless_equals_int (data2[2], 0x80);
1731 fail_unless_equals_int (data2[3], 0x80);
1733 gst_buffer_unmap (pix2, &map);
1735 /* now unscaled premultiplied data, global-alpha not applied,
1736 * is this really a valid use case?*/
1737 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1738 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA |
1739 GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1740 /* this should just return the rect/buffer, that was cached for the
1741 * premultiplied data */
1742 fail_unless (pix2 == pix4);
1743 /* make sure we got what we expected */
1744 gst_buffer_map (pix2, &map, GST_MAP_READ);
1746 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1748 fail_unless_equals_int (data2[0], 0x40);
1749 fail_unless_equals_int (data2[1], 0x40);
1750 fail_unless_equals_int (data2[2], 0x40);
1751 fail_unless_equals_int (data2[3], 0x80);
1754 fail_unless_equals_int (data2[0], 0x80);
1755 fail_unless_equals_int (data2[1], 0x40);
1756 fail_unless_equals_int (data2[2], 0x40);
1757 fail_unless_equals_int (data2[3], 0x40);
1759 gst_buffer_unmap (pix2, &map);
1761 /* unscaled premultiplied data, global-alpha (0.25) applied */
1762 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1763 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1764 /* this should just return the rect/buffer, that was cached for the
1765 * premultiplied data */
1766 fail_unless (pix2 == pix4);
1767 /* make sure we got what we expected:
1768 * (0x40 / (0x80/0xFF) * (0x20/0xFF) = 0x10
1769 * NOTE: unless we are using round() for the premultiplied case
1770 * in gst_video_overlay_rectangle_apply_global_alpha() we get rounding
1771 * error, i.e. 0x0F here */
1772 gst_buffer_map (pix2, &map, GST_MAP_READ);
1774 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1776 fail_unless_equals_int (data2[0], 0x0F);
1777 fail_unless_equals_int (data2[1], 0x0F);
1778 fail_unless_equals_int (data2[2], 0x0F);
1779 fail_unless_equals_int (data2[3], 0x20);
1782 fail_unless_equals_int (data2[0], 0x20);
1783 fail_unless_equals_int (data2[1], 0x0F);
1784 fail_unless_equals_int (data2[2], 0x0F);
1785 fail_unless_equals_int (data2[3], 0x0F);
1787 gst_buffer_unmap (pix2, &map);
1789 /* set global_alpha once more */
1790 gst_video_overlay_rectangle_set_global_alpha (rect1, 0.75);
1791 /* and verify that also premultiplied data is adjusted
1792 * correspondingly (though with increasing rounding errors) */
1793 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1794 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1795 /* this should just return the rect/buffer, that was cached for the
1796 * premultiplied data */
1797 fail_unless (pix2 == pix4);
1798 /* make sure we got what we expected:
1799 * (0x0F / (0x20/0xFF) * (0x60/0xFF) = 0x2D
1800 * NOTE: using floats everywhere we would get 0x30
1801 * here we will actually end up with 0x2C */
1802 gst_buffer_map (pix2, &map, GST_MAP_READ);
1804 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1806 fail_unless_equals_int (data2[0], 0x2C);
1807 fail_unless_equals_int (data2[1], 0x2C);
1808 fail_unless_equals_int (data2[2], 0x2C);
1809 fail_unless_equals_int (data2[3], 0x60);
1812 fail_unless_equals_int (data2[0], 0x60);
1813 fail_unless_equals_int (data2[1], 0x2C);
1814 fail_unless_equals_int (data2[2], 0x2C);
1815 fail_unless_equals_int (data2[3], 0x2C);
1817 gst_buffer_unmap (pix2, &map);
1819 /* now scaled and premultiplied data, global-alpha not applied,
1820 * is this really a valid use case?*/
1821 pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1822 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA |
1823 GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1824 /* this should just return the rect/buffer, that was cached for the
1825 * first premultiplied+scaled rect*/
1826 fail_unless (pix2 == pix5);
1827 /* make sure we got what we expected */
1828 gst_buffer_map (pix2, &map, GST_MAP_READ);
1830 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1832 fail_unless_equals_int (data2[0], 0x40);
1833 fail_unless_equals_int (data2[1], 0x40);
1834 fail_unless_equals_int (data2[2], 0x40);
1835 fail_unless_equals_int (data2[3], 0x80);
1838 fail_unless_equals_int (data2[0], 0x80);
1839 fail_unless_equals_int (data2[1], 0x40);
1840 fail_unless_equals_int (data2[2], 0x40);
1841 fail_unless_equals_int (data2[3], 0x40);
1843 gst_buffer_unmap (pix2, &map);
1845 /* scaled and premultiplied data, global-alpha applied */
1846 pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1847 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1848 /* this should just return the rect/buffer, that was cached for the
1849 * first premultiplied+scaled rect*/
1850 fail_unless (pix2 == pix5);
1851 /* make sure we got what we expected; see above note about rounding errors! */
1852 gst_buffer_map (pix2, &map, GST_MAP_READ);
1854 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1856 fail_unless_equals_int (data2[0], 0x2F);
1857 fail_unless_equals_int (data2[1], 0x2F);
1858 fail_unless_equals_int (data2[2], 0x2F);
1859 fail_unless_equals_int (data2[3], 0x60);
1862 fail_unless_equals_int (data2[0], 0x60);
1863 fail_unless_equals_int (data2[1], 0x2F);
1864 fail_unless_equals_int (data2[2], 0x2F);
1865 fail_unless_equals_int (data2[3], 0x2F);
1867 gst_buffer_unmap (pix2, &map);
1869 gst_video_overlay_rectangle_unref (rect1);
1875 make_pixels (gint depth, gint width, gint height)
1877 guint32 color = 0xff000000;
1881 guint8 *pixels = g_malloc (width * height * 4);
1882 for (i = 0; i < height; i++) {
1883 for (j = 0; j < width; j++) {
1884 pixels[(i * width + j) * 4 + 0] = ((color >> 24) & 0xff);
1885 pixels[(i * width + j) * 4 + 1] = ((color >> 16) & 0xff);
1886 pixels[(i * width + j) * 4 + 2] = ((color >> 8) & 0xff);
1887 pixels[(i * width + j) * 4 + 3] = (color & 0xff);
1893 #define TO16(a) (((a)<<8)|(a))
1894 guint16 *pixels = g_malloc (width * height * 8);
1895 for (i = 0; i < height; i++) {
1896 for (j = 0; j < width; j++) {
1897 pixels[(i * width + j) * 4 + 0] = TO16 ((color >> 24) & 0xff);
1898 pixels[(i * width + j) * 4 + 1] = TO16 ((color >> 16) & 0xff);
1899 pixels[(i * width + j) * 4 + 2] = TO16 ((color >> 8) & 0xff);
1900 pixels[(i * width + j) * 4 + 3] = TO16 (color & 0xff);
1905 return (guint8 *) pixels;
1909 #define HS(x,o) ((x)&hs[o])
1910 #define WS(x,o) ((x)&ws[o])
1911 #define IN(i,j,o) (in[(HS(i, o)*width + WS(j,o))*4+(o)] & mask[o])
1912 #define OUT(i,j,o) (out[((i)*width + (j))*4+o] & mask[o])
1914 compare_frame (const GstVideoFormatInfo * finfo, gint depth, guint8 * outpixels,
1915 guint8 * pixels, gint width, gint height)
1918 guint ws[4], hs[4], mask[4];
1920 for (k = 0; k < 4; k++) {
1921 hs[k] = G_MAXUINT << finfo->h_sub[(3 + k) % 4];
1922 ws[k] = G_MAXUINT << finfo->w_sub[(3 + k) % 4];
1923 mask[k] = G_MAXUINT << (depth - finfo->depth[(3 + k) % 4]);
1927 guint8 *in = pixels;
1928 guint8 *out = outpixels;
1930 for (i = 0; i < height; i++) {
1931 for (j = 0; j < width; j++) {
1932 for (k = 0; k < 4; k++) {
1933 diff += IN (i, j, k) != OUT (i, j, k);
1938 guint16 *in = (guint16 *) pixels;
1939 guint16 *out = (guint16 *) outpixels;
1941 for (i = 0; i < height; i++) {
1942 for (j = 0; j < width; j++) {
1943 for (k = 0; k < 4; k++) {
1944 diff += IN (i, j, k) != OUT (i, j, k);
1959 GstVideoFormat infmt;
1960 GstVideoFormat outfmt;
1962 gdouble convert_sec;
1965 #define SIGN(a,b) ((a) < (b) ? -1 : (a) > (b) ? 1 : 0)
1968 compare_result (gconstpointer a, gconstpointer b)
1970 const ConvertResult *ap = a;
1971 const ConvertResult *bp = b;
1973 return SIGN (ap->convert_sec, bp->convert_sec);
1976 #define UNPACK_FRAME(frame,dest,line,x,width) \
1977 (frame)->info.finfo->unpack_func ((frame)->info.finfo, \
1978 (GST_VIDEO_FRAME_IS_INTERLACED (frame) ? \
1979 GST_VIDEO_PACK_FLAG_INTERLACED : \
1980 GST_VIDEO_PACK_FLAG_NONE), \
1981 dest, (frame)->data, (frame)->info.stride, x, \
1983 #define PACK_FRAME(frame,src,line,width) \
1984 (frame)->info.finfo->pack_func ((frame)->info.finfo, \
1985 (GST_VIDEO_FRAME_IS_INTERLACED (frame) ? \
1986 GST_VIDEO_PACK_FLAG_INTERLACED : \
1987 GST_VIDEO_PACK_FLAG_NONE), \
1988 src, 0, (frame)->data, (frame)->info.stride, \
1989 (frame)->info.chroma_site, line, width);
1991 GST_START_TEST (test_video_pack_unpack2)
1993 GstVideoFormat format;
1995 gint num_formats, i;
1996 GArray *packarray, *unpackarray;
2000 /* set to something larger to do benchmarks */
2003 timer = g_timer_new ();
2004 packarray = g_array_new (FALSE, FALSE, sizeof (ConvertResult));
2005 unpackarray = g_array_new (FALSE, FALSE, sizeof (ConvertResult));
2007 num_formats = get_num_formats ();
2009 GST_DEBUG ("pack/sec\t unpack/sec \tpack GB/sec\tunpack GB/sec\tformat");
2011 for (format = GST_VIDEO_FORMAT_I420; format < num_formats; format++) {
2013 const GstVideoFormatInfo *finfo, *fuinfo;
2015 GstVideoFrame frame;
2016 gint k, stride, count, diff, depth;
2017 guint8 *pixels, *outpixels;
2019 gdouble unpack_sec, pack_sec;
2022 finfo = gst_video_format_get_info (format);
2023 fail_unless (finfo != NULL);
2025 if (GST_VIDEO_FORMAT_INFO_HAS_PALETTE (finfo))
2028 fuinfo = gst_video_format_get_info (finfo->unpack_format);
2029 fail_unless (fuinfo != NULL);
2031 depth = GST_VIDEO_FORMAT_INFO_BITS (fuinfo);
2032 fail_unless (depth == 8 || depth == 16);
2034 pixels = make_pixels (depth, WIDTH, HEIGHT);
2035 stride = WIDTH * (depth >> 1);
2037 gst_video_info_set_format (&info, format, WIDTH, HEIGHT);
2038 buffer = gst_buffer_new_and_alloc (info.size);
2039 gst_video_frame_map (&frame, &info, buffer, GST_MAP_READWRITE);
2041 /* pack the frame into the target format */
2043 PACK_FRAME (&frame, pixels, 0, WIDTH);
2046 g_timer_start (timer);
2048 for (k = 0; k < HEIGHT; k += finfo->pack_lines) {
2049 PACK_FRAME (&frame, pixels + k * stride, k, WIDTH);
2052 elapsed = g_timer_elapsed (timer, NULL);
2053 if (elapsed >= TIME)
2056 unpack_sec = count / elapsed;
2059 res.outfmt = finfo->unpack_format;
2060 res.convert_sec = unpack_sec;
2061 g_array_append_val (unpackarray, res);
2063 outpixels = g_malloc0 (HEIGHT * stride);
2065 /* unpack the frame */
2067 UNPACK_FRAME (&frame, outpixels, 0, 0, WIDTH);
2070 g_timer_start (timer);
2072 for (k = 0; k < HEIGHT; k += finfo->pack_lines) {
2073 UNPACK_FRAME (&frame, outpixels + k * stride, k, 0, WIDTH);
2076 elapsed = g_timer_elapsed (timer, NULL);
2077 if (elapsed >= TIME)
2080 pack_sec = count / elapsed;
2082 res.outfmt = format;
2083 res.infmt = finfo->unpack_format;
2084 res.convert_sec = pack_sec;
2085 g_array_append_val (packarray, res);
2087 /* compare the frame */
2088 diff = compare_frame (finfo, depth, outpixels, pixels, WIDTH, HEIGHT);
2090 GST_DEBUG ("%f \t %f \t %f \t %f \t %s %d/%f", pack_sec, unpack_sec,
2091 info.size * pack_sec, info.size * unpack_sec, finfo->name, count,
2095 gst_util_dump_mem (outpixels, 128);
2096 gst_util_dump_mem (pixels, 128);
2097 fail_if (diff != 0);
2099 gst_video_frame_unmap (&frame);
2100 gst_buffer_unref (buffer);
2105 g_array_sort (packarray, compare_result);
2106 for (i = 0; i < packarray->len; i++) {
2107 ConvertResult *res = &g_array_index (packarray, ConvertResult, i);
2109 GST_DEBUG ("%f pack/sec %s->%s", res->convert_sec,
2110 gst_video_format_to_string (res->infmt),
2111 gst_video_format_to_string (res->outfmt));
2114 g_array_sort (unpackarray, compare_result);
2115 for (i = 0; i < unpackarray->len; i++) {
2116 ConvertResult *res = &g_array_index (unpackarray, ConvertResult, i);
2118 GST_DEBUG ("%f unpack/sec %s->%s", res->convert_sec,
2119 gst_video_format_to_string (res->infmt),
2120 gst_video_format_to_string (res->outfmt));
2123 g_timer_destroy (timer);
2124 g_array_free (packarray, TRUE);
2125 g_array_free (unpackarray, TRUE);
2136 #define GET_LINE(l) (pixels + CLAMP (l, 0, HEIGHT-1) * WIDTH * 4)
2137 GST_START_TEST (test_video_chroma)
2141 gint i, j, k, offset, count;
2144 gdouble elapsed, subsample_sec;
2145 GstVideoChromaSite sites[] = {
2146 GST_VIDEO_CHROMA_SITE_NONE,
2147 GST_VIDEO_CHROMA_SITE_H_COSITED,
2150 timer = g_timer_new ();
2151 pixels = make_pixels (8, WIDTH, HEIGHT);
2153 for (k = 0; k < G_N_ELEMENTS (sites); k++) {
2154 GstVideoChromaResample *resample;
2156 resample = gst_video_chroma_resample_new (GST_VIDEO_CHROMA_METHOD_LINEAR,
2157 sites[k], GST_VIDEO_CHROMA_FLAG_NONE, GST_VIDEO_FORMAT_AYUV, -1, -1);
2159 gst_video_chroma_resample_get_info (resample, &n_lines, &offset);
2160 fail_unless (n_lines < 10);
2163 for (j = 0; j < n_lines; j++)
2164 lines[j] = GET_LINE (offset + j);
2165 gst_video_chroma_resample (resample, lines, WIDTH);
2168 g_timer_start (timer);
2170 for (i = 0; i < HEIGHT; i += n_lines) {
2171 for (j = 0; j < n_lines; j++)
2172 lines[j] = GET_LINE (i + offset + j);
2174 gst_video_chroma_resample (resample, lines, WIDTH);
2177 elapsed = g_timer_elapsed (timer, NULL);
2178 if (elapsed >= TIME)
2181 subsample_sec = count / elapsed;
2182 GST_DEBUG ("%f downsamples/sec %d/%f", subsample_sec, count, elapsed);
2183 gst_video_chroma_resample_free (resample);
2185 resample = gst_video_chroma_resample_new (GST_VIDEO_CHROMA_METHOD_LINEAR,
2186 sites[k], GST_VIDEO_CHROMA_FLAG_NONE, GST_VIDEO_FORMAT_AYUV, 1, 1);
2188 gst_video_chroma_resample_get_info (resample, &n_lines, &offset);
2189 fail_unless (n_lines < 10);
2192 for (j = 0; j < n_lines; j++)
2193 lines[j] = GET_LINE (offset + j);
2194 gst_video_chroma_resample (resample, lines, WIDTH);
2197 g_timer_start (timer);
2199 for (i = 0; i < HEIGHT; i += n_lines) {
2200 for (j = 0; j < n_lines; j++)
2201 lines[j] = GET_LINE (i + offset + j);
2203 gst_video_chroma_resample (resample, lines, WIDTH);
2206 elapsed = g_timer_elapsed (timer, NULL);
2207 if (elapsed >= TIME)
2210 subsample_sec = count / elapsed;
2211 GST_DEBUG ("%f upsamples/sec %d/%f", subsample_sec, count, elapsed);
2212 gst_video_chroma_resample_free (resample);
2216 g_timer_destroy (timer);
2224 GST_START_TEST (test_video_scaler)
2226 GstVideoScaler *scale;
2228 scale = gst_video_scaler_new (GST_VIDEO_RESAMPLER_METHOD_LINEAR,
2229 GST_VIDEO_SCALER_FLAG_NONE, 2, 10, 5, NULL);
2230 gst_video_scaler_free (scale);
2232 scale = gst_video_scaler_new (GST_VIDEO_RESAMPLER_METHOD_LINEAR,
2233 GST_VIDEO_SCALER_FLAG_NONE, 2, 15, 5, NULL);
2234 gst_video_scaler_free (scale);
2243 GST_START_TEST (test_video_color_convert)
2245 GstVideoFormat infmt, outfmt;
2247 gint num_formats, i;
2250 array = g_array_new (FALSE, FALSE, sizeof (ConvertResult));
2252 timer = g_timer_new ();
2254 num_formats = get_num_formats ();
2256 for (infmt = GST_VIDEO_FORMAT_I420; infmt < num_formats; infmt++) {
2257 GstVideoInfo ininfo;
2258 GstVideoFrame inframe;
2259 GstBuffer *inbuffer;
2261 gst_video_info_set_format (&ininfo, infmt, WIDTH, HEIGHT);
2262 inbuffer = gst_buffer_new_and_alloc (ininfo.size);
2263 gst_buffer_memset (inbuffer, 0, 0, -1);
2264 gst_video_frame_map (&inframe, &ininfo, inbuffer, GST_MAP_READ);
2266 for (outfmt = GST_VIDEO_FORMAT_I420; outfmt < num_formats; outfmt++) {
2267 GstVideoInfo outinfo;
2268 GstVideoFrame outframe;
2269 GstBuffer *outbuffer;
2270 GstVideoConverter *convert;
2275 gst_video_info_set_format (&outinfo, outfmt, WIDTH, HEIGHT);
2276 outbuffer = gst_buffer_new_and_alloc (outinfo.size);
2277 gst_video_frame_map (&outframe, &outinfo, outbuffer, GST_MAP_WRITE);
2279 convert = gst_video_converter_new (&ininfo, &outinfo, NULL);
2281 gst_video_converter_frame (convert, &inframe, &outframe);
2284 g_timer_start (timer);
2286 gst_video_converter_frame (convert, &inframe, &outframe);
2289 elapsed = g_timer_elapsed (timer, NULL);
2290 if (elapsed >= TIME)
2295 res.outfmt = outfmt;
2296 res.convert_sec = count / elapsed;
2298 GST_DEBUG ("%f conversions/sec %s->%s, %d/%f", res.convert_sec,
2299 gst_video_format_to_string (infmt),
2300 gst_video_format_to_string (outfmt), count, elapsed);
2302 g_array_append_val (array, res);
2304 gst_video_converter_free (convert);
2306 gst_video_frame_unmap (&outframe);
2307 gst_buffer_unref (outbuffer);
2309 gst_video_frame_unmap (&inframe);
2310 gst_buffer_unref (inbuffer);
2313 g_array_sort (array, compare_result);
2315 for (i = 0; i < array->len; i++) {
2316 ConvertResult *res = &g_array_index (array, ConvertResult, i);
2318 GST_DEBUG ("%f conversions/sec %s->%s", res->convert_sec,
2319 gst_video_format_to_string (res->infmt),
2320 gst_video_format_to_string (res->outfmt));
2323 g_array_free (array, TRUE);
2325 g_timer_destroy (timer);
2332 #define WIDTH_IN 320
2333 #define HEIGHT_IN 240
2334 #define WIDTH_OUT 400
2335 #define HEIGHT_OUT 300
2338 GST_START_TEST (test_video_size_convert)
2340 GstVideoFormat infmt, outfmt;
2342 gint num_formats, i;
2345 array = g_array_new (FALSE, FALSE, sizeof (ConvertResult));
2347 timer = g_timer_new ();
2349 num_formats = get_num_formats ();
2351 for (infmt = GST_VIDEO_FORMAT_I420; infmt < num_formats; infmt++) {
2352 GstVideoInfo ininfo, outinfo;
2353 GstVideoFrame inframe, outframe;
2354 GstBuffer *inbuffer, *outbuffer;
2355 GstVideoConverter *convert;
2360 gst_video_info_set_format (&ininfo, infmt, WIDTH_IN, HEIGHT_IN);
2361 inbuffer = gst_buffer_new_and_alloc (ininfo.size);
2362 gst_buffer_memset (inbuffer, 0, 0, -1);
2363 gst_video_frame_map (&inframe, &ininfo, inbuffer, GST_MAP_READ);
2366 gst_video_info_set_format (&outinfo, outfmt, WIDTH_OUT, HEIGHT_OUT);
2367 outbuffer = gst_buffer_new_and_alloc (outinfo.size);
2368 gst_video_frame_map (&outframe, &outinfo, outbuffer, GST_MAP_WRITE);
2370 for (method = 0; method < 4; method++) {
2371 convert = gst_video_converter_new (&ininfo, &outinfo,
2372 gst_structure_new ("options",
2373 GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
2374 GST_TYPE_VIDEO_RESAMPLER_METHOD, method, NULL));
2377 gst_video_converter_frame (convert, &inframe, &outframe);
2380 g_timer_start (timer);
2382 gst_video_converter_frame (convert, &inframe, &outframe);
2385 elapsed = g_timer_elapsed (timer, NULL);
2386 if (elapsed >= TIME)
2391 res.outfmt = outfmt;
2392 res.method = method;
2393 res.convert_sec = count / elapsed;
2395 GST_DEBUG ("%f resize/sec %s->%s, %d, %d/%f", res.convert_sec,
2396 gst_video_format_to_string (infmt),
2397 gst_video_format_to_string (outfmt), method, count, elapsed);
2399 g_array_append_val (array, res);
2401 gst_video_converter_free (convert);
2403 gst_video_frame_unmap (&outframe);
2404 gst_buffer_unref (outbuffer);
2405 gst_video_frame_unmap (&inframe);
2406 gst_buffer_unref (inbuffer);
2409 g_array_sort (array, compare_result);
2411 for (i = 0; i < array->len; i++) {
2412 ConvertResult *res = &g_array_index (array, ConvertResult, i);
2414 GST_DEBUG ("%f method %d, resize/sec %s->%s", res->convert_sec, res->method,
2415 gst_video_format_to_string (res->infmt),
2416 gst_video_format_to_string (res->outfmt));
2419 g_array_free (array, TRUE);
2421 g_timer_destroy (timer);
2428 GST_START_TEST (test_video_convert)
2430 GstVideoInfo ininfo, outinfo;
2431 GstVideoFrame inframe, outframe;
2432 GstBuffer *inbuffer, *outbuffer;
2433 GstVideoConverter *convert;
2435 gst_video_info_set_format (&ininfo, GST_VIDEO_FORMAT_ARGB, 320, 240);
2436 inbuffer = gst_buffer_new_and_alloc (ininfo.size);
2437 gst_buffer_memset (inbuffer, 0, 0, -1);
2438 gst_video_frame_map (&inframe, &ininfo, inbuffer, GST_MAP_READ);
2440 gst_video_info_set_format (&outinfo, GST_VIDEO_FORMAT_BGRx, 400, 300);
2441 outbuffer = gst_buffer_new_and_alloc (outinfo.size);
2442 gst_video_frame_map (&outframe, &outinfo, outbuffer, GST_MAP_WRITE);
2444 /* see that we don't reuse the source line directly because we need
2445 * to add borders to it */
2446 convert = gst_video_converter_new (&ininfo, &outinfo,
2447 gst_structure_new ("options",
2448 GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
2449 GST_TYPE_VIDEO_RESAMPLER_METHOD, 3,
2450 GST_VIDEO_CONVERTER_OPT_SRC_X, G_TYPE_INT, 10,
2451 GST_VIDEO_CONVERTER_OPT_SRC_Y, G_TYPE_INT, 0,
2452 GST_VIDEO_CONVERTER_OPT_SRC_WIDTH, G_TYPE_INT, 300,
2453 GST_VIDEO_CONVERTER_OPT_SRC_HEIGHT, G_TYPE_INT, 220,
2454 GST_VIDEO_CONVERTER_OPT_DEST_X, G_TYPE_INT, 80,
2455 GST_VIDEO_CONVERTER_OPT_DEST_Y, G_TYPE_INT, 60,
2456 GST_VIDEO_CONVERTER_OPT_DEST_WIDTH, G_TYPE_INT, 300,
2457 GST_VIDEO_CONVERTER_OPT_DEST_HEIGHT, G_TYPE_INT, 220, NULL));
2459 gst_video_converter_frame (convert, &inframe, &outframe);
2460 gst_video_converter_free (convert);
2462 /* see that we reuse the source line directly because we need to scale
2464 convert = gst_video_converter_new (&ininfo, &outinfo,
2465 gst_structure_new ("options",
2466 GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
2467 GST_TYPE_VIDEO_RESAMPLER_METHOD, 3,
2468 GST_VIDEO_CONVERTER_OPT_SRC_X, G_TYPE_INT, 10,
2469 GST_VIDEO_CONVERTER_OPT_SRC_Y, G_TYPE_INT, 0,
2470 GST_VIDEO_CONVERTER_OPT_SRC_WIDTH, G_TYPE_INT, 300,
2471 GST_VIDEO_CONVERTER_OPT_SRC_HEIGHT, G_TYPE_INT, 220,
2472 GST_VIDEO_CONVERTER_OPT_DEST_X, G_TYPE_INT, 80,
2473 GST_VIDEO_CONVERTER_OPT_DEST_Y, G_TYPE_INT, 60,
2474 GST_VIDEO_CONVERTER_OPT_DEST_WIDTH, G_TYPE_INT, 310,
2475 GST_VIDEO_CONVERTER_OPT_DEST_HEIGHT, G_TYPE_INT, 230, NULL));
2477 gst_video_converter_frame (convert, &inframe, &outframe);
2478 gst_video_converter_free (convert);
2480 gst_video_frame_unmap (&outframe);
2481 gst_buffer_unref (outbuffer);
2482 gst_video_frame_unmap (&inframe);
2483 gst_buffer_unref (inbuffer);
2489 GST_START_TEST (test_video_transfer)
2493 for (j = GST_VIDEO_TRANSFER_GAMMA10; j <= GST_VIDEO_TRANSFER_LOG316; j++) {
2494 for (i = 0; i < 256; i++) {
2497 val1 = gst_video_color_transfer_encode (j, i / 255.0);
2498 fail_if (val1 < 0.0 || val1 > 1.0);
2500 val2 = gst_video_color_transfer_decode (j, val1);
2501 fail_if (val2 < 0.0 || val2 > 1.0);
2503 GST_DEBUG ("%d: %d %f->%f->%f %d", j, i, i / 255.0, val1, val2,
2504 (int) lrint (val2 * 255.0));
2506 fail_if (val2 != 0.0);
2508 fail_if (lrint (val2 * 255.0) != i);
2515 GST_START_TEST (test_video_center_rect)
2517 GstVideoRectangle src, dest, result, expected;
2519 #define NEW_RECT(x,y,w,h) ((GstVideoRectangle) {x,y,w,h})
2520 #define CHECK_RECT(res, exp) \
2521 fail_unless_equals_int(exp.x, res.x);\
2522 fail_unless_equals_int(exp.y, res.y);\
2523 fail_unless_equals_int(exp.w, res.w);\
2524 fail_unless_equals_int(exp.h, res.h);
2526 /* 1:1 Aspect Ratio */
2527 src = NEW_RECT (0, 0, 100, 100);
2528 dest = NEW_RECT (0, 0, 100, 100);
2529 expected = NEW_RECT (0, 0, 100, 100);
2530 gst_video_sink_center_rect (src, dest, &result, TRUE);
2531 CHECK_RECT (result, expected);
2533 src = NEW_RECT (0, 0, 100, 100);
2534 dest = NEW_RECT (0, 0, 50, 50);
2535 expected = NEW_RECT (0, 0, 50, 50);
2536 gst_video_sink_center_rect (src, dest, &result, TRUE);
2537 CHECK_RECT (result, expected);
2539 src = NEW_RECT (0, 0, 100, 100);
2540 dest = NEW_RECT (50, 50, 100, 100);
2541 expected = NEW_RECT (50, 50, 100, 100);
2542 gst_video_sink_center_rect (src, dest, &result, TRUE);
2543 CHECK_RECT (result, expected);
2545 /* Aspect ratio scaling (tall) */
2546 src = NEW_RECT (0, 0, 50, 100);
2547 dest = NEW_RECT (0, 0, 50, 50);
2548 expected = NEW_RECT (12, 0, 25, 50);
2549 gst_video_sink_center_rect (src, dest, &result, TRUE);
2550 CHECK_RECT (result, expected);
2552 src = NEW_RECT (0, 0, 50, 100);
2553 dest = NEW_RECT (50, 50, 50, 50);
2554 expected = NEW_RECT (62, 50, 25, 50);
2555 gst_video_sink_center_rect (src, dest, &result, TRUE);
2556 CHECK_RECT (result, expected);
2558 /* Aspect ratio scaling (wide) */
2559 src = NEW_RECT (0, 0, 100, 50);
2560 dest = NEW_RECT (0, 0, 50, 50);
2561 expected = NEW_RECT (0, 12, 50, 25);
2562 gst_video_sink_center_rect (src, dest, &result, TRUE);
2563 CHECK_RECT (result, expected);
2565 src = NEW_RECT (0, 0, 100, 50);
2566 dest = NEW_RECT (50, 50, 50, 50);
2567 expected = NEW_RECT (50, 62, 50, 25);
2568 gst_video_sink_center_rect (src, dest, &result, TRUE);
2569 CHECK_RECT (result, expected);
2574 void test_overlay_blend_rect (gint x, gint y, gint width, gint height,
2575 GstVideoFrame * video_frame);
2576 void test_overlay_blend_rect_verify (gint x, gint y, gint width,
2577 gint height, GstVideoFrame * video_frame);
2578 #define VIDEO_WIDTH 320
2579 #define VIDEO_HEIGHT 240
2582 test_overlay_blend_rect_verify (gint x, gint y, gint width, gint height,
2583 GstVideoFrame * video_frame)
2586 gint i = 0, prev_i = 0;
2588 gint temp_width = 0, temp_height = 0;
2590 data = GST_VIDEO_FRAME_PLANE_DATA (video_frame, 0);
2591 size = GST_VIDEO_FRAME_SIZE (video_frame);
2593 if (x + width < 0 || y + height < 0 || x >= VIDEO_WIDTH || y >= VIDEO_HEIGHT)
2596 temp_width = width + x;
2597 else if (x > 0 && (x + width) <= VIDEO_WIDTH)
2600 temp_width = VIDEO_WIDTH - x;
2602 temp_height = height + y;
2603 else if (y > 0 && (y + height) <= VIDEO_HEIGHT)
2604 temp_height = height;
2606 temp_height = VIDEO_HEIGHT - y;
2608 if (x <= 0 && y <= 0)
2611 i = (((x <= 0) ? 0 : x) + (((y <= 0) ? 0 : y) * VIDEO_WIDTH)) * 4;
2614 for (; i < size - 4; i += 4) {
2615 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
2617 fail_unless_equals_int (data[i], 0x80);
2618 fail_unless_equals_int (data[i + 1], 0x80);
2619 fail_unless_equals_int (data[i + 2], 0x80);
2620 fail_unless_equals_int (data[i + 3], 0x80);
2623 fail_unless_equals_int (data[i], 0x00);
2624 fail_unless_equals_int (data[i + 1], 0x80);
2625 fail_unless_equals_int (data[i + 2], 0x80);
2626 fail_unless_equals_int (data[i + 3], 0x80);
2628 if ((i + 4) == (4 * (((((y > 0) ? (y + temp_height) : temp_height) -
2629 1) * VIDEO_WIDTH) + ((x >
2630 0) ? (x + temp_width) : temp_width))))
2632 if ((i + 4 - prev_i) == ((temp_width) * 4)) {
2633 i += ((VIDEO_WIDTH - (temp_width)) * 4);
2641 test_overlay_blend_rect (gint x, gint y, gint width, gint height,
2642 GstVideoFrame * video_frame)
2644 GstVideoOverlayComposition *comp1;
2645 GstVideoOverlayRectangle *rect1;
2646 GstBuffer *pix, *pix1;
2649 memset (video_frame, 0, sizeof (GstVideoFrame));
2651 gst_buffer_new_and_alloc (VIDEO_WIDTH * VIDEO_HEIGHT * sizeof (guint32));
2652 gst_buffer_memset (pix, 0, 0, gst_buffer_get_size (pix));
2653 gst_video_info_init (&vinfo);
2654 gst_video_info_set_format (&vinfo, GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB,
2655 VIDEO_WIDTH, VIDEO_HEIGHT);
2656 gst_video_frame_map (video_frame, &vinfo, pix, GST_MAP_READWRITE);
2657 gst_buffer_unref (pix);
2660 pix1 = gst_buffer_new_and_alloc (width * height * sizeof (guint32));
2661 gst_buffer_memset (pix1, 0, 0x80, gst_buffer_get_size (pix1));
2662 gst_buffer_add_video_meta (pix1, GST_VIDEO_FRAME_FLAG_NONE,
2663 GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB, width, height);
2664 rect1 = gst_video_overlay_rectangle_new_raw (pix1,
2665 x, y, width, height, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
2666 gst_buffer_unref (pix1);
2669 comp1 = gst_video_overlay_composition_new (rect1);
2670 fail_unless (gst_video_overlay_composition_blend (comp1, video_frame));
2671 gst_video_overlay_composition_unref (comp1);
2672 gst_video_overlay_rectangle_unref (rect1);
2674 test_overlay_blend_rect_verify (x, y, width, height, video_frame);
2675 gst_video_frame_unmap (video_frame);
2678 GST_START_TEST (test_overlay_blend)
2680 GstVideoFrame video_frame;
2682 /* Overlay width & height smaller than video width & height */
2683 /* Overlay rendered completely left of video surface
2684 * x + overlay_width <= 0 */
2685 test_overlay_blend_rect (-60, 50, 50, 50, &video_frame);
2686 /* Overlay rendered completely right of video surface
2687 * x >= video_width */
2688 test_overlay_blend_rect (330, 50, 50, 50, &video_frame);
2689 /* Overlay rendered completely top of video surface
2690 * y + overlay_height <= 0 */
2691 test_overlay_blend_rect (50, -60, 50, 50, &video_frame);
2692 /* Overlay rendered completely bottom of video surface
2693 * y >= video_height */
2694 test_overlay_blend_rect (50, 250, 50, 50, &video_frame);
2695 /* Overlay rendered partially left of video surface
2696 * x < 0 && -x < overlay_width */
2697 test_overlay_blend_rect (-40, 50, 50, 50, &video_frame);
2698 /* Overlay rendered partially right of video surface
2699 * x < video_width && (overlay_width + x) > video_width */
2700 test_overlay_blend_rect (300, 50, 50, 50, &video_frame);
2701 /* Overlay rendered partially top of video surface
2702 * y < 0 && -y < overlay_height */
2703 test_overlay_blend_rect (50, -40, 50, 50, &video_frame);
2704 /* Overlay rendered partially bottom of video surface
2705 * y < video_height && (overlay_height + y) > video_height */
2706 test_overlay_blend_rect (50, 220, 50, 50, &video_frame);
2708 /* Overlay width & height bigger than video width & height */
2709 /* Overlay rendered completely left of video surface
2710 * x + overlay_width <= 0 */
2711 test_overlay_blend_rect (-360, 50, 350, 250, &video_frame);
2712 /* Overlay rendered completely right of video surface
2713 * x >= video_width */
2714 test_overlay_blend_rect (330, 50, 350, 250, &video_frame);
2715 /* Overlay rendered completely top of video surface
2716 * y + overlay_height <= 0 */
2717 test_overlay_blend_rect (50, -260, 350, 250, &video_frame);
2718 /* Overlay rendered completely bottom of video surface
2719 * y >= video_height */
2720 test_overlay_blend_rect (50, 250, 350, 250, &video_frame);
2721 /* Overlay rendered partially left of video surface
2722 * x < 0 && -x < overlay_width */
2723 test_overlay_blend_rect (-40, 50, 350, 250, &video_frame);
2724 /* Overlay rendered partially right of video surface
2725 * x < video_width && (overlay_width + x) > video_width */
2726 test_overlay_blend_rect (300, 50, 350, 250, &video_frame);
2727 /* Overlay rendered partially top of video surface
2728 * y < 0 && -y < overlay_height */
2729 test_overlay_blend_rect (50, -40, 350, 250, &video_frame);
2730 /* Overlay rendered partially bottom of video surface
2731 * y < video_height && (overlay_height + y) > video_height */
2732 test_overlay_blend_rect (50, 220, 350, 250, &video_frame);
2737 GST_START_TEST (test_overlay_composition_over_transparency)
2739 GstVideoOverlayComposition *comp1;
2740 GstVideoOverlayRectangle *rect1;
2741 GstBuffer *pix1, *pix2;
2745 GstVideoFrame video_frame;
2746 guint fwidth = 200, height = 50, swidth = 100;
2748 memset (&video_frame, 0, sizeof (GstVideoFrame));
2750 pix1 = gst_buffer_new_and_alloc (fwidth * sizeof (guint32) * height);
2751 gst_buffer_memset (pix1, 0, 0x00, gst_buffer_get_size (pix1));
2752 gst_video_info_init (&vinfo);
2753 gst_video_info_set_format (&vinfo, GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB,
2755 gst_video_frame_map (&video_frame, &vinfo, pix1, GST_MAP_READWRITE);
2756 gst_buffer_unref (pix1);
2758 pix2 = gst_buffer_new_and_alloc (swidth * sizeof (guint32) * height);
2759 gst_buffer_memset (pix2, 0, 0xFF, gst_buffer_get_size (pix2));
2760 gst_buffer_add_video_meta (pix2, GST_VIDEO_FRAME_FLAG_NONE,
2761 GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB, swidth, height);
2762 rect1 = gst_video_overlay_rectangle_new_raw (pix2, swidth, 0,
2763 swidth, height, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
2765 comp1 = gst_video_overlay_composition_new (rect1);
2766 fail_unless (gst_video_overlay_composition_blend (comp1, &video_frame));
2767 gst_video_overlay_composition_unref (comp1);
2768 gst_video_overlay_rectangle_unref (rect1);
2769 gst_buffer_unref (pix2);
2771 data = GST_VIDEO_FRAME_PLANE_DATA (&video_frame, 0);
2773 fail_unless_equals_int (data[0], 0x00);
2774 fail_unless_equals_int (data[1], 0x00);
2775 fail_unless_equals_int (data[2], 0x00);
2776 fail_unless_equals_int (data[3], 0x00);
2778 data += swidth * sizeof (guint32);
2780 fail_unless_equals_int (data[0], 0xFF);
2781 fail_unless_equals_int (data[1], 0xFF);
2782 fail_unless_equals_int (data[2], 0xFF);
2783 fail_unless_equals_int (data[3], 0xFF);
2785 gst_video_frame_unmap (&video_frame);
2794 Suite *s = suite_create ("video support library");
2795 TCase *tc_chain = tcase_create ("general");
2797 tcase_set_timeout (tc_chain, 60 * 60);
2799 suite_add_tcase (s, tc_chain);
2800 tcase_add_test (tc_chain, test_video_formats);
2801 tcase_add_test (tc_chain, test_video_formats_overflow);
2802 tcase_add_test (tc_chain, test_video_formats_rgb);
2803 tcase_add_test (tc_chain, test_video_formats_rgba_large_dimension);
2804 tcase_add_test (tc_chain, test_video_formats_all);
2805 tcase_add_test (tc_chain, test_video_formats_pack_unpack);
2806 tcase_add_test (tc_chain, test_dar_calc);
2807 tcase_add_test (tc_chain, test_parse_caps_rgb);
2808 tcase_add_test (tc_chain, test_parse_caps_multiview);
2809 tcase_add_test (tc_chain, test_parse_colorimetry);
2810 tcase_add_test (tc_chain, test_events);
2811 tcase_add_test (tc_chain, test_convert_frame);
2812 tcase_add_test (tc_chain, test_convert_frame_async);
2813 tcase_add_test (tc_chain, test_video_size_from_caps);
2814 tcase_add_test (tc_chain, test_overlay_composition);
2815 tcase_add_test (tc_chain, test_overlay_composition_premultiplied_alpha);
2816 tcase_add_test (tc_chain, test_overlay_composition_global_alpha);
2817 tcase_add_test (tc_chain, test_video_pack_unpack2);
2818 tcase_add_test (tc_chain, test_video_chroma);
2819 tcase_add_test (tc_chain, test_video_scaler);
2820 tcase_add_test (tc_chain, test_video_color_convert);
2821 tcase_add_test (tc_chain, test_video_size_convert);
2822 tcase_add_test (tc_chain, test_video_convert);
2823 tcase_add_test (tc_chain, test_video_transfer);
2824 tcase_add_test (tc_chain, test_overlay_blend);
2825 tcase_add_test (tc_chain, test_video_center_rect);
2826 tcase_add_test (tc_chain, test_overlay_composition_over_transparency);
2831 GST_CHECK_MAIN (video);