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>
32 #include <gst/check/gstcheck.h>
34 #include <gst/video/video.h>
35 #include <gst/video/gstvideometa.h>
36 #include <gst/video/video-overlay-composition.h>
39 /* These are from the current/old videotestsrc; we check our new public API
40 * in libgstvideo against the old one to make sure the sizes and offsets
43 typedef struct paintinfo_struct paintinfo;
44 struct paintinfo_struct
46 unsigned char *dest; /* pointer to first byte of video data */
47 unsigned char *yp, *up, *vp; /* pointers to first byte of each component
48 * for both packed/planar YUV and RGB */
49 unsigned char *ap; /* pointer to first byte of alpha component */
50 unsigned char *endptr; /* pointer to byte beyond last video data */
58 struct fourcc_list_struct
63 void (*paint_setup) (paintinfo * p, unsigned char *dest);
66 static void paint_setup_I420 (paintinfo * p, unsigned char *dest);
67 static void paint_setup_YV12 (paintinfo * p, unsigned char *dest);
68 static void paint_setup_YUY2 (paintinfo * p, unsigned char *dest);
69 static void paint_setup_UYVY (paintinfo * p, unsigned char *dest);
70 static void paint_setup_YVYU (paintinfo * p, unsigned char *dest);
71 static void paint_setup_IYU2 (paintinfo * p, unsigned char *dest);
72 static void paint_setup_Y41B (paintinfo * p, unsigned char *dest);
73 static void paint_setup_Y42B (paintinfo * p, unsigned char *dest);
74 static void paint_setup_GRAY8 (paintinfo * p, unsigned char *dest);
75 static void paint_setup_AYUV (paintinfo * p, unsigned char *dest);
78 static void paint_setup_IMC1 (paintinfo * p, unsigned char *dest);
79 static void paint_setup_IMC2 (paintinfo * p, unsigned char *dest);
80 static void paint_setup_IMC3 (paintinfo * p, unsigned char *dest);
81 static void paint_setup_IMC4 (paintinfo * p, unsigned char *dest);
83 static void paint_setup_YUV9 (paintinfo * p, unsigned char *dest);
84 static void paint_setup_YVU9 (paintinfo * p, unsigned char *dest);
86 int fourcc_get_size (struct fourcc_list_struct *fourcc, int w, int h);
88 struct fourcc_list_struct fourcc_list[] = {
90 {"YUY2", "YUY2", 16, paint_setup_YUY2},
91 {"UYVY", "UYVY", 16, paint_setup_UYVY},
92 {"Y422", "Y422", 16, paint_setup_UYVY},
93 {"UYNV", "UYNV", 16, paint_setup_UYVY}, /* FIXME: UYNV? */
94 {"YVYU", "YVYU", 16, paint_setup_YVYU},
95 {"AYUV", "AYUV", 32, paint_setup_AYUV},
98 /*{ "IUYV", "IUY2", 16, paint_setup_YVYU }, */
101 /*{ "cyuv", "cyuv", 16, paint_setup_YVYU }, */
103 /*{ "Y41P", "Y41P", 12, paint_setup_YVYU }, */
106 /*{ "IY41", "IY41", 12, paint_setup_YVYU }, */
108 /*{ "Y211", "Y211", 8, paint_setup_YVYU }, */
110 /*{ "Y41T", "Y41T", 12, paint_setup_YVYU }, */
111 /*{ "Y42P", "Y42P", 16, paint_setup_YVYU }, */
112 /*{ "CLJR", "CLJR", 8, paint_setup_YVYU }, */
113 /*{ "IYU1", "IYU1", 12, paint_setup_YVYU }, */
114 {"IYU2", "IYU2", 24, paint_setup_IYU2},
118 {"YVU9", "YVU9", 9, paint_setup_YVU9},
120 {"YUV9", "YUV9", 9, paint_setup_YUV9},
123 {"YV12", "YV12", 12, paint_setup_YV12},
125 {"I420", "I420", 12, paint_setup_I420},
130 {"IMC1", "IMC1", 16, paint_setup_IMC1},
132 {"IMC2", "IMC2", 12, paint_setup_IMC2},
134 {"IMC3", "IMC3", 16, paint_setup_IMC3},
136 {"IMC4", "IMC4", 12, paint_setup_IMC4},
140 {"Y41B", "Y41B", 12, paint_setup_Y41B},
142 {"Y42B", "Y42B", 16, paint_setup_Y42B},
143 /* GRAY8 grayscale */
144 {"GRAY8", "GRAY8", 8, paint_setup_GRAY8}
147 /* returns the size in bytes for one video frame of the given dimensions
148 * given the fourcc */
150 fourcc_get_size (struct fourcc_list_struct *fourcc, int w, int h)
152 paintinfo pi = { NULL, };
158 fourcc->paint_setup (p, NULL);
160 return (unsigned long) p->endptr;
164 paint_setup_I420 (paintinfo * p, unsigned char *dest)
167 p->ystride = GST_ROUND_UP_4 (p->width);
168 p->up = p->yp + p->ystride * GST_ROUND_UP_2 (p->height);
169 p->ustride = GST_ROUND_UP_8 (p->width) / 2;
170 p->vp = p->up + p->ustride * GST_ROUND_UP_2 (p->height) / 2;
171 p->vstride = GST_ROUND_UP_8 (p->ystride) / 2;
172 p->endptr = p->vp + p->vstride * GST_ROUND_UP_2 (p->height) / 2;
176 paint_setup_YV12 (paintinfo * p, unsigned char *dest)
179 p->ystride = GST_ROUND_UP_4 (p->width);
180 p->vp = p->yp + p->ystride * GST_ROUND_UP_2 (p->height);
181 p->vstride = GST_ROUND_UP_8 (p->ystride) / 2;
182 p->up = p->vp + p->vstride * GST_ROUND_UP_2 (p->height) / 2;
183 p->ustride = GST_ROUND_UP_8 (p->ystride) / 2;
184 p->endptr = p->up + p->ustride * GST_ROUND_UP_2 (p->height) / 2;
188 paint_setup_AYUV (paintinfo * p, unsigned char *dest)
194 p->ystride = p->width * 4;
195 p->endptr = dest + p->ystride * p->height;
199 paint_setup_YUY2 (paintinfo * p, unsigned char *dest)
204 p->ystride = GST_ROUND_UP_2 (p->width) * 2;
205 p->endptr = dest + p->ystride * p->height;
209 paint_setup_UYVY (paintinfo * p, unsigned char *dest)
214 p->ystride = GST_ROUND_UP_2 (p->width) * 2;
215 p->endptr = dest + p->ystride * p->height;
219 paint_setup_YVYU (paintinfo * p, unsigned char *dest)
224 p->ystride = GST_ROUND_UP_2 (p->width) * 2;
225 p->endptr = dest + p->ystride * p->height;
229 paint_setup_IYU2 (paintinfo * p, unsigned char *dest)
235 p->ystride = GST_ROUND_UP_4 (p->width * 3);
236 p->endptr = dest + p->ystride * p->height;
240 paint_setup_Y41B (paintinfo * p, unsigned char *dest)
243 p->ystride = GST_ROUND_UP_4 (p->width);
244 p->up = p->yp + p->ystride * p->height;
245 p->ustride = GST_ROUND_UP_16 (p->width) / 4;
246 p->vp = p->up + p->ustride * p->height;
247 p->vstride = GST_ROUND_UP_16 (p->width) / 4;
248 p->endptr = p->vp + p->vstride * p->height;
252 paint_setup_Y42B (paintinfo * p, unsigned char *dest)
255 p->ystride = GST_ROUND_UP_4 (p->width);
256 p->up = p->yp + p->ystride * p->height;
257 p->ustride = GST_ROUND_UP_8 (p->width) / 2;
258 p->vp = p->up + p->ustride * p->height;
259 p->vstride = GST_ROUND_UP_8 (p->width) / 2;
260 p->endptr = p->vp + p->vstride * p->height;
264 paint_setup_GRAY8 (paintinfo * p, unsigned char *dest)
268 p->ystride = GST_ROUND_UP_4 (p->width);
269 p->endptr = dest + p->ystride * p->height;
274 paint_setup_IMC1 (paintinfo * p, unsigned char *dest)
277 p->up = dest + p->width * p->height;
278 p->vp = dest + p->width * p->height + p->width * p->height / 2;
282 paint_setup_IMC2 (paintinfo * p, unsigned char *dest)
285 p->vp = dest + p->width * p->height;
286 p->up = dest + p->width * p->height + p->width / 2;
290 paint_setup_IMC3 (paintinfo * p, unsigned char *dest)
293 p->up = dest + p->width * p->height + p->width * p->height / 2;
294 p->vp = dest + p->width * p->height;
298 paint_setup_IMC4 (paintinfo * p, unsigned char *dest)
301 p->vp = dest + p->width * p->height + p->width / 2;
302 p->up = dest + p->width * p->height;
307 paint_setup_YVU9 (paintinfo * p, unsigned char *dest)
310 p->ystride = GST_ROUND_UP_4 (p->width);
311 p->vp = p->yp + p->ystride * p->height;
312 p->vstride = GST_ROUND_UP_4 (p->ystride / 4);
313 p->up = p->vp + p->vstride * (GST_ROUND_UP_4 (p->height) / 4);
314 p->ustride = GST_ROUND_UP_4 (p->ystride / 4);
315 p->endptr = p->up + p->ustride * (GST_ROUND_UP_4 (p->height) / 4);
319 paint_setup_YUV9 (paintinfo * p, unsigned char *dest)
322 p->ystride = GST_ROUND_UP_4 (p->width);
323 p->up = p->yp + p->ystride * p->height;
324 p->ustride = GST_ROUND_UP_4 (p->ystride / 4);
325 p->vp = p->up + p->ustride * (GST_ROUND_UP_4 (p->height) / 4);
326 p->vstride = GST_ROUND_UP_4 (p->ystride / 4);
327 p->endptr = p->vp + p->vstride * (GST_ROUND_UP_4 (p->height) / 4);
330 #define gst_video_format_is_packed video_format_is_packed
332 video_format_is_packed (GstVideoFormat fmt)
335 case GST_VIDEO_FORMAT_I420:
336 case GST_VIDEO_FORMAT_YV12:
337 case GST_VIDEO_FORMAT_Y41B:
338 case GST_VIDEO_FORMAT_Y42B:
339 case GST_VIDEO_FORMAT_GRAY8:
340 case GST_VIDEO_FORMAT_YUV9:
341 case GST_VIDEO_FORMAT_YVU9:
343 case GST_VIDEO_FORMAT_IYU1:
344 case GST_VIDEO_FORMAT_IYU2:
345 case GST_VIDEO_FORMAT_YUY2:
346 case GST_VIDEO_FORMAT_YVYU:
347 case GST_VIDEO_FORMAT_UYVY:
348 case GST_VIDEO_FORMAT_VYUY:
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:
363 g_return_val_if_reached (FALSE);
369 get_num_formats (void)
371 gint num_formats = 100;
372 fail_unless (gst_video_format_to_string (num_formats) == NULL);
373 while (gst_video_format_to_string (num_formats) == NULL)
375 GST_INFO ("number of known video formats: %d", num_formats);
376 return num_formats + 1;
379 GST_START_TEST (test_video_formats_all)
382 const GValue *val, *list_val;
384 guint num, n, num_formats;
386 num_formats = get_num_formats ();
388 caps = gst_caps_from_string ("video/x-raw, format=" GST_VIDEO_FORMATS_ALL);
389 s = gst_caps_get_structure (caps, 0);
390 val = gst_structure_get_value (s, "format");
391 fail_unless (val != NULL);
392 fail_unless (GST_VALUE_HOLDS_LIST (val));
393 num = gst_value_list_get_size (val);
394 fail_unless (num > 0);
395 for (n = 0; n < num; ++n) {
396 const gchar *fmt_str;
398 list_val = gst_value_list_get_value (val, n);
399 fail_unless (G_VALUE_HOLDS_STRING (list_val));
400 fmt_str = g_value_get_string (list_val);
401 GST_INFO ("format: %s", fmt_str);
402 fail_if (gst_video_format_from_string (fmt_str) ==
403 GST_VIDEO_FORMAT_UNKNOWN);
405 /* Take into account GST_VIDEO_FORMAT_ENCODED and UNKNOWN */
406 fail_unless_equals_int (num, num_formats - 2);
408 gst_caps_unref (caps);
415 GST_START_TEST (test_video_formats_pack_unpack)
417 guint n, num_formats;
419 num_formats = get_num_formats ();
421 for (n = GST_VIDEO_FORMAT_ENCODED + 1; n < num_formats; ++n) {
422 const GstVideoFormatInfo *vfinfo, *unpackinfo;
423 GstVideoFormat fmt = n;
425 gpointer data[GST_VIDEO_MAX_PLANES];
426 gint stride[GST_VIDEO_MAX_PLANES];
427 guint8 *vdata, *unpack_data;
428 gsize vsize, unpack_size;
431 GST_INFO ("testing %s", gst_video_format_to_string (fmt));
433 vfinfo = gst_video_format_get_info (fmt);
434 fail_unless (vfinfo != NULL);
436 unpackinfo = gst_video_format_get_info (vfinfo->unpack_format);
437 fail_unless (unpackinfo != NULL);
439 gst_video_info_init (&vinfo);
440 gst_video_info_set_format (&vinfo, fmt, WIDTH, HEIGHT);
441 vsize = GST_VIDEO_INFO_SIZE (&vinfo);
442 vdata = g_malloc (vsize);
443 memset (vdata, 0x99, vsize);
445 g_assert (vfinfo->pack_lines == 1);
448 GST_VIDEO_FORMAT_INFO_BITS (unpackinfo) *
449 GST_VIDEO_FORMAT_INFO_N_COMPONENTS (unpackinfo) *
450 GST_ROUND_UP_16 (WIDTH);
451 unpack_data = g_malloc (unpack_size);
453 for (p = 0; p < GST_VIDEO_INFO_N_PLANES (&vinfo); ++p) {
454 data[p] = vdata + GST_VIDEO_INFO_PLANE_OFFSET (&vinfo, p);
455 stride[p] = GST_VIDEO_INFO_PLANE_STRIDE (&vinfo, p);
459 vfinfo->unpack_func (vfinfo, GST_VIDEO_PACK_FLAG_NONE, unpack_data, data,
460 stride, 0, 0, WIDTH);
463 vfinfo->pack_func (vfinfo, GST_VIDEO_PACK_FLAG_NONE, unpack_data,
464 unpack_size, data, stride, GST_VIDEO_CHROMA_SITE_UNKNOWN, 0, WIDTH);
467 vfinfo->unpack_func (vfinfo, GST_VIDEO_PACK_FLAG_NONE, unpack_data, data,
468 stride, 0, HEIGHT - 1, WIDTH);
471 vfinfo->pack_func (vfinfo, GST_VIDEO_PACK_FLAG_NONE, unpack_data,
472 unpack_size, data, stride, GST_VIDEO_CHROMA_SITE_UNKNOWN, HEIGHT - 1,
475 g_free (unpack_data);
484 GST_START_TEST (test_video_formats)
488 for (i = 0; i < G_N_ELEMENTS (fourcc_list); ++i) {
489 const GstVideoFormatInfo *vf_info;
495 s = fourcc_list[i].fourcc;
496 fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]);
497 fmt = gst_video_format_from_fourcc (fourcc);
499 if (fmt == GST_VIDEO_FORMAT_UNKNOWN) {
500 GST_DEBUG ("Unknown format %s, skipping tests", fourcc_list[i].fourcc);
504 vf_info = gst_video_format_get_info (fmt);
505 fail_unless (vf_info != NULL);
507 fail_unless_equals_int (GST_VIDEO_FORMAT_INFO_FORMAT (vf_info), fmt);
509 GST_INFO ("Fourcc %s, packed=%d", fourcc_list[i].fourcc,
510 gst_video_format_is_packed (fmt));
512 fail_unless (GST_VIDEO_FORMAT_INFO_IS_YUV (vf_info));
514 /* use any non-NULL pointer so we can compare against NULL */
516 paintinfo paintinfo = { 0, };
517 fourcc_list[i].paint_setup (&paintinfo, (unsigned char *) s);
518 if (paintinfo.ap != NULL) {
519 fail_unless (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vf_info));
521 fail_if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vf_info));
525 for (w = 1; w <= 65; ++w) {
526 for (h = 1; h <= 65; ++h) {
528 paintinfo paintinfo = { 0, };
529 guint off0, off1, off2, off3;
530 guint cs0, cs1, cs2, cs3;
533 GST_LOG ("%s, %dx%d", fourcc_list[i].fourcc, w, h);
535 gst_video_info_init (&vinfo);
536 gst_video_info_set_format (&vinfo, fmt, w, h);
539 paintinfo.height = h;
540 fourcc_list[i].paint_setup (&paintinfo, NULL);
541 fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 0),
543 if (!gst_video_format_is_packed (fmt)
544 && GST_VIDEO_INFO_N_PLANES (&vinfo) <= 2) {
546 fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 1),
548 fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 2),
550 /* check component_width * height against offsets/size somehow? */
553 size = GST_VIDEO_INFO_SIZE (&vinfo);
554 off0 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 0);
555 off1 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 1);
556 off2 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 2);
558 GST_INFO ("size %d <> %d", size, (int) ((guintptr) paintinfo.endptr));
559 GST_INFO ("off0 %d <> %d", off0, (int) ((guintptr) paintinfo.yp));
560 GST_INFO ("off1 %d <> %d", off1, (int) ((guintptr) paintinfo.up));
561 GST_INFO ("off2 %d <> %d", off2, (int) ((guintptr) paintinfo.vp));
563 fail_unless_equals_int (size, (unsigned long) paintinfo.endptr);
564 fail_unless_equals_int (off0, (unsigned long) paintinfo.yp);
565 fail_unless_equals_int (off1, (unsigned long) paintinfo.up);
566 fail_unless_equals_int (off2, (unsigned long) paintinfo.vp);
568 /* should be 0 if there's no alpha component */
569 off3 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 3);
570 fail_unless_equals_int (off3, (unsigned long) paintinfo.ap);
572 cs0 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 0) *
573 GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 0);
574 cs1 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 1) *
575 GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 1);
576 cs2 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 2) *
577 GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 2);
579 /* GST_LOG ("cs0=%d,cs1=%d,cs2=%d,off0=%d,off1=%d,off2=%d,size=%d",
580 cs0, cs1, cs2, off0, off1, off2, size); */
582 if (!gst_video_format_is_packed (fmt))
583 fail_unless (cs0 <= off1);
585 if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vinfo.finfo)) {
586 cs3 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 3) *
587 GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 2);
588 fail_unless (cs3 < size);
589 /* U/V/alpha shouldn't take up more space than the Y component */
590 fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0);
591 fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0);
592 fail_if (cs3 > cs0, "cs3 (%d) should be <= cs0 (%d)", cs3, cs0);
594 /* all components together shouldn't take up more space than size */
595 fail_unless (cs0 + cs1 + cs2 + cs3 <= size);
597 /* U/V shouldn't take up more space than the Y component */
598 fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0);
599 fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0);
601 /* all components together shouldn't take up more space than size */
602 fail_unless (cs0 + cs1 + cs2 <= size,
603 "cs0 (%d) + cs1 (%d) + cs2 (%d) should be <= size (%d)",
604 cs0, cs1, cs2, size);
613 GST_START_TEST (test_video_formats_overflow)
617 gst_video_info_init (&vinfo);
619 fail_unless (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, 32768,
621 /* fails due to simplification: we forbid some things that would in theory be fine.
622 * We assume a 128 byte alignment for the width currently
623 * fail_unless (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, 32767, 32768));
625 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, 32768,
628 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB,
629 G_MAXINT / 2, G_MAXINT));
630 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, G_MAXINT,
632 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB,
633 G_MAXINT / 2, G_MAXINT / 2));
634 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, G_MAXINT,
636 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB,
637 G_MAXUINT / 2, G_MAXUINT));
638 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, G_MAXUINT,
640 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB,
641 G_MAXUINT / 2, G_MAXUINT / 2));
642 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, G_MAXUINT,
645 fail_unless (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB,
646 1073741824 - 128, 1));
647 fail_if (gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_ARGB, 1073741824,
654 GST_START_TEST (test_video_formats_rgb)
657 gint width, height, framerate_n, framerate_d, par_n, par_d;
659 GstStructure *structure;
661 gst_video_info_init (&vinfo);
662 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_RGB, 800, 600);
667 caps = gst_video_info_to_caps (&vinfo);
668 structure = gst_caps_get_structure (caps, 0);
670 fail_unless (gst_structure_get_int (structure, "width", &width));
671 fail_unless (gst_structure_get_int (structure, "height", &height));
672 fail_unless (gst_structure_get_fraction (structure, "framerate", &framerate_n,
674 fail_unless (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
677 fail_unless (width == 800);
678 fail_unless (height == 600);
679 fail_unless (framerate_n == 0);
680 fail_unless (framerate_d == 1);
681 fail_unless (par_n == 1);
682 fail_unless (par_d == 1);
684 gst_caps_unref (caps);
690 GST_START_TEST (test_video_formats_rgba_large_dimension)
693 gint width, height, framerate_n, framerate_d, par_n, par_d;
695 GstStructure *structure;
697 gst_video_info_init (&vinfo);
698 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_RGBA, 29700, 21000);
703 caps = gst_video_info_to_caps (&vinfo);
704 structure = gst_caps_get_structure (caps, 0);
706 fail_unless (gst_structure_get_int (structure, "width", &width));
707 fail_unless (gst_structure_get_int (structure, "height", &height));
708 fail_unless (gst_structure_get_fraction (structure, "framerate", &framerate_n,
710 fail_unless (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
713 fail_unless (width == 29700);
714 fail_unless (height == 21000);
715 fail_unless (framerate_n == 0);
716 fail_unless (framerate_d == 1);
717 fail_unless (par_n == 1);
718 fail_unless (par_d == 1);
719 fail_unless (vinfo.size == (gsize) 29700 * 21000 * 4);
721 gst_caps_unref (caps);
726 GST_START_TEST (test_guess_framerate)
728 /* Check some obvious exact framerates */
730 fail_unless (gst_video_guess_framerate (GST_SECOND / 24, &fps_n, &fps_d));
731 fail_unless (fps_n == 24 && fps_d == 1);
733 fail_unless (gst_video_guess_framerate (GST_SECOND / 30, &fps_n, &fps_d));
734 fail_unless (fps_n == 30 && fps_d == 1);
736 fail_unless (gst_video_guess_framerate (GST_SECOND / 25, &fps_n, &fps_d));
737 fail_unless (fps_n == 25 && fps_d == 1);
739 /* Some NTSC rates: */
740 fail_unless (gst_video_guess_framerate (GST_SECOND * 1001 / 30000, &fps_n,
742 fail_unless (fps_n == 30000 && fps_d == 1001);
744 fail_unless (gst_video_guess_framerate (GST_SECOND * 1001 / 24000, &fps_n,
746 fail_unless (fps_n == 24000 && fps_d == 1001);
748 fail_unless (gst_video_guess_framerate (GST_SECOND * 1001 / 60000, &fps_n,
750 fail_unless (fps_n == 60000 && fps_d == 1001);
752 /* Check some high FPS, low durations */
753 fail_unless (gst_video_guess_framerate (GST_SECOND / 9000, &fps_n, &fps_d));
754 fail_unless (fps_n == 9000 && fps_d == 1);
755 fail_unless (gst_video_guess_framerate (GST_SECOND / 10000, &fps_n, &fps_d));
756 fail_unless (fps_n == 10000 && fps_d == 1);
757 fail_unless (gst_video_guess_framerate (GST_SECOND / 11000, &fps_n, &fps_d));
758 fail_unless (fps_n == 11000 && fps_d == 1);
759 fail_unless (gst_video_guess_framerate (GST_SECOND / 20000, &fps_n, &fps_d));
760 fail_unless (fps_n == 20000 && fps_d == 1);
761 fail_unless (gst_video_guess_framerate (GST_SECOND / 100000, &fps_n, &fps_d));
762 fail_unless (fps_n == 100000 && fps_d == 1);
767 GST_START_TEST (test_dar_calc)
769 guint display_ratio_n, display_ratio_d;
771 /* Ensure that various Display Ratio calculations are correctly done */
772 /* video 768x576, par 16/15, display par 16/15 = 4/3 */
773 fail_unless (gst_video_calculate_display_ratio (&display_ratio_n,
774 &display_ratio_d, 768, 576, 16, 15, 16, 15));
775 fail_unless (display_ratio_n == 4 && display_ratio_d == 3);
777 /* video 720x480, par 32/27, display par 1/1 = 16/9 */
778 fail_unless (gst_video_calculate_display_ratio (&display_ratio_n,
779 &display_ratio_d, 720, 480, 32, 27, 1, 1));
780 fail_unless (display_ratio_n == 16 && display_ratio_d == 9);
782 /* video 360x288, par 533333/500000, display par 16/15 =
783 * dar 1599999/1600000 */
784 fail_unless (gst_video_calculate_display_ratio (&display_ratio_n,
785 &display_ratio_d, 360, 288, 533333, 500000, 16, 15));
786 fail_unless (display_ratio_n == 1599999 && display_ratio_d == 1280000);
791 GST_START_TEST (test_parse_caps_rgb)
795 const gchar *tmpl_caps_string;
800 GST_VIDEO_CAPS_MAKE ("RGB"), GST_VIDEO_FORMAT_RGB}, {
801 GST_VIDEO_CAPS_MAKE ("BGR"), GST_VIDEO_FORMAT_BGR},
802 /* 32 bit (no alpha) */
804 GST_VIDEO_CAPS_MAKE ("RGBx"), GST_VIDEO_FORMAT_RGBx}, {
805 GST_VIDEO_CAPS_MAKE ("xRGB"), GST_VIDEO_FORMAT_xRGB}, {
806 GST_VIDEO_CAPS_MAKE ("BGRx"), GST_VIDEO_FORMAT_BGRx}, {
807 GST_VIDEO_CAPS_MAKE ("xBGR"), GST_VIDEO_FORMAT_xBGR},
808 /* 32 bit (with alpha) */
810 GST_VIDEO_CAPS_MAKE ("RGBA"), GST_VIDEO_FORMAT_RGBA}, {
811 GST_VIDEO_CAPS_MAKE ("ARGB"), GST_VIDEO_FORMAT_ARGB}, {
812 GST_VIDEO_CAPS_MAKE ("BGRA"), GST_VIDEO_FORMAT_BGRA}, {
813 GST_VIDEO_CAPS_MAKE ("ABGR"), GST_VIDEO_FORMAT_ABGR},
816 GST_VIDEO_CAPS_MAKE ("RGB16"), GST_VIDEO_FORMAT_RGB16}, {
817 GST_VIDEO_CAPS_MAKE ("BGR16"), GST_VIDEO_FORMAT_BGR16}, {
818 GST_VIDEO_CAPS_MAKE ("RGB15"), GST_VIDEO_FORMAT_RGB15}, {
819 GST_VIDEO_CAPS_MAKE ("BGR15"), GST_VIDEO_FORMAT_BGR15}
823 for (i = 0; i < G_N_ELEMENTS (formats); ++i) {
825 GstCaps *caps, *caps2;
827 caps = gst_caps_from_string (formats[i].tmpl_caps_string);
828 fail_unless (caps != NULL);
829 gst_caps_set_simple (caps, "width", G_TYPE_INT, 2 * (i + 1), "height",
830 G_TYPE_INT, i + 1, "framerate", GST_TYPE_FRACTION, 15, 1,
831 "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
832 "interlace-mode", G_TYPE_STRING, "progressive",
833 "colorimetry", G_TYPE_STRING, "1:1:0:0",
834 "multiview-mode", G_TYPE_STRING, "mono",
835 "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET, 0,
836 GST_FLAG_SET_MASK_EXACT, NULL);
837 g_assert (gst_caps_is_fixed (caps));
839 GST_DEBUG ("testing caps: %" GST_PTR_FORMAT, caps);
841 gst_video_info_init (&vinfo);
842 fail_unless (gst_video_info_from_caps (&vinfo, caps));
843 fail_unless_equals_int (GST_VIDEO_INFO_FORMAT (&vinfo), formats[i].fmt);
844 fail_unless_equals_int (GST_VIDEO_INFO_WIDTH (&vinfo), 2 * (i + 1));
845 fail_unless_equals_int (GST_VIDEO_INFO_HEIGHT (&vinfo), i + 1);
847 /* make sure they're serialised back correctly */
848 caps2 = gst_video_info_to_caps (&vinfo);
849 fail_unless (caps2 != NULL);
850 if (!gst_caps_is_equal (caps, caps2)) {
851 gchar *caps1s = gst_caps_to_string (caps);
852 gchar *caps2s = gst_caps_to_string (caps2);
853 fail ("caps [%s] not equal to caps2 [%s]", caps1s, caps2s);
858 gst_caps_unref (caps);
859 gst_caps_unref (caps2);
865 GST_START_TEST (test_parse_caps_multiview)
868 GstVideoMultiviewMode modes[] = {
869 GST_VIDEO_MULTIVIEW_MODE_MONO,
870 GST_VIDEO_MULTIVIEW_MODE_LEFT,
871 GST_VIDEO_MULTIVIEW_MODE_RIGHT,
872 GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE,
873 GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX,
874 GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED,
875 GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED,
876 GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM,
877 GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD,
878 GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME,
879 GST_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME,
880 GST_VIDEO_MULTIVIEW_MODE_SEPARATED,
882 GstVideoMultiviewFlags flags[] = {
883 GST_VIDEO_MULTIVIEW_FLAGS_NONE,
884 GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST,
885 GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED,
886 GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED,
887 GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED,
888 GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED,
889 GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO,
890 GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO |
891 GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST,
892 GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO |
893 GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED
896 for (i = 0; i < G_N_ELEMENTS (modes); i++) {
897 for (j = 0; j < G_N_ELEMENTS (flags); j++) {
901 gst_video_info_init (&vinfo);
902 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_I420, 320, 240);
904 GST_VIDEO_INFO_MULTIVIEW_MODE (&vinfo) = modes[i];
905 GST_VIDEO_INFO_MULTIVIEW_FLAGS (&vinfo) = flags[j];
907 caps = gst_video_info_to_caps (&vinfo);
908 fail_if (caps == NULL);
909 GST_LOG ("mview mode %d flags %x -> caps %" GST_PTR_FORMAT,
910 modes[i], flags[j], caps);
912 fail_unless (gst_video_info_from_caps (&vinfo, caps));
914 GST_LOG ("mview mode %d flags %x -> info mode %d flags %x",
915 modes[i], flags[j], GST_VIDEO_INFO_MULTIVIEW_MODE (&vinfo),
916 GST_VIDEO_INFO_MULTIVIEW_FLAGS (&vinfo));
918 fail_unless (GST_VIDEO_INFO_MULTIVIEW_MODE (&vinfo) == modes[i],
919 "Expected multiview mode %d got mode %d", modes[i],
920 GST_VIDEO_INFO_MULTIVIEW_MODE (&vinfo));
921 fail_unless (GST_VIDEO_INFO_MULTIVIEW_FLAGS (&vinfo) == flags[j],
922 "Expected multiview flags 0x%x got 0x%x", flags[j],
923 GST_VIDEO_INFO_MULTIVIEW_FLAGS (&vinfo));
925 gst_caps_unref (caps);
934 const gchar *string_from;
935 const gchar *string_to;
937 GstVideoColorimetry color;
940 #define MAKE_COLORIMETRY_TEST(s1,s2,n,r,m,t,p) { s1, s2, n, \
941 { GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \
942 GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p } }
944 GST_START_TEST (test_parse_colorimetry)
946 ColorimetryTest tests[] = {
947 MAKE_COLORIMETRY_TEST ("bt601", "bt601", "bt601",
948 _16_235, BT601, BT709, SMPTE170M),
949 MAKE_COLORIMETRY_TEST ("2:4:5:4", "bt601", "bt601",
950 _16_235, BT601, BT709, SMPTE170M),
951 MAKE_COLORIMETRY_TEST ("bt709", "bt709", "bt709",
952 _16_235, BT709, BT709, BT709),
953 MAKE_COLORIMETRY_TEST ("smpte240m", "smpte240m", "smpte240m",
954 _16_235, SMPTE240M, SMPTE240M, SMPTE240M),
955 MAKE_COLORIMETRY_TEST ("sRGB", "sRGB", "sRGB",
956 _0_255, RGB, SRGB, BT709),
957 MAKE_COLORIMETRY_TEST ("bt2020", "bt2020", "bt2020",
958 _16_235, BT2020, BT2020_12, BT2020),
959 MAKE_COLORIMETRY_TEST ("1:4:0:0", "1:4:0:0", NULL,
960 _0_255, BT601, UNKNOWN, UNKNOWN),
964 for (i = 0; i < G_N_ELEMENTS (tests); i++) {
965 const ColorimetryTest *test = &tests[i];
966 GstVideoColorimetry color;
969 fail_unless (gst_video_colorimetry_from_string (&color, test->string_from));
970 fail_unless_equals_int (color.range, test->color.range);
971 fail_unless_equals_int (color.matrix, test->color.matrix);
972 fail_unless_equals_int (color.transfer, test->color.transfer);
973 fail_unless_equals_int (color.primaries, test->color.primaries);
975 string = gst_video_colorimetry_to_string (&color);
976 fail_unless_equals_string (string, test->string_to);
979 fail_unless (gst_video_colorimetry_is_equal (&color, &test->color));
982 fail_unless (gst_video_colorimetry_matches (&color, test->name));
988 GST_START_TEST (test_events)
993 e = gst_video_event_new_still_frame (TRUE);
994 fail_if (e == NULL, "Failed to create still frame event");
995 fail_unless (gst_video_event_parse_still_frame (e, &in_still),
996 "Failed to parse still frame event");
997 fail_unless (gst_video_event_parse_still_frame (e, NULL),
998 "Failed to parse still frame event w/ in_still == NULL");
999 fail_unless (in_still == TRUE);
1000 gst_event_unref (e);
1002 e = gst_video_event_new_still_frame (FALSE);
1003 fail_if (e == NULL, "Failed to create still frame event");
1004 fail_unless (gst_video_event_parse_still_frame (e, &in_still),
1005 "Failed to parse still frame event");
1006 fail_unless (gst_video_event_parse_still_frame (e, NULL),
1007 "Failed to parse still frame event w/ in_still == NULL");
1008 fail_unless (in_still == FALSE);
1009 gst_event_unref (e);
1014 GST_START_TEST (test_convert_frame)
1017 GstCaps *from_caps, *to_caps;
1018 GstBuffer *from_buffer;
1019 GstSample *from_sample, *to_sample;
1020 GError *error = NULL;
1024 gst_debug_set_threshold_for_name ("default", GST_LEVEL_NONE);
1026 from_buffer = gst_buffer_new_and_alloc (640 * 480 * 4);
1028 gst_buffer_map (from_buffer, &map, GST_MAP_WRITE);
1029 for (i = 0; i < 640 * 480; i++) {
1030 map.data[4 * i + 0] = 0; /* x */
1031 map.data[4 * i + 1] = 255; /* R */
1032 map.data[4 * i + 2] = 0; /* G */
1033 map.data[4 * i + 3] = 0; /* B */
1035 gst_buffer_unmap (from_buffer, &map);
1037 gst_video_info_init (&vinfo);
1038 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_xRGB, 640, 480);
1043 from_caps = gst_video_info_to_caps (&vinfo);
1045 from_sample = gst_sample_new (from_buffer, from_caps, NULL, NULL);
1048 gst_caps_from_string
1049 ("something/that, does=(string)not, exist=(boolean)FALSE");
1052 gst_video_convert_sample (from_sample, to_caps,
1053 GST_CLOCK_TIME_NONE, &error);
1054 fail_if (to_sample != NULL);
1055 fail_unless (error != NULL);
1056 g_error_free (error);
1059 gst_caps_unref (to_caps);
1060 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_I420, 240, 320);
1065 to_caps = gst_video_info_to_caps (&vinfo);
1068 gst_video_convert_sample (from_sample, to_caps,
1069 GST_CLOCK_TIME_NONE, &error);
1070 fail_unless (to_sample != NULL);
1071 fail_unless (error == NULL);
1073 gst_buffer_unref (from_buffer);
1074 gst_caps_unref (from_caps);
1075 gst_sample_unref (from_sample);
1076 gst_sample_unref (to_sample);
1077 gst_caps_unref (to_caps);
1087 } ConvertFrameContext;
1090 convert_sample_async_callback (GstSample * sample, GError * err,
1091 ConvertFrameContext * cf_data)
1093 cf_data->sample = sample;
1094 cf_data->error = err;
1096 g_main_loop_quit (cf_data->loop);
1099 GST_START_TEST (test_convert_frame_async)
1102 GstCaps *from_caps, *to_caps;
1103 GstBuffer *from_buffer;
1104 GstSample *from_sample;
1108 ConvertFrameContext cf_data = { NULL, NULL, NULL };
1110 gst_debug_set_threshold_for_name ("default", GST_LEVEL_NONE);
1112 from_buffer = gst_buffer_new_and_alloc (640 * 480 * 4);
1114 gst_buffer_map (from_buffer, &map, GST_MAP_WRITE);
1115 for (i = 0; i < 640 * 480; i++) {
1116 map.data[4 * i + 0] = 0; /* x */
1117 map.data[4 * i + 1] = 255; /* R */
1118 map.data[4 * i + 2] = 0; /* G */
1119 map.data[4 * i + 3] = 0; /* B */
1121 gst_buffer_unmap (from_buffer, &map);
1123 gst_video_info_init (&vinfo);
1124 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_xRGB, 640, 470);
1129 from_caps = gst_video_info_to_caps (&vinfo);
1132 gst_caps_from_string
1133 ("something/that, does=(string)not, exist=(boolean)FALSE");
1135 loop = cf_data.loop = g_main_loop_new (NULL, FALSE);
1137 from_sample = gst_sample_new (from_buffer, from_caps, NULL, NULL);
1138 gst_buffer_unref (from_buffer);
1139 gst_caps_unref (from_caps);
1141 gst_video_convert_sample_async (from_sample, to_caps,
1142 GST_CLOCK_TIME_NONE,
1143 (GstVideoConvertSampleCallback) convert_sample_async_callback, &cf_data,
1146 g_main_loop_run (loop);
1148 fail_if (cf_data.sample != NULL);
1149 fail_unless (cf_data.error != NULL);
1150 g_error_free (cf_data.error);
1151 cf_data.error = NULL;
1153 gst_caps_unref (to_caps);
1154 gst_video_info_init (&vinfo);
1155 gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_I420, 240, 320);
1160 to_caps = gst_video_info_to_caps (&vinfo);
1161 gst_video_convert_sample_async (from_sample, to_caps,
1162 GST_CLOCK_TIME_NONE,
1163 (GstVideoConvertSampleCallback) convert_sample_async_callback, &cf_data,
1165 g_main_loop_run (loop);
1166 fail_unless (cf_data.sample != NULL);
1167 fail_unless (cf_data.error == NULL);
1169 gst_sample_unref (cf_data.sample);
1170 gst_caps_unref (to_caps);
1171 gst_sample_unref (from_sample);
1173 g_main_loop_unref (loop);
1178 GST_START_TEST (test_video_size_from_caps)
1183 caps = gst_caps_new_simple ("video/x-raw",
1184 "format", G_TYPE_STRING, "YV12",
1185 "width", G_TYPE_INT, 640,
1186 "height", G_TYPE_INT, 480, "framerate", GST_TYPE_FRACTION, 25, 1, NULL);
1188 gst_video_info_init (&vinfo);
1189 fail_unless (gst_video_info_from_caps (&vinfo, caps));
1190 fail_unless (GST_VIDEO_INFO_SIZE (&vinfo) == (640 * 480 * 12 / 8));
1192 gst_caps_unref (caps);
1197 GST_START_TEST (test_interlace_mode)
1201 GstStructure *structure;
1202 GstCapsFeatures *features;
1203 const char *mode_str;
1206 gst_video_info_init (&vinfo);
1209 fail_unless (gst_video_info_set_interlaced_format (&vinfo,
1210 GST_VIDEO_FORMAT_YV12, GST_VIDEO_INTERLACE_MODE_PROGRESSIVE, 320,
1212 fail_unless (GST_VIDEO_INFO_SIZE (&vinfo) == 115200);
1214 caps = gst_video_info_to_caps (&vinfo);
1215 fail_unless (caps != NULL);
1216 structure = gst_caps_get_structure (caps, 0);
1217 fail_unless (structure != NULL);
1218 mode_str = gst_structure_get_string (structure, "interlace-mode");
1219 mode = gst_video_interlace_mode_from_string (mode_str);
1220 fail_unless (mode == GST_VIDEO_INTERLACE_MODE_PROGRESSIVE);
1222 /* Converting back to video info */
1223 fail_unless (gst_video_info_from_caps (&vinfo, caps));
1224 fail_unless (GST_VIDEO_INFO_INTERLACE_MODE (&vinfo) ==
1225 GST_VIDEO_INTERLACE_MODE_PROGRESSIVE);
1227 gst_caps_unref (caps);
1229 /* Interlaced with alternate frame on buffers */
1230 fail_unless (gst_video_info_set_interlaced_format (&vinfo,
1231 GST_VIDEO_FORMAT_YV12, GST_VIDEO_INTERLACE_MODE_ALTERNATE, 320, 240));
1232 fail_unless (GST_VIDEO_INFO_SIZE (&vinfo) == 57600);
1234 caps = gst_video_info_to_caps (&vinfo);
1235 fail_unless (caps != NULL);
1236 structure = gst_caps_get_structure (caps, 0);
1237 fail_unless (structure != NULL);
1238 mode_str = gst_structure_get_string (structure, "interlace-mode");
1239 mode = gst_video_interlace_mode_from_string (mode_str);
1240 fail_unless (mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE);
1241 /* 'alternate' mode must always be accompanied by interlaced caps feature. */
1242 features = gst_caps_get_features (caps, 0);
1243 fail_unless (gst_caps_features_contains (features,
1244 GST_CAPS_FEATURE_FORMAT_INTERLACED));
1246 /* Converting back to video info */
1247 fail_unless (gst_video_info_from_caps (&vinfo, caps));
1248 fail_unless (GST_VIDEO_INFO_INTERLACE_MODE (&vinfo) ==
1249 GST_VIDEO_INTERLACE_MODE_ALTERNATE);
1251 gst_caps_unref (caps);
1256 GST_START_TEST (test_overlay_composition)
1258 GstVideoOverlayComposition *comp1, *comp2;
1259 GstVideoOverlayRectangle *rect1, *rect2;
1260 GstVideoOverlayCompositionMeta *ometa;
1261 GstBuffer *pix1, *pix2, *buf;
1262 GstVideoMeta *vmeta;
1268 pix1 = gst_buffer_new_and_alloc (200 * sizeof (guint32) * 50);
1269 gst_buffer_memset (pix1, 0, 0, gst_buffer_get_size (pix1));
1271 gst_buffer_add_video_meta (pix1, GST_VIDEO_FRAME_FLAG_NONE,
1272 GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB, 200, 50);
1273 rect1 = gst_video_overlay_rectangle_new_raw (pix1,
1274 600, 50, 300, 50, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1276 gst_buffer_unref (pix1);
1279 comp1 = gst_video_overlay_composition_new (rect1);
1280 fail_unless (gst_video_overlay_composition_n_rectangles (comp1) == 1);
1281 fail_unless (gst_video_overlay_composition_get_rectangle (comp1, 0) == rect1);
1282 fail_unless (gst_video_overlay_composition_get_rectangle (comp1, 1) == NULL);
1284 /* rectangle was created first, sequence number should be smaller */
1285 seq1 = gst_video_overlay_rectangle_get_seqnum (rect1);
1286 seq2 = gst_video_overlay_composition_get_seqnum (comp1);
1287 fail_unless (seq1 < seq2);
1289 /* composition took own ref, so refcount is 2 now, so this should fail */
1290 ASSERT_CRITICAL (gst_video_overlay_rectangle_set_render_rectangle (rect1, 50,
1293 /* drop our ref, so refcount is 1 (we know it will continue to be valid) */
1294 gst_video_overlay_rectangle_unref (rect1);
1295 gst_video_overlay_rectangle_set_render_rectangle (rect1, 50, 600, 300, 50);
1297 comp2 = gst_video_overlay_composition_new (rect1);
1298 fail_unless (gst_video_overlay_composition_n_rectangles (comp2) == 1);
1299 fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 0) == rect1);
1300 fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 1) == NULL);
1302 fail_unless (seq1 < gst_video_overlay_composition_get_seqnum (comp2));
1303 fail_unless (seq2 < gst_video_overlay_composition_get_seqnum (comp2));
1305 /* now refcount is 2 again because comp2 has also taken a ref, so must fail */
1306 ASSERT_CRITICAL (gst_video_overlay_rectangle_set_render_rectangle (rect1, 0,
1309 /* this should make a copy of the rectangles so drop the original
1310 * second ref on rect1 */
1311 comp2 = gst_video_overlay_composition_make_writable (comp2);
1312 gst_video_overlay_rectangle_set_render_rectangle (rect1, 51, 601, 301, 51);
1314 rect2 = gst_video_overlay_composition_get_rectangle (comp2, 0);
1315 fail_unless (gst_video_overlay_composition_n_rectangles (comp2) == 1);
1316 fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 0) == rect2);
1317 fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 1) == NULL);
1318 fail_unless (rect1 != rect2);
1320 gst_video_overlay_composition_add_rectangle (comp1, rect2);
1321 gst_video_overlay_composition_ref (comp1);
1322 ASSERT_CRITICAL (gst_video_overlay_composition_add_rectangle (comp1, rect2));
1323 gst_video_overlay_composition_unref (comp1);
1325 /* make sure the copy really worked */
1326 gst_video_overlay_rectangle_get_render_rectangle (rect1, &x, &y, &w, &h);
1327 fail_unless_equals_int (x, 51);
1328 fail_unless_equals_int (y, 601);
1329 fail_unless_equals_int (w, 301);
1330 fail_unless_equals_int (h, 51);
1332 /* get scaled pixbuf and touch last byte */
1333 pix1 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1334 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1336 fail_unless (gst_buffer_get_size (pix1) > ((h - 1) * stride + (w * 4) - 1),
1337 "size %u vs. last pixel offset %u", gst_buffer_get_size (pix1),
1338 ((h - 1) * stride + (w * 4) - 1));
1339 gst_buffer_extract (pix1, ((h - 1) * stride + (w * 4) - 1), &val, 1);
1340 fail_unless_equals_int (val, 0);
1342 gst_video_overlay_rectangle_get_render_rectangle (rect2, &x, &y, &w, &h);
1343 fail_unless_equals_int (x, 50);
1344 fail_unless_equals_int (y, 600);
1345 fail_unless_equals_int (w, 300);
1346 fail_unless_equals_int (h, 50);
1348 /* get scaled pixbuf and touch last byte */
1349 pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect2,
1350 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1352 fail_unless (gst_buffer_get_size (pix2) > ((h - 1) * stride + (w * 4) - 1),
1353 "size %u vs. last pixel offset %u", gst_buffer_get_size (pix1),
1354 ((h - 1) * stride + (w * 4) - 1));
1355 gst_buffer_extract (pix2, ((h - 1) * stride + (w * 4) - 1), &val, 1);
1356 fail_unless_equals_int (val, 0);
1358 /* get scaled pixbuf again, should be the same buffer as before (caching) */
1359 pix1 = gst_video_overlay_rectangle_get_pixels_raw (rect2,
1360 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1361 fail_unless (pix1 == pix2);
1363 /* get in different format */
1364 pix1 = gst_video_overlay_rectangle_get_pixels_ayuv (rect2,
1365 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1366 fail_unless (pix1 != pix2);
1367 /* get it again, should be same (caching) */
1368 pix2 = gst_video_overlay_rectangle_get_pixels_ayuv (rect2,
1369 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1370 fail_unless (pix1 == pix2);
1371 /* get unscaled, should be different */
1372 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_ayuv (rect2,
1373 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1374 fail_unless (pix1 != pix2);
1375 /* but should be cached */
1376 pix1 = gst_video_overlay_rectangle_get_pixels_unscaled_ayuv (rect2,
1377 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1378 fail_unless (pix1 == pix2);
1380 vmeta = gst_buffer_get_video_meta (pix1);
1381 fail_unless (vmeta != NULL);
1384 fail_unless_equals_int (w, 200);
1385 fail_unless_equals_int (h, 50);
1386 fail_unless_equals_int (vmeta->format,
1387 GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_YUV);
1388 fail_unless (gst_buffer_get_size (pix1) == w * h * 4);
1389 gst_buffer_extract (pix1, 0, &seq1, 4);
1390 fail_unless (seq1 != 0);
1392 /* now compare the original unscaled ones */
1393 pix1 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1394 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1395 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect2,
1396 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1398 vmeta = gst_buffer_get_video_meta (pix2);
1399 fail_unless (vmeta != NULL);
1403 /* the original pixel buffers should be identical */
1404 fail_unless (pix1 == pix2);
1405 fail_unless_equals_int (w, 200);
1406 fail_unless_equals_int (h, 50);
1409 /* touch last byte */
1410 fail_unless (gst_buffer_get_size (pix1) > ((h - 1) * stride + (w * 4) - 1),
1411 "size %u vs. last pixel offset %u", gst_buffer_get_size (pix1),
1412 ((h - 1) * stride + (w * 4) - 1));
1413 gst_buffer_extract (pix1, ((h - 1) * stride + (w * 4) - 1), &val, 1);
1414 fail_unless_equals_int (val, 0);
1416 /* test attaching and retrieving of compositions to/from buffers */
1417 buf = gst_buffer_new ();
1418 fail_unless (gst_buffer_get_video_overlay_composition_meta (buf) == NULL);
1420 gst_buffer_ref (buf);
1421 /* buffer now has refcount of 2, so its metadata is not writable.
1422 * only check this if we are not running in valgrind, as it leaks */
1423 #ifdef HAVE_VALGRIND
1424 if (!RUNNING_ON_VALGRIND) {
1425 ASSERT_CRITICAL (gst_buffer_add_video_overlay_composition_meta (buf,
1429 gst_buffer_unref (buf);
1430 gst_buffer_add_video_overlay_composition_meta (buf, comp1);
1431 ometa = gst_buffer_get_video_overlay_composition_meta (buf);
1432 fail_unless (ometa != NULL);
1433 fail_unless (ometa->overlay == comp1);
1434 fail_unless (gst_buffer_remove_video_overlay_composition_meta (buf, ometa));
1435 gst_buffer_add_video_overlay_composition_meta (buf, comp2);
1436 ometa = gst_buffer_get_video_overlay_composition_meta (buf);
1437 fail_unless (ometa->overlay == comp2);
1438 fail_unless (gst_buffer_remove_video_overlay_composition_meta (buf, ometa));
1439 fail_unless (gst_buffer_get_video_overlay_composition_meta (buf) == NULL);
1441 /* make sure the buffer cleans up its composition ref when unreffed */
1442 gst_buffer_add_video_overlay_composition_meta (buf, comp2);
1443 gst_buffer_unref (buf);
1445 gst_video_overlay_composition_unref (comp2);
1446 gst_video_overlay_composition_unref (comp1);
1451 GST_START_TEST (test_overlay_composition_premultiplied_alpha)
1453 GstVideoOverlayRectangle *rect1;
1454 GstVideoMeta *vmeta;
1455 GstBuffer *pix1, *pix2, *pix3, *pix4, *pix5;
1456 GstBuffer *pix6, *pix7, *pix8, *pix9, *pix10;
1457 guint8 *data5, *data7;
1461 pix1 = gst_buffer_new_and_alloc (200 * sizeof (guint32) * 50);
1462 gst_buffer_memset (pix1, 0, 0x80, gst_buffer_get_size (pix1));
1464 gst_buffer_add_video_meta (pix1, GST_VIDEO_FRAME_FLAG_NONE,
1465 GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB, 200, 50);
1466 rect1 = gst_video_overlay_rectangle_new_raw (pix1,
1467 600, 50, 300, 50, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1468 gst_buffer_unref (pix1);
1470 /* same flags, unscaled, should be the same buffer */
1471 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1472 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1473 fail_unless (pix1 == pix2);
1475 /* same flags, but scaled */
1476 pix3 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1477 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1478 fail_if (pix3 == pix1 || pix3 == pix2);
1480 /* same again, should hopefully get the same (cached) buffer as before */
1481 pix4 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1482 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1483 fail_unless (pix4 == pix3);
1485 /* just to update the vars */
1486 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1487 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1489 vmeta = gst_buffer_get_video_meta (pix2);
1490 fail_unless (vmeta != NULL);
1494 /* now, let's try to get premultiplied alpha from the unpremultiplied input */
1495 pix5 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1496 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1497 fail_if (pix5 == pix1 || pix5 == pix2 || pix5 == pix3);
1498 vmeta = gst_buffer_get_video_meta (pix5);
1499 fail_unless (vmeta != NULL);
1502 fail_unless_equals_int (w, w2);
1503 fail_unless_equals_int (h, h2);
1504 fail_unless_equals_int (gst_buffer_get_size (pix2),
1505 gst_buffer_get_size (pix5));
1506 gst_buffer_map (pix5, &map, GST_MAP_READ);
1507 fail_if (gst_buffer_memcmp (pix2, 0, map.data, map.size) == 0);
1508 /* make sure it actually did what we expected it to do (input=0x80808080) */
1510 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1512 fail_unless_equals_int (data5[0], 0x40);
1513 fail_unless_equals_int (data5[1], 0x40);
1514 fail_unless_equals_int (data5[2], 0x40);
1515 fail_unless_equals_int (data5[3], 0x80);
1518 fail_unless_equals_int (data5[0], 0x80);
1519 fail_unless_equals_int (data5[1], 0x40);
1520 fail_unless_equals_int (data5[2], 0x40);
1521 fail_unless_equals_int (data5[3], 0x40);
1523 gst_buffer_unmap (pix5, &map);
1525 /* same again, now we should be getting back the same buffer as before,
1526 * as it should have been cached */
1527 pix6 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1528 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1529 fail_unless (pix6 == pix5);
1531 /* just to update the stride var */
1532 pix3 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1533 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1534 fail_unless (pix3 == pix4);
1536 /* now try to get scaled premultiplied alpha from unpremultiplied input */
1537 pix7 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1538 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1539 fail_if (pix7 == pix1 || pix7 == pix2 || pix7 == pix3 || pix7 == pix5);
1541 gst_buffer_map (pix7, &map, GST_MAP_READ);
1543 /* make sure it actually did what we expected it to do (input=0x80808080)
1544 * hoping that the scaling didn't mess up our values */
1545 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1547 fail_unless_equals_int (data7[0], 0x40);
1548 fail_unless_equals_int (data7[1], 0x40);
1549 fail_unless_equals_int (data7[2], 0x40);
1550 fail_unless_equals_int (data7[3], 0x80);
1553 fail_unless_equals_int (data7[0], 0x80);
1554 fail_unless_equals_int (data7[1], 0x40);
1555 fail_unless_equals_int (data7[2], 0x40);
1556 fail_unless_equals_int (data7[3], 0x40);
1558 gst_buffer_unmap (pix7, &map);
1560 /* and the same again, it should be cached now */
1561 pix8 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1562 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1563 fail_unless (pix8 == pix7);
1565 /* make sure other cached stuff is still there */
1566 pix9 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1567 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1568 fail_unless (pix9 == pix3);
1569 pix10 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1570 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1571 fail_unless (pix10 == pix5);
1573 gst_video_overlay_rectangle_unref (rect1);
1578 GST_START_TEST (test_overlay_composition_global_alpha)
1580 GstVideoOverlayRectangle *rect1;
1581 GstBuffer *pix1, *pix2, *pix3, *pix4, *pix5;
1582 GstVideoMeta *vmeta;
1583 guint8 *data2, *data4, *data5;
1587 GstVideoOverlayFormatFlags flags1;
1590 pix1 = gst_buffer_new_and_alloc (200 * sizeof (guint32) * 50);
1591 gst_buffer_memset (pix1, 0, 0x80, gst_buffer_get_size (pix1));
1593 gst_buffer_add_video_meta (pix1, GST_VIDEO_FRAME_FLAG_NONE,
1594 GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB, 200, 50);
1595 rect1 = gst_video_overlay_rectangle_new_raw (pix1,
1596 600, 50, 300, 50, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1597 gst_buffer_unref (pix1);
1599 /* same flags, unscaled, should be the same buffer */
1600 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1601 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1602 fail_unless (pix1 == pix2);
1604 vmeta = gst_buffer_get_video_meta (pix2);
1605 fail_unless (vmeta != NULL);
1609 /* same flags, but scaled */
1610 pix3 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1611 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1612 fail_if (pix3 == pix1 || pix3 == pix2);
1614 /* get unscaled premultiplied data, new cached rectangle should be created */
1615 pix4 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1616 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1617 fail_if (pix4 == pix2 || pix4 == pix3);
1618 vmeta = gst_buffer_get_video_meta (pix4);
1619 fail_unless (vmeta != NULL);
1622 fail_unless_equals_int (w, w4);
1623 fail_unless_equals_int (h, h4);
1624 fail_unless_equals_int (gst_buffer_get_size (pix2),
1625 gst_buffer_get_size (pix4));
1626 gst_buffer_map (pix4, &map, GST_MAP_READ);
1627 fail_if (gst_buffer_memcmp (pix1, 0, map.data, map.size) == 0);
1628 /* make sure it actually did what we expected it to do (input=0x80808080) */
1630 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1632 fail_unless_equals_int (data4[0], 0x40);
1633 fail_unless_equals_int (data4[1], 0x40);
1634 fail_unless_equals_int (data4[2], 0x40);
1635 fail_unless_equals_int (data4[3], 0x80);
1638 fail_unless_equals_int (data4[0], 0x80);
1639 fail_unless_equals_int (data4[1], 0x40);
1640 fail_unless_equals_int (data4[2], 0x40);
1641 fail_unless_equals_int (data4[3], 0x40);
1643 gst_buffer_unmap (pix4, &map);
1645 /* now premultiplied and scaled, again a new cached rectangle should be cached */
1646 pix5 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1647 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1648 fail_if (pix5 == pix2 || pix5 == pix3 || pix5 == pix4);
1649 /* stride and size should be equal to the first scaled rect */
1650 fail_unless_equals_int (gst_buffer_get_size (pix5),
1651 gst_buffer_get_size (pix3));
1652 /* data should be different (premutliplied) though */
1653 gst_buffer_map (pix5, &map, GST_MAP_READ);
1654 fail_if (gst_buffer_memcmp (pix3, 0, map.data, map.size) == 0);
1655 /* make sure it actually did what we expected it to do (input=0x80808080) */
1657 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1659 fail_unless_equals_int (data5[0], 0x40);
1660 fail_unless_equals_int (data5[1], 0x40);
1661 fail_unless_equals_int (data5[2], 0x40);
1662 fail_unless_equals_int (data5[3], 0x80);
1665 fail_unless_equals_int (data5[0], 0x80);
1666 fail_unless_equals_int (data5[1], 0x40);
1667 fail_unless_equals_int (data5[2], 0x40);
1668 fail_unless_equals_int (data5[3], 0x40);
1670 gst_buffer_unmap (pix5, &map);
1672 /* global_alpha should initially be 1.0 */
1673 ga1 = gst_video_overlay_rectangle_get_global_alpha (rect1);
1674 fail_unless_equals_float (ga1, 1.0);
1676 /* now set global_alpha */
1677 seq1 = gst_video_overlay_rectangle_get_seqnum (rect1);
1678 gst_video_overlay_rectangle_set_global_alpha (rect1, 0.5);
1679 ga2 = gst_video_overlay_rectangle_get_global_alpha (rect1);
1680 fail_unless_equals_float (ga2, 0.5);
1682 /* seqnum should have changed */
1683 seq2 = gst_video_overlay_rectangle_get_seqnum (rect1);
1684 fail_unless (seq1 < seq2);
1686 /* internal flags should have been set */
1687 flags1 = gst_video_overlay_rectangle_get_flags (rect1);
1688 fail_unless_equals_int (flags1, GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1690 /* request unscaled pixel-data, global-alpha not applied */
1691 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1692 GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1693 /* this should just return the same buffer */
1694 fail_unless (pix2 == pix1);
1695 /* make sure we got the initial data (input=0x80808080) */
1696 gst_buffer_map (pix2, &map, GST_MAP_READ);
1698 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1700 fail_unless_equals_int (data2[0], 0x80);
1701 fail_unless_equals_int (data2[1], 0x80);
1702 fail_unless_equals_int (data2[2], 0x80);
1703 fail_unless_equals_int (data2[3], 0x80);
1706 fail_unless_equals_int (data2[0], 0x80);
1707 fail_unless_equals_int (data2[1], 0x80);
1708 fail_unless_equals_int (data2[2], 0x80);
1709 fail_unless_equals_int (data2[3], 0x80);
1711 gst_buffer_unmap (pix2, &map);
1713 /* unscaled pixel-data, global-alpha applied */
1714 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1715 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1716 /* this should be the same buffer with on-the-fly modified alpha-channel */
1717 fail_unless (pix2 == pix1);
1718 gst_buffer_map (pix2, &map, GST_MAP_READ);
1720 /* make sure we got the initial data with adjusted alpha-channel */
1721 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1723 fail_unless_equals_int (data2[0], 0x80);
1724 fail_unless_equals_int (data2[1], 0x80);
1725 fail_unless_equals_int (data2[2], 0x80);
1726 fail_unless_equals_int (data2[3], 0x40);
1729 fail_unless_equals_int (data2[0], 0x40);
1730 fail_unless_equals_int (data2[1], 0x80);
1731 fail_unless_equals_int (data2[2], 0x80);
1732 fail_unless_equals_int (data2[3], 0x80);
1734 gst_buffer_unmap (pix2, &map);
1736 /* adjust global_alpha once more */
1737 gst_video_overlay_rectangle_set_global_alpha (rect1, 0.25);
1738 ga2 = gst_video_overlay_rectangle_get_global_alpha (rect1);
1739 fail_unless_equals_float (ga2, 0.25);
1740 /* and again request unscaled pixel-data, global-alpha applied */
1741 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1742 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1743 fail_unless (pix2 == pix1);
1744 /* make sure we got the initial data with adjusted alpha-channel */
1745 gst_buffer_map (pix2, &map, GST_MAP_READ);
1747 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1749 fail_unless_equals_int (data2[0], 0x80);
1750 fail_unless_equals_int (data2[1], 0x80);
1751 fail_unless_equals_int (data2[2], 0x80);
1752 fail_unless_equals_int (data2[3], 0x20);
1755 fail_unless_equals_int (data2[0], 0x20);
1756 fail_unless_equals_int (data2[1], 0x80);
1757 fail_unless_equals_int (data2[2], 0x80);
1758 fail_unless_equals_int (data2[3], 0x80);
1760 gst_buffer_unmap (pix2, &map);
1762 /* again: unscaled pixel-data, global-alpha not applied,
1763 * this should revert alpha-channel to initial values */
1764 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1765 GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1766 fail_unless (pix2 == pix1);
1767 /* make sure we got the initial data (input=0x80808080) */
1768 gst_buffer_map (pix2, &map, GST_MAP_READ);
1770 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1772 fail_unless_equals_int (data2[0], 0x80);
1773 fail_unless_equals_int (data2[1], 0x80);
1774 fail_unless_equals_int (data2[2], 0x80);
1775 fail_unless_equals_int (data2[3], 0x80);
1778 fail_unless_equals_int (data2[0], 0x80);
1779 fail_unless_equals_int (data2[1], 0x80);
1780 fail_unless_equals_int (data2[2], 0x80);
1781 fail_unless_equals_int (data2[3], 0x80);
1783 gst_buffer_unmap (pix2, &map);
1785 /* now scaled, global-alpha not applied */
1786 pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1787 GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1788 /* this should just return the rect/buffer, that was cached for these
1789 * scaling dimensions */
1790 fail_unless (pix2 == pix3);
1791 /* make sure we got the initial data (input=0x80808080) */
1792 gst_buffer_map (pix2, &map, GST_MAP_READ);
1794 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1796 fail_unless_equals_int (data2[0], 0x80);
1797 fail_unless_equals_int (data2[1], 0x80);
1798 fail_unless_equals_int (data2[2], 0x80);
1799 fail_unless_equals_int (data2[3], 0x80);
1802 fail_unless_equals_int (data2[0], 0x80);
1803 fail_unless_equals_int (data2[1], 0x80);
1804 fail_unless_equals_int (data2[2], 0x80);
1805 fail_unless_equals_int (data2[3], 0x80);
1807 gst_buffer_unmap (pix2, &map);
1809 /* scaled, global-alpha (0.25) applied */
1810 pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1811 GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
1812 /* this should just return the rect/buffer, that was cached for these
1813 * scaling dimensions with modified alpha channel */
1814 fail_unless (pix2 == pix3);
1815 /* make sure we got the data we expect for global-alpha=0.25 */
1816 gst_buffer_map (pix2, &map, GST_MAP_READ);
1818 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1820 fail_unless_equals_int (data2[0], 0x80);
1821 fail_unless_equals_int (data2[1], 0x80);
1822 fail_unless_equals_int (data2[2], 0x80);
1823 fail_unless_equals_int (data2[3], 0x20);
1826 fail_unless_equals_int (data2[0], 0x20);
1827 fail_unless_equals_int (data2[1], 0x80);
1828 fail_unless_equals_int (data2[2], 0x80);
1829 fail_unless_equals_int (data2[3], 0x80);
1831 gst_buffer_unmap (pix2, &map);
1833 /* now unscaled premultiplied data, global-alpha not applied,
1834 * is this really a valid use case?*/
1835 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1836 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA |
1837 GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1838 /* this should just return the rect/buffer, that was cached for the
1839 * premultiplied data */
1840 fail_unless (pix2 == pix4);
1841 /* make sure we got what we expected */
1842 gst_buffer_map (pix2, &map, GST_MAP_READ);
1844 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1846 fail_unless_equals_int (data2[0], 0x40);
1847 fail_unless_equals_int (data2[1], 0x40);
1848 fail_unless_equals_int (data2[2], 0x40);
1849 fail_unless_equals_int (data2[3], 0x80);
1852 fail_unless_equals_int (data2[0], 0x80);
1853 fail_unless_equals_int (data2[1], 0x40);
1854 fail_unless_equals_int (data2[2], 0x40);
1855 fail_unless_equals_int (data2[3], 0x40);
1857 gst_buffer_unmap (pix2, &map);
1859 /* unscaled premultiplied data, global-alpha (0.25) applied */
1860 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1861 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1862 /* this should just return the rect/buffer, that was cached for the
1863 * premultiplied data */
1864 fail_unless (pix2 == pix4);
1865 /* make sure we got what we expected:
1866 * (0x40 / (0x80/0xFF) * (0x20/0xFF) = 0x10
1867 * NOTE: unless we are using round() for the premultiplied case
1868 * in gst_video_overlay_rectangle_apply_global_alpha() we get rounding
1869 * error, i.e. 0x0F here */
1870 gst_buffer_map (pix2, &map, GST_MAP_READ);
1872 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1874 fail_unless_equals_int (data2[0], 0x0F);
1875 fail_unless_equals_int (data2[1], 0x0F);
1876 fail_unless_equals_int (data2[2], 0x0F);
1877 fail_unless_equals_int (data2[3], 0x20);
1880 fail_unless_equals_int (data2[0], 0x20);
1881 fail_unless_equals_int (data2[1], 0x0F);
1882 fail_unless_equals_int (data2[2], 0x0F);
1883 fail_unless_equals_int (data2[3], 0x0F);
1885 gst_buffer_unmap (pix2, &map);
1887 /* set global_alpha once more */
1888 gst_video_overlay_rectangle_set_global_alpha (rect1, 0.75);
1889 /* and verify that also premultiplied data is adjusted
1890 * correspondingly (though with increasing rounding errors) */
1891 pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect1,
1892 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1893 /* this should just return the rect/buffer, that was cached for the
1894 * premultiplied data */
1895 fail_unless (pix2 == pix4);
1896 /* make sure we got what we expected:
1897 * (0x0F / (0x20/0xFF) * (0x60/0xFF) = 0x2D
1898 * NOTE: using floats everywhere we would get 0x30
1899 * here we will actually end up with 0x2C */
1900 gst_buffer_map (pix2, &map, GST_MAP_READ);
1902 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1904 fail_unless_equals_int (data2[0], 0x2C);
1905 fail_unless_equals_int (data2[1], 0x2C);
1906 fail_unless_equals_int (data2[2], 0x2C);
1907 fail_unless_equals_int (data2[3], 0x60);
1910 fail_unless_equals_int (data2[0], 0x60);
1911 fail_unless_equals_int (data2[1], 0x2C);
1912 fail_unless_equals_int (data2[2], 0x2C);
1913 fail_unless_equals_int (data2[3], 0x2C);
1915 gst_buffer_unmap (pix2, &map);
1917 /* now scaled and premultiplied data, global-alpha not applied,
1918 * is this really a valid use case?*/
1919 pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1920 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA |
1921 GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA);
1922 /* this should just return the rect/buffer, that was cached for the
1923 * first premultiplied+scaled rect*/
1924 fail_unless (pix2 == pix5);
1925 /* make sure we got what we expected */
1926 gst_buffer_map (pix2, &map, GST_MAP_READ);
1928 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1930 fail_unless_equals_int (data2[0], 0x40);
1931 fail_unless_equals_int (data2[1], 0x40);
1932 fail_unless_equals_int (data2[2], 0x40);
1933 fail_unless_equals_int (data2[3], 0x80);
1936 fail_unless_equals_int (data2[0], 0x80);
1937 fail_unless_equals_int (data2[1], 0x40);
1938 fail_unless_equals_int (data2[2], 0x40);
1939 fail_unless_equals_int (data2[3], 0x40);
1941 gst_buffer_unmap (pix2, &map);
1943 /* scaled and premultiplied data, global-alpha applied */
1944 pix2 = gst_video_overlay_rectangle_get_pixels_raw (rect1,
1945 GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
1946 /* this should just return the rect/buffer, that was cached for the
1947 * first premultiplied+scaled rect*/
1948 fail_unless (pix2 == pix5);
1949 /* make sure we got what we expected; see above note about rounding errors! */
1950 gst_buffer_map (pix2, &map, GST_MAP_READ);
1952 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1954 fail_unless_equals_int (data2[0], 0x2F);
1955 fail_unless_equals_int (data2[1], 0x2F);
1956 fail_unless_equals_int (data2[2], 0x2F);
1957 fail_unless_equals_int (data2[3], 0x60);
1960 fail_unless_equals_int (data2[0], 0x60);
1961 fail_unless_equals_int (data2[1], 0x2F);
1962 fail_unless_equals_int (data2[2], 0x2F);
1963 fail_unless_equals_int (data2[3], 0x2F);
1965 gst_buffer_unmap (pix2, &map);
1967 gst_video_overlay_rectangle_unref (rect1);
1973 make_pixels (gint depth, gint width, gint height)
1975 guint32 color = 0xff000000;
1979 guint8 *pixels = g_malloc (width * height * 4);
1980 for (i = 0; i < height; i++) {
1981 for (j = 0; j < width; j++) {
1982 pixels[(i * width + j) * 4 + 0] = ((color >> 24) & 0xff);
1983 pixels[(i * width + j) * 4 + 1] = ((color >> 16) & 0xff);
1984 pixels[(i * width + j) * 4 + 2] = ((color >> 8) & 0xff);
1985 pixels[(i * width + j) * 4 + 3] = (color & 0xff);
1991 #define TO16(a) (((a)<<8)|(a))
1992 guint16 *pixels = g_malloc (width * height * 8);
1993 for (i = 0; i < height; i++) {
1994 for (j = 0; j < width; j++) {
1995 pixels[(i * width + j) * 4 + 0] = TO16 ((color >> 24) & 0xff);
1996 pixels[(i * width + j) * 4 + 1] = TO16 ((color >> 16) & 0xff);
1997 pixels[(i * width + j) * 4 + 2] = TO16 ((color >> 8) & 0xff);
1998 pixels[(i * width + j) * 4 + 3] = TO16 (color & 0xff);
2003 return (guint8 *) pixels;
2007 #define HS(x,o) ((x)&hs[o])
2008 #define WS(x,o) ((x)&ws[o])
2009 #define IN(i,j,o) (in[(HS(i, o)*width + WS(j,o))*4+(o)] & mask[o])
2010 #define OUT(i,j,o) (out[((i)*width + (j))*4+o] & mask[o])
2012 compare_frame (const GstVideoFormatInfo * finfo, gint depth, guint8 * outpixels,
2013 guint8 * pixels, gint width, gint height)
2016 guint ws[4], hs[4], mask[4];
2018 for (k = 0; k < 4; k++) {
2019 hs[k] = G_MAXUINT << finfo->h_sub[(3 + k) % 4];
2020 ws[k] = G_MAXUINT << finfo->w_sub[(3 + k) % 4];
2021 mask[k] = G_MAXUINT << (depth - finfo->depth[(3 + k) % 4]);
2025 guint8 *in = pixels;
2026 guint8 *out = outpixels;
2028 for (i = 0; i < height; i++) {
2029 for (j = 0; j < width; j++) {
2030 for (k = 0; k < 4; k++) {
2031 diff += IN (i, j, k) != OUT (i, j, k);
2036 guint16 *in = (guint16 *) pixels;
2037 guint16 *out = (guint16 *) outpixels;
2039 for (i = 0; i < height; i++) {
2040 for (j = 0; j < width; j++) {
2041 for (k = 0; k < 4; k++) {
2042 diff += IN (i, j, k) != OUT (i, j, k);
2057 GstVideoFormat infmt;
2058 GstVideoFormat outfmt;
2060 gdouble convert_sec;
2063 #define SIGN(a,b) ((a) < (b) ? -1 : (a) > (b) ? 1 : 0)
2066 compare_result (gconstpointer a, gconstpointer b)
2068 const ConvertResult *ap = a;
2069 const ConvertResult *bp = b;
2071 return SIGN (ap->convert_sec, bp->convert_sec);
2074 #define UNPACK_FRAME(frame,dest,line,x,width) \
2075 (frame)->info.finfo->unpack_func ((frame)->info.finfo, \
2076 (GST_VIDEO_FRAME_IS_INTERLACED (frame) ? \
2077 GST_VIDEO_PACK_FLAG_INTERLACED : \
2078 GST_VIDEO_PACK_FLAG_NONE), \
2079 dest, (frame)->data, (frame)->info.stride, x, \
2081 #define PACK_FRAME(frame,src,line,width) \
2082 (frame)->info.finfo->pack_func ((frame)->info.finfo, \
2083 (GST_VIDEO_FRAME_IS_INTERLACED (frame) ? \
2084 GST_VIDEO_PACK_FLAG_INTERLACED : \
2085 GST_VIDEO_PACK_FLAG_NONE), \
2086 src, 0, (frame)->data, (frame)->info.stride, \
2087 (frame)->info.chroma_site, line, width);
2089 GST_START_TEST (test_video_pack_unpack2)
2091 GstVideoFormat format;
2093 gint num_formats, i;
2094 GArray *packarray, *unpackarray;
2098 /* set to something larger to do benchmarks */
2101 timer = g_timer_new ();
2102 packarray = g_array_new (FALSE, FALSE, sizeof (ConvertResult));
2103 unpackarray = g_array_new (FALSE, FALSE, sizeof (ConvertResult));
2105 num_formats = get_num_formats ();
2107 GST_DEBUG ("pack/sec\t unpack/sec \tpack GB/sec\tunpack GB/sec\tformat");
2109 for (format = GST_VIDEO_FORMAT_I420; format < num_formats; format++) {
2111 const GstVideoFormatInfo *finfo, *fuinfo;
2113 GstVideoFrame frame;
2114 gint k, stride, count, diff, depth;
2115 guint8 *pixels, *outpixels;
2117 gdouble unpack_sec, pack_sec;
2120 finfo = gst_video_format_get_info (format);
2121 fail_unless (finfo != NULL);
2123 if (GST_VIDEO_FORMAT_INFO_HAS_PALETTE (finfo))
2126 fuinfo = gst_video_format_get_info (finfo->unpack_format);
2127 fail_unless (fuinfo != NULL);
2129 depth = GST_VIDEO_FORMAT_INFO_BITS (fuinfo);
2130 fail_unless (depth == 8 || depth == 16);
2132 pixels = make_pixels (depth, WIDTH, HEIGHT);
2133 stride = WIDTH * (depth >> 1);
2135 gst_video_info_set_format (&info, format, WIDTH, HEIGHT);
2136 buffer = gst_buffer_new_and_alloc (info.size);
2137 gst_video_frame_map (&frame, &info, buffer, GST_MAP_READWRITE);
2139 /* pack the frame into the target format */
2141 PACK_FRAME (&frame, pixels, 0, WIDTH);
2144 g_timer_start (timer);
2146 for (k = 0; k < HEIGHT; k += finfo->pack_lines) {
2147 PACK_FRAME (&frame, pixels + k * stride, k, WIDTH);
2150 elapsed = g_timer_elapsed (timer, NULL);
2151 if (elapsed >= TIME)
2154 unpack_sec = count / elapsed;
2157 res.outfmt = finfo->unpack_format;
2158 res.convert_sec = unpack_sec;
2159 g_array_append_val (unpackarray, res);
2161 outpixels = g_malloc0 (HEIGHT * stride);
2163 /* unpack the frame */
2165 UNPACK_FRAME (&frame, outpixels, 0, 0, WIDTH);
2168 g_timer_start (timer);
2170 for (k = 0; k < HEIGHT; k += finfo->pack_lines) {
2171 UNPACK_FRAME (&frame, outpixels + k * stride, k, 0, WIDTH);
2174 elapsed = g_timer_elapsed (timer, NULL);
2175 if (elapsed >= TIME)
2178 pack_sec = count / elapsed;
2180 res.outfmt = format;
2181 res.infmt = finfo->unpack_format;
2182 res.convert_sec = pack_sec;
2183 g_array_append_val (packarray, res);
2185 /* compare the frame */
2186 diff = compare_frame (finfo, depth, outpixels, pixels, WIDTH, HEIGHT);
2188 GST_DEBUG ("%f \t %f \t %f \t %f \t %s %d/%f", pack_sec, unpack_sec,
2189 info.size * pack_sec, info.size * unpack_sec, finfo->name, count,
2193 gst_util_dump_mem (outpixels, 128);
2194 gst_util_dump_mem (pixels, 128);
2195 fail_if (diff != 0);
2197 gst_video_frame_unmap (&frame);
2198 gst_buffer_unref (buffer);
2203 g_array_sort (packarray, compare_result);
2204 for (i = 0; i < packarray->len; i++) {
2205 ConvertResult *res = &g_array_index (packarray, ConvertResult, i);
2207 GST_DEBUG ("%f pack/sec %s->%s", res->convert_sec,
2208 gst_video_format_to_string (res->infmt),
2209 gst_video_format_to_string (res->outfmt));
2212 g_array_sort (unpackarray, compare_result);
2213 for (i = 0; i < unpackarray->len; i++) {
2214 ConvertResult *res = &g_array_index (unpackarray, ConvertResult, i);
2216 GST_DEBUG ("%f unpack/sec %s->%s", res->convert_sec,
2217 gst_video_format_to_string (res->infmt),
2218 gst_video_format_to_string (res->outfmt));
2221 g_timer_destroy (timer);
2222 g_array_free (packarray, TRUE);
2223 g_array_free (unpackarray, TRUE);
2234 #define GET_LINE(l) (pixels + CLAMP (l, 0, HEIGHT-1) * WIDTH * 4)
2235 GST_START_TEST (test_video_chroma)
2239 gint i, j, k, offset, count;
2242 gdouble elapsed, subsample_sec;
2243 GstVideoChromaSite sites[] = {
2244 GST_VIDEO_CHROMA_SITE_NONE,
2245 GST_VIDEO_CHROMA_SITE_H_COSITED,
2248 timer = g_timer_new ();
2249 pixels = make_pixels (8, WIDTH, HEIGHT);
2251 for (k = 0; k < G_N_ELEMENTS (sites); k++) {
2252 GstVideoChromaResample *resample;
2254 resample = gst_video_chroma_resample_new (GST_VIDEO_CHROMA_METHOD_LINEAR,
2255 sites[k], GST_VIDEO_CHROMA_FLAG_NONE, GST_VIDEO_FORMAT_AYUV, -1, -1);
2257 gst_video_chroma_resample_get_info (resample, &n_lines, &offset);
2258 fail_unless (n_lines < 10);
2261 for (j = 0; j < n_lines; j++)
2262 lines[j] = GET_LINE (offset + j);
2263 gst_video_chroma_resample (resample, lines, WIDTH);
2266 g_timer_start (timer);
2268 for (i = 0; i < HEIGHT; i += n_lines) {
2269 for (j = 0; j < n_lines; j++)
2270 lines[j] = GET_LINE (i + offset + j);
2272 gst_video_chroma_resample (resample, lines, WIDTH);
2275 elapsed = g_timer_elapsed (timer, NULL);
2276 if (elapsed >= TIME)
2279 subsample_sec = count / elapsed;
2280 GST_DEBUG ("%f downsamples/sec %d/%f", subsample_sec, count, elapsed);
2281 gst_video_chroma_resample_free (resample);
2283 resample = gst_video_chroma_resample_new (GST_VIDEO_CHROMA_METHOD_LINEAR,
2284 sites[k], GST_VIDEO_CHROMA_FLAG_NONE, GST_VIDEO_FORMAT_AYUV, 1, 1);
2286 gst_video_chroma_resample_get_info (resample, &n_lines, &offset);
2287 fail_unless (n_lines < 10);
2290 for (j = 0; j < n_lines; j++)
2291 lines[j] = GET_LINE (offset + j);
2292 gst_video_chroma_resample (resample, lines, WIDTH);
2295 g_timer_start (timer);
2297 for (i = 0; i < HEIGHT; i += n_lines) {
2298 for (j = 0; j < n_lines; j++)
2299 lines[j] = GET_LINE (i + offset + j);
2301 gst_video_chroma_resample (resample, lines, WIDTH);
2304 elapsed = g_timer_elapsed (timer, NULL);
2305 if (elapsed >= TIME)
2308 subsample_sec = count / elapsed;
2309 GST_DEBUG ("%f upsamples/sec %d/%f", subsample_sec, count, elapsed);
2310 gst_video_chroma_resample_free (resample);
2314 g_timer_destroy (timer);
2322 GST_START_TEST (test_video_scaler)
2324 GstVideoScaler *scale;
2326 scale = gst_video_scaler_new (GST_VIDEO_RESAMPLER_METHOD_LINEAR,
2327 GST_VIDEO_SCALER_FLAG_NONE, 2, 10, 5, NULL);
2328 gst_video_scaler_free (scale);
2330 scale = gst_video_scaler_new (GST_VIDEO_RESAMPLER_METHOD_LINEAR,
2331 GST_VIDEO_SCALER_FLAG_NONE, 2, 15, 5, NULL);
2332 gst_video_scaler_free (scale);
2341 GST_START_TEST (test_video_color_convert)
2343 GstVideoFormat infmt, outfmt;
2345 gint num_formats, i;
2348 array = g_array_new (FALSE, FALSE, sizeof (ConvertResult));
2350 timer = g_timer_new ();
2352 num_formats = get_num_formats ();
2354 for (infmt = GST_VIDEO_FORMAT_I420; infmt < num_formats; infmt++) {
2355 GstVideoInfo ininfo;
2356 GstVideoFrame inframe;
2357 GstBuffer *inbuffer;
2359 gst_video_info_set_format (&ininfo, infmt, WIDTH, HEIGHT);
2360 inbuffer = gst_buffer_new_and_alloc (ininfo.size);
2361 gst_buffer_memset (inbuffer, 0, 0, -1);
2362 gst_video_frame_map (&inframe, &ininfo, inbuffer, GST_MAP_READ);
2364 for (outfmt = GST_VIDEO_FORMAT_I420; outfmt < num_formats; outfmt++) {
2365 GstVideoInfo outinfo;
2366 GstVideoFrame outframe;
2367 GstBuffer *outbuffer;
2368 GstVideoConverter *convert;
2373 gst_video_info_set_format (&outinfo, outfmt, WIDTH, HEIGHT);
2374 outbuffer = gst_buffer_new_and_alloc (outinfo.size);
2375 gst_video_frame_map (&outframe, &outinfo, outbuffer, GST_MAP_WRITE);
2377 convert = gst_video_converter_new (&ininfo, &outinfo, NULL);
2379 gst_video_converter_frame (convert, &inframe, &outframe);
2382 g_timer_start (timer);
2384 gst_video_converter_frame (convert, &inframe, &outframe);
2387 elapsed = g_timer_elapsed (timer, NULL);
2388 if (elapsed >= TIME)
2393 res.outfmt = outfmt;
2394 res.convert_sec = count / elapsed;
2396 GST_DEBUG ("%f conversions/sec %s->%s, %d/%f", res.convert_sec,
2397 gst_video_format_to_string (infmt),
2398 gst_video_format_to_string (outfmt), count, elapsed);
2400 g_array_append_val (array, res);
2402 gst_video_converter_free (convert);
2404 gst_video_frame_unmap (&outframe);
2405 gst_buffer_unref (outbuffer);
2407 gst_video_frame_unmap (&inframe);
2408 gst_buffer_unref (inbuffer);
2411 g_array_sort (array, compare_result);
2413 for (i = 0; i < array->len; i++) {
2414 ConvertResult *res = &g_array_index (array, ConvertResult, i);
2416 GST_DEBUG ("%f conversions/sec %s->%s", res->convert_sec,
2417 gst_video_format_to_string (res->infmt),
2418 gst_video_format_to_string (res->outfmt));
2421 g_array_free (array, TRUE);
2423 g_timer_destroy (timer);
2430 #define WIDTH_IN 320
2431 #define HEIGHT_IN 240
2432 #define WIDTH_OUT 400
2433 #define HEIGHT_OUT 300
2436 GST_START_TEST (test_video_size_convert)
2438 GstVideoFormat infmt, outfmt;
2440 gint num_formats, i;
2443 array = g_array_new (FALSE, FALSE, sizeof (ConvertResult));
2445 timer = g_timer_new ();
2447 num_formats = get_num_formats ();
2449 for (infmt = GST_VIDEO_FORMAT_I420; infmt < num_formats; infmt++) {
2450 GstVideoInfo ininfo, outinfo;
2451 GstVideoFrame inframe, outframe;
2452 GstBuffer *inbuffer, *outbuffer;
2453 GstVideoConverter *convert;
2458 gst_video_info_set_format (&ininfo, infmt, WIDTH_IN, HEIGHT_IN);
2459 inbuffer = gst_buffer_new_and_alloc (ininfo.size);
2460 gst_buffer_memset (inbuffer, 0, 0, -1);
2461 gst_video_frame_map (&inframe, &ininfo, inbuffer, GST_MAP_READ);
2464 gst_video_info_set_format (&outinfo, outfmt, WIDTH_OUT, HEIGHT_OUT);
2465 outbuffer = gst_buffer_new_and_alloc (outinfo.size);
2466 gst_video_frame_map (&outframe, &outinfo, outbuffer, GST_MAP_WRITE);
2468 for (method = 0; method < 4; method++) {
2469 convert = gst_video_converter_new (&ininfo, &outinfo,
2470 gst_structure_new ("options",
2471 GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
2472 GST_TYPE_VIDEO_RESAMPLER_METHOD, method, NULL));
2475 gst_video_converter_frame (convert, &inframe, &outframe);
2478 g_timer_start (timer);
2480 gst_video_converter_frame (convert, &inframe, &outframe);
2483 elapsed = g_timer_elapsed (timer, NULL);
2484 if (elapsed >= TIME)
2489 res.outfmt = outfmt;
2490 res.method = method;
2491 res.convert_sec = count / elapsed;
2493 GST_DEBUG ("%f resize/sec %s->%s, %d, %d/%f", res.convert_sec,
2494 gst_video_format_to_string (infmt),
2495 gst_video_format_to_string (outfmt), method, count, elapsed);
2497 g_array_append_val (array, res);
2499 gst_video_converter_free (convert);
2501 gst_video_frame_unmap (&outframe);
2502 gst_buffer_unref (outbuffer);
2503 gst_video_frame_unmap (&inframe);
2504 gst_buffer_unref (inbuffer);
2507 g_array_sort (array, compare_result);
2509 for (i = 0; i < array->len; i++) {
2510 ConvertResult *res = &g_array_index (array, ConvertResult, i);
2512 GST_DEBUG ("%f method %d, resize/sec %s->%s", res->convert_sec, res->method,
2513 gst_video_format_to_string (res->infmt),
2514 gst_video_format_to_string (res->outfmt));
2517 g_array_free (array, TRUE);
2519 g_timer_destroy (timer);
2526 GST_START_TEST (test_video_convert)
2528 GstVideoInfo ininfo, outinfo;
2529 GstVideoFrame inframe, outframe;
2530 GstBuffer *inbuffer, *outbuffer;
2531 GstVideoConverter *convert;
2533 gst_video_info_set_format (&ininfo, GST_VIDEO_FORMAT_ARGB, 320, 240);
2534 inbuffer = gst_buffer_new_and_alloc (ininfo.size);
2535 gst_buffer_memset (inbuffer, 0, 0, -1);
2536 gst_video_frame_map (&inframe, &ininfo, inbuffer, GST_MAP_READ);
2538 gst_video_info_set_format (&outinfo, GST_VIDEO_FORMAT_BGRx, 400, 300);
2539 outbuffer = gst_buffer_new_and_alloc (outinfo.size);
2540 gst_video_frame_map (&outframe, &outinfo, outbuffer, GST_MAP_WRITE);
2542 /* see that we don't reuse the source line directly because we need
2543 * to add borders to it */
2544 convert = gst_video_converter_new (&ininfo, &outinfo,
2545 gst_structure_new ("options",
2546 GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
2547 GST_TYPE_VIDEO_RESAMPLER_METHOD, 3,
2548 GST_VIDEO_CONVERTER_OPT_SRC_X, G_TYPE_INT, 10,
2549 GST_VIDEO_CONVERTER_OPT_SRC_Y, G_TYPE_INT, 0,
2550 GST_VIDEO_CONVERTER_OPT_SRC_WIDTH, G_TYPE_INT, 300,
2551 GST_VIDEO_CONVERTER_OPT_SRC_HEIGHT, G_TYPE_INT, 220,
2552 GST_VIDEO_CONVERTER_OPT_DEST_X, G_TYPE_INT, 80,
2553 GST_VIDEO_CONVERTER_OPT_DEST_Y, G_TYPE_INT, 60,
2554 GST_VIDEO_CONVERTER_OPT_DEST_WIDTH, G_TYPE_INT, 300,
2555 GST_VIDEO_CONVERTER_OPT_DEST_HEIGHT, G_TYPE_INT, 220, NULL));
2557 gst_video_converter_frame (convert, &inframe, &outframe);
2558 gst_video_converter_free (convert);
2560 /* see that we reuse the source line directly because we need to scale
2562 convert = gst_video_converter_new (&ininfo, &outinfo,
2563 gst_structure_new ("options",
2564 GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
2565 GST_TYPE_VIDEO_RESAMPLER_METHOD, 3,
2566 GST_VIDEO_CONVERTER_OPT_SRC_X, G_TYPE_INT, 10,
2567 GST_VIDEO_CONVERTER_OPT_SRC_Y, G_TYPE_INT, 0,
2568 GST_VIDEO_CONVERTER_OPT_SRC_WIDTH, G_TYPE_INT, 300,
2569 GST_VIDEO_CONVERTER_OPT_SRC_HEIGHT, G_TYPE_INT, 220,
2570 GST_VIDEO_CONVERTER_OPT_DEST_X, G_TYPE_INT, 80,
2571 GST_VIDEO_CONVERTER_OPT_DEST_Y, G_TYPE_INT, 60,
2572 GST_VIDEO_CONVERTER_OPT_DEST_WIDTH, G_TYPE_INT, 310,
2573 GST_VIDEO_CONVERTER_OPT_DEST_HEIGHT, G_TYPE_INT, 230, NULL));
2575 gst_video_converter_frame (convert, &inframe, &outframe);
2576 gst_video_converter_free (convert);
2578 gst_video_frame_unmap (&outframe);
2579 gst_buffer_unref (outbuffer);
2580 gst_video_frame_unmap (&inframe);
2581 gst_buffer_unref (inbuffer);
2587 GST_START_TEST (test_video_transfer)
2591 for (j = GST_VIDEO_TRANSFER_GAMMA10; j <= GST_VIDEO_TRANSFER_LOG316; j++) {
2592 for (i = 0; i < 256; i++) {
2595 val1 = gst_video_color_transfer_encode (j, i / 255.0);
2596 fail_if (val1 < 0.0 || val1 > 1.0);
2598 val2 = gst_video_color_transfer_decode (j, val1);
2599 fail_if (val2 < 0.0 || val2 > 1.0);
2601 GST_DEBUG ("%d: %d %f->%f->%f %d", j, i, i / 255.0, val1, val2,
2602 (int) lrint (val2 * 255.0));
2604 fail_if (val2 != 0.0);
2606 fail_if (lrint (val2 * 255.0) != i);
2613 GST_START_TEST (test_video_center_rect)
2615 GstVideoRectangle src, dest, result, expected;
2617 #define NEW_RECT(x,y,w,h) ((GstVideoRectangle) {x,y,w,h})
2618 #define CHECK_RECT(res, exp) \
2619 fail_unless_equals_int(exp.x, res.x);\
2620 fail_unless_equals_int(exp.y, res.y);\
2621 fail_unless_equals_int(exp.w, res.w);\
2622 fail_unless_equals_int(exp.h, res.h);
2624 /* 1:1 Aspect Ratio */
2625 src = NEW_RECT (0, 0, 100, 100);
2626 dest = NEW_RECT (0, 0, 100, 100);
2627 expected = NEW_RECT (0, 0, 100, 100);
2628 gst_video_sink_center_rect (src, dest, &result, TRUE);
2629 CHECK_RECT (result, expected);
2631 src = NEW_RECT (0, 0, 100, 100);
2632 dest = NEW_RECT (0, 0, 50, 50);
2633 expected = NEW_RECT (0, 0, 50, 50);
2634 gst_video_sink_center_rect (src, dest, &result, TRUE);
2635 CHECK_RECT (result, expected);
2637 src = NEW_RECT (0, 0, 100, 100);
2638 dest = NEW_RECT (50, 50, 100, 100);
2639 expected = NEW_RECT (50, 50, 100, 100);
2640 gst_video_sink_center_rect (src, dest, &result, TRUE);
2641 CHECK_RECT (result, expected);
2643 /* Aspect ratio scaling (tall) */
2644 src = NEW_RECT (0, 0, 50, 100);
2645 dest = NEW_RECT (0, 0, 50, 50);
2646 expected = NEW_RECT (12, 0, 25, 50);
2647 gst_video_sink_center_rect (src, dest, &result, TRUE);
2648 CHECK_RECT (result, expected);
2650 src = NEW_RECT (0, 0, 50, 100);
2651 dest = NEW_RECT (50, 50, 50, 50);
2652 expected = NEW_RECT (62, 50, 25, 50);
2653 gst_video_sink_center_rect (src, dest, &result, TRUE);
2654 CHECK_RECT (result, expected);
2656 /* Aspect ratio scaling (wide) */
2657 src = NEW_RECT (0, 0, 100, 50);
2658 dest = NEW_RECT (0, 0, 50, 50);
2659 expected = NEW_RECT (0, 12, 50, 25);
2660 gst_video_sink_center_rect (src, dest, &result, TRUE);
2661 CHECK_RECT (result, expected);
2663 src = NEW_RECT (0, 0, 100, 50);
2664 dest = NEW_RECT (50, 50, 50, 50);
2665 expected = NEW_RECT (50, 62, 50, 25);
2666 gst_video_sink_center_rect (src, dest, &result, TRUE);
2667 CHECK_RECT (result, expected);
2672 void test_overlay_blend_rect (gint x, gint y, gint width, gint height,
2673 GstVideoFrame * video_frame);
2674 void test_overlay_blend_rect_verify (gint x, gint y, gint width,
2675 gint height, GstVideoFrame * video_frame);
2676 #define VIDEO_WIDTH 320
2677 #define VIDEO_HEIGHT 240
2680 test_overlay_blend_rect_verify (gint x, gint y, gint width, gint height,
2681 GstVideoFrame * video_frame)
2684 gint i = 0, prev_i = 0;
2686 gint temp_width = 0, temp_height = 0;
2688 data = GST_VIDEO_FRAME_PLANE_DATA (video_frame, 0);
2689 size = GST_VIDEO_FRAME_SIZE (video_frame);
2691 if (x + width < 0 || y + height < 0 || x >= VIDEO_WIDTH || y >= VIDEO_HEIGHT)
2694 temp_width = width + x;
2695 else if (x > 0 && (x + width) <= VIDEO_WIDTH)
2698 temp_width = VIDEO_WIDTH - x;
2700 temp_height = height + y;
2701 else if (y > 0 && (y + height) <= VIDEO_HEIGHT)
2702 temp_height = height;
2704 temp_height = VIDEO_HEIGHT - y;
2706 if (x <= 0 && y <= 0)
2709 i = (((x <= 0) ? 0 : x) + (((y <= 0) ? 0 : y) * VIDEO_WIDTH)) * 4;
2712 for (; i < size - 4; i += 4) {
2713 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
2715 fail_unless_equals_int (data[i], 0x80);
2716 fail_unless_equals_int (data[i + 1], 0x80);
2717 fail_unless_equals_int (data[i + 2], 0x80);
2718 fail_unless_equals_int (data[i + 3], 0x80);
2721 fail_unless_equals_int (data[i], 0x00);
2722 fail_unless_equals_int (data[i + 1], 0x80);
2723 fail_unless_equals_int (data[i + 2], 0x80);
2724 fail_unless_equals_int (data[i + 3], 0x80);
2726 if ((i + 4) == (4 * (((((y > 0) ? (y + temp_height) : temp_height) -
2727 1) * VIDEO_WIDTH) + ((x >
2728 0) ? (x + temp_width) : temp_width))))
2730 if ((i + 4 - prev_i) == ((temp_width) * 4)) {
2731 i += ((VIDEO_WIDTH - (temp_width)) * 4);
2739 test_overlay_blend_rect (gint x, gint y, gint width, gint height,
2740 GstVideoFrame * video_frame)
2742 GstVideoOverlayComposition *comp1;
2743 GstVideoOverlayRectangle *rect1;
2744 GstBuffer *pix, *pix1;
2747 memset (video_frame, 0, sizeof (GstVideoFrame));
2749 gst_buffer_new_and_alloc (VIDEO_WIDTH * VIDEO_HEIGHT * sizeof (guint32));
2750 gst_buffer_memset (pix, 0, 0, gst_buffer_get_size (pix));
2751 gst_video_info_init (&vinfo);
2752 gst_video_info_set_format (&vinfo, GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB,
2753 VIDEO_WIDTH, VIDEO_HEIGHT);
2754 gst_video_frame_map (video_frame, &vinfo, pix, GST_MAP_READWRITE);
2755 gst_buffer_unref (pix);
2758 pix1 = gst_buffer_new_and_alloc (width * height * sizeof (guint32));
2759 gst_buffer_memset (pix1, 0, 0x80, gst_buffer_get_size (pix1));
2760 gst_buffer_add_video_meta (pix1, GST_VIDEO_FRAME_FLAG_NONE,
2761 GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB, width, height);
2762 rect1 = gst_video_overlay_rectangle_new_raw (pix1,
2763 x, y, width, height, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
2764 gst_buffer_unref (pix1);
2767 comp1 = gst_video_overlay_composition_new (rect1);
2768 fail_unless (gst_video_overlay_composition_blend (comp1, video_frame));
2769 gst_video_overlay_composition_unref (comp1);
2770 gst_video_overlay_rectangle_unref (rect1);
2772 test_overlay_blend_rect_verify (x, y, width, height, video_frame);
2773 gst_video_frame_unmap (video_frame);
2776 GST_START_TEST (test_overlay_blend)
2778 GstVideoFrame video_frame;
2780 /* Overlay width & height smaller than video width & height */
2781 /* Overlay rendered completely left of video surface
2782 * x + overlay_width <= 0 */
2783 test_overlay_blend_rect (-60, 50, 50, 50, &video_frame);
2784 /* Overlay rendered completely right of video surface
2785 * x >= video_width */
2786 test_overlay_blend_rect (330, 50, 50, 50, &video_frame);
2787 /* Overlay rendered completely top of video surface
2788 * y + overlay_height <= 0 */
2789 test_overlay_blend_rect (50, -60, 50, 50, &video_frame);
2790 /* Overlay rendered completely bottom of video surface
2791 * y >= video_height */
2792 test_overlay_blend_rect (50, 250, 50, 50, &video_frame);
2793 /* Overlay rendered partially left of video surface
2794 * x < 0 && -x < overlay_width */
2795 test_overlay_blend_rect (-40, 50, 50, 50, &video_frame);
2796 /* Overlay rendered partially right of video surface
2797 * x < video_width && (overlay_width + x) > video_width */
2798 test_overlay_blend_rect (300, 50, 50, 50, &video_frame);
2799 /* Overlay rendered partially top of video surface
2800 * y < 0 && -y < overlay_height */
2801 test_overlay_blend_rect (50, -40, 50, 50, &video_frame);
2802 /* Overlay rendered partially bottom of video surface
2803 * y < video_height && (overlay_height + y) > video_height */
2804 test_overlay_blend_rect (50, 220, 50, 50, &video_frame);
2806 /* Overlay width & height bigger than video width & height */
2807 /* Overlay rendered completely left of video surface
2808 * x + overlay_width <= 0 */
2809 test_overlay_blend_rect (-360, 50, 350, 250, &video_frame);
2810 /* Overlay rendered completely right of video surface
2811 * x >= video_width */
2812 test_overlay_blend_rect (330, 50, 350, 250, &video_frame);
2813 /* Overlay rendered completely top of video surface
2814 * y + overlay_height <= 0 */
2815 test_overlay_blend_rect (50, -260, 350, 250, &video_frame);
2816 /* Overlay rendered completely bottom of video surface
2817 * y >= video_height */
2818 test_overlay_blend_rect (50, 250, 350, 250, &video_frame);
2819 /* Overlay rendered partially left of video surface
2820 * x < 0 && -x < overlay_width */
2821 test_overlay_blend_rect (-40, 50, 350, 250, &video_frame);
2822 /* Overlay rendered partially right of video surface
2823 * x < video_width && (overlay_width + x) > video_width */
2824 test_overlay_blend_rect (300, 50, 350, 250, &video_frame);
2825 /* Overlay rendered partially top of video surface
2826 * y < 0 && -y < overlay_height */
2827 test_overlay_blend_rect (50, -40, 350, 250, &video_frame);
2828 /* Overlay rendered partially bottom of video surface
2829 * y < video_height && (overlay_height + y) > video_height */
2830 test_overlay_blend_rect (50, 220, 350, 250, &video_frame);
2835 GST_START_TEST (test_overlay_composition_over_transparency)
2837 GstVideoOverlayComposition *comp1;
2838 GstVideoOverlayRectangle *rect1;
2839 GstBuffer *pix1, *pix2;
2843 GstVideoFrame video_frame;
2844 guint fwidth = 200, height = 50, swidth = 100;
2846 memset (&video_frame, 0, sizeof (GstVideoFrame));
2848 pix1 = gst_buffer_new_and_alloc (fwidth * sizeof (guint32) * height);
2849 gst_buffer_memset (pix1, 0, 0x00, gst_buffer_get_size (pix1));
2850 gst_video_info_init (&vinfo);
2851 gst_video_info_set_format (&vinfo, GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB,
2853 gst_video_frame_map (&video_frame, &vinfo, pix1, GST_MAP_READWRITE);
2854 gst_buffer_unref (pix1);
2856 pix2 = gst_buffer_new_and_alloc (swidth * sizeof (guint32) * height);
2857 gst_buffer_memset (pix2, 0, 0xFF, gst_buffer_get_size (pix2));
2858 gst_buffer_add_video_meta (pix2, GST_VIDEO_FRAME_FLAG_NONE,
2859 GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB, swidth, height);
2860 rect1 = gst_video_overlay_rectangle_new_raw (pix2, swidth, 0,
2861 swidth, height, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
2863 comp1 = gst_video_overlay_composition_new (rect1);
2864 fail_unless (gst_video_overlay_composition_blend (comp1, &video_frame));
2865 gst_video_overlay_composition_unref (comp1);
2866 gst_video_overlay_rectangle_unref (rect1);
2867 gst_buffer_unref (pix2);
2869 data = GST_VIDEO_FRAME_PLANE_DATA (&video_frame, 0);
2871 fail_unless_equals_int (data[0], 0x00);
2872 fail_unless_equals_int (data[1], 0x00);
2873 fail_unless_equals_int (data[2], 0x00);
2874 fail_unless_equals_int (data[3], 0x00);
2876 data += swidth * sizeof (guint32);
2878 fail_unless_equals_int (data[0], 0xFF);
2879 fail_unless_equals_int (data[1], 0xFF);
2880 fail_unless_equals_int (data[2], 0xFF);
2881 fail_unless_equals_int (data[3], 0xFF);
2883 gst_video_frame_unmap (&video_frame);
2892 Suite *s = suite_create ("video support library");
2893 TCase *tc_chain = tcase_create ("general");
2895 tcase_set_timeout (tc_chain, 60 * 60);
2897 suite_add_tcase (s, tc_chain);
2898 tcase_add_test (tc_chain, test_video_formats);
2899 tcase_add_test (tc_chain, test_video_formats_overflow);
2900 tcase_add_test (tc_chain, test_video_formats_rgb);
2901 tcase_add_test (tc_chain, test_video_formats_rgba_large_dimension);
2902 tcase_add_test (tc_chain, test_video_formats_all);
2903 tcase_add_test (tc_chain, test_video_formats_pack_unpack);
2904 tcase_add_test (tc_chain, test_guess_framerate);
2905 tcase_add_test (tc_chain, test_dar_calc);
2906 tcase_add_test (tc_chain, test_parse_caps_rgb);
2907 tcase_add_test (tc_chain, test_parse_caps_multiview);
2908 tcase_add_test (tc_chain, test_parse_colorimetry);
2909 tcase_add_test (tc_chain, test_events);
2910 tcase_add_test (tc_chain, test_convert_frame);
2911 tcase_add_test (tc_chain, test_convert_frame_async);
2912 tcase_add_test (tc_chain, test_video_size_from_caps);
2913 tcase_add_test (tc_chain, test_interlace_mode);
2914 tcase_add_test (tc_chain, test_overlay_composition);
2915 tcase_add_test (tc_chain, test_overlay_composition_premultiplied_alpha);
2916 tcase_add_test (tc_chain, test_overlay_composition_global_alpha);
2917 tcase_add_test (tc_chain, test_video_pack_unpack2);
2918 tcase_add_test (tc_chain, test_video_chroma);
2919 tcase_add_test (tc_chain, test_video_scaler);
2920 tcase_add_test (tc_chain, test_video_color_convert);
2921 tcase_add_test (tc_chain, test_video_size_convert);
2922 tcase_add_test (tc_chain, test_video_convert);
2923 tcase_add_test (tc_chain, test_video_transfer);
2924 tcase_add_test (tc_chain, test_overlay_blend);
2925 tcase_add_test (tc_chain, test_video_center_rect);
2926 tcase_add_test (tc_chain, test_overlay_composition_over_transparency);
2931 GST_CHECK_MAIN (video);