Macro qtTrIdx() replaced by tr() and QT_TRANSLATE_NOOP()
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / tests / check / libs / video.c
1 /* GStreamer unit test for video
2  *
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Jan Schmidt <thaytan@mad.scientist.com>
5  * Copyright (C) <2008> Tim-Philipp Müller <tim centricular net>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <unistd.h>
28
29 #include <gst/check/gstcheck.h>
30
31 #include <gst/video/video.h>
32 #include <string.h>
33
34 /* These are from the current/old videotestsrc; we check our new public API
35  * in libgstvideo against the old one to make sure the sizes and offsets
36  * end up the same */
37
38 typedef struct paintinfo_struct paintinfo;
39 struct paintinfo_struct
40 {
41   unsigned char *dest;          /* pointer to first byte of video data */
42   unsigned char *yp, *up, *vp;  /* pointers to first byte of each component
43                                  * for both packed/planar YUV and RGB */
44   unsigned char *ap;            /* pointer to first byte of alpha component */
45   unsigned char *endptr;        /* pointer to byte beyond last video data */
46   int ystride;
47   int ustride;
48   int vstride;
49   int width;
50   int height;
51 };
52
53 struct fourcc_list_struct
54 {
55   const char *fourcc;
56   const char *name;
57   int bitspp;
58   void (*paint_setup) (paintinfo * p, unsigned char *dest);
59 };
60
61 static void paint_setup_I420 (paintinfo * p, unsigned char *dest);
62 static void paint_setup_YV12 (paintinfo * p, unsigned char *dest);
63 static void paint_setup_YUY2 (paintinfo * p, unsigned char *dest);
64 static void paint_setup_UYVY (paintinfo * p, unsigned char *dest);
65 static void paint_setup_YVYU (paintinfo * p, unsigned char *dest);
66 static void paint_setup_IYU2 (paintinfo * p, unsigned char *dest);
67 static void paint_setup_Y41B (paintinfo * p, unsigned char *dest);
68 static void paint_setup_Y42B (paintinfo * p, unsigned char *dest);
69 static void paint_setup_Y800 (paintinfo * p, unsigned char *dest);
70 static void paint_setup_AYUV (paintinfo * p, unsigned char *dest);
71
72 #if 0
73 static void paint_setup_IMC1 (paintinfo * p, unsigned char *dest);
74 static void paint_setup_IMC2 (paintinfo * p, unsigned char *dest);
75 static void paint_setup_IMC3 (paintinfo * p, unsigned char *dest);
76 static void paint_setup_IMC4 (paintinfo * p, unsigned char *dest);
77 #endif
78 static void paint_setup_YUV9 (paintinfo * p, unsigned char *dest);
79 static void paint_setup_YVU9 (paintinfo * p, unsigned char *dest);
80
81 int fourcc_get_size (struct fourcc_list_struct *fourcc, int w, int h);
82
83 struct fourcc_list_struct fourcc_list[] = {
84 /* packed */
85   {"YUY2", "YUY2", 16, paint_setup_YUY2},
86   {"UYVY", "UYVY", 16, paint_setup_UYVY},
87   {"Y422", "Y422", 16, paint_setup_UYVY},
88   {"UYNV", "UYNV", 16, paint_setup_UYVY},       /* FIXME: UYNV? */
89   {"YVYU", "YVYU", 16, paint_setup_YVYU},
90   {"AYUV", "AYUV", 32, paint_setup_AYUV},
91
92   /* interlaced */
93   /*{   "IUYV", "IUY2", 16, paint_setup_YVYU }, */
94
95   /* inverted */
96   /*{   "cyuv", "cyuv", 16, paint_setup_YVYU }, */
97
98   /*{   "Y41P", "Y41P", 12, paint_setup_YVYU }, */
99
100   /* interlaced */
101   /*{   "IY41", "IY41", 12, paint_setup_YVYU }, */
102
103   /*{   "Y211", "Y211", 8, paint_setup_YVYU }, */
104
105   /*{   "Y41T", "Y41T", 12, paint_setup_YVYU }, */
106   /*{   "Y42P", "Y42P", 16, paint_setup_YVYU }, */
107   /*{   "CLJR", "CLJR", 8, paint_setup_YVYU }, */
108   /*{   "IYU1", "IYU1", 12, paint_setup_YVYU }, */
109   {"IYU2", "IYU2", 24, paint_setup_IYU2},
110
111 /* planar */
112   /* YVU9 */
113   {"YVU9", "YVU9", 9, paint_setup_YVU9},
114   /* YUV9 */
115   {"YUV9", "YUV9", 9, paint_setup_YUV9},
116   /* IF09 */
117   /* YV12 */
118   {"YV12", "YV12", 12, paint_setup_YV12},
119   /* I420 */
120   {"I420", "I420", 12, paint_setup_I420},
121   /* NV12 */
122   /* NV21 */
123 #if 0
124   /* IMC1 */
125   {"IMC1", "IMC1", 16, paint_setup_IMC1},
126   /* IMC2 */
127   {"IMC2", "IMC2", 12, paint_setup_IMC2},
128   /* IMC3 */
129   {"IMC3", "IMC3", 16, paint_setup_IMC3},
130   /* IMC4 */
131   {"IMC4", "IMC4", 12, paint_setup_IMC4},
132 #endif
133   /* CLPL */
134   /* Y41B */
135   {"Y41B", "Y41B", 12, paint_setup_Y41B},
136   /* Y42B */
137   {"Y42B", "Y42B", 16, paint_setup_Y42B},
138   /* Y800 grayscale */
139   {"Y800", "Y800", 8, paint_setup_Y800}
140 };
141
142 /* returns the size in bytes for one video frame of the given dimensions
143  * given the fourcc */
144 int
145 fourcc_get_size (struct fourcc_list_struct *fourcc, int w, int h)
146 {
147   paintinfo pi = { NULL, };
148   paintinfo *p = &pi;
149
150   p->width = w;
151   p->height = h;
152
153   fourcc->paint_setup (p, NULL);
154
155   return (unsigned long) p->endptr;
156 }
157
158 static void
159 paint_setup_I420 (paintinfo * p, unsigned char *dest)
160 {
161   p->yp = dest;
162   p->ystride = GST_ROUND_UP_4 (p->width);
163   p->up = p->yp + p->ystride * GST_ROUND_UP_2 (p->height);
164   p->ustride = GST_ROUND_UP_8 (p->width) / 2;
165   p->vp = p->up + p->ustride * GST_ROUND_UP_2 (p->height) / 2;
166   p->vstride = GST_ROUND_UP_8 (p->ystride) / 2;
167   p->endptr = p->vp + p->vstride * GST_ROUND_UP_2 (p->height) / 2;
168 }
169
170 static void
171 paint_setup_YV12 (paintinfo * p, unsigned char *dest)
172 {
173   p->yp = dest;
174   p->ystride = GST_ROUND_UP_4 (p->width);
175   p->vp = p->yp + p->ystride * GST_ROUND_UP_2 (p->height);
176   p->vstride = GST_ROUND_UP_8 (p->ystride) / 2;
177   p->up = p->vp + p->vstride * GST_ROUND_UP_2 (p->height) / 2;
178   p->ustride = GST_ROUND_UP_8 (p->ystride) / 2;
179   p->endptr = p->up + p->ustride * GST_ROUND_UP_2 (p->height) / 2;
180 }
181
182 static void
183 paint_setup_AYUV (paintinfo * p, unsigned char *dest)
184 {
185   p->ap = dest;
186   p->yp = dest + 1;
187   p->up = dest + 2;
188   p->vp = dest + 3;
189   p->ystride = p->width * 4;
190   p->endptr = dest + p->ystride * p->height;
191 }
192
193 static void
194 paint_setup_YUY2 (paintinfo * p, unsigned char *dest)
195 {
196   p->yp = dest;
197   p->up = dest + 1;
198   p->vp = dest + 3;
199   p->ystride = GST_ROUND_UP_2 (p->width) * 2;
200   p->endptr = dest + p->ystride * p->height;
201 }
202
203 static void
204 paint_setup_UYVY (paintinfo * p, unsigned char *dest)
205 {
206   p->yp = dest + 1;
207   p->up = dest;
208   p->vp = dest + 2;
209   p->ystride = GST_ROUND_UP_2 (p->width) * 2;
210   p->endptr = dest + p->ystride * p->height;
211 }
212
213 static void
214 paint_setup_YVYU (paintinfo * p, unsigned char *dest)
215 {
216   p->yp = dest;
217   p->up = dest + 3;
218   p->vp = dest + 1;
219   p->ystride = GST_ROUND_UP_2 (p->width) * 2;
220   p->endptr = dest + p->ystride * p->height;
221 }
222
223 static void
224 paint_setup_IYU2 (paintinfo * p, unsigned char *dest)
225 {
226   /* untested */
227   p->yp = dest + 1;
228   p->up = dest + 0;
229   p->vp = dest + 2;
230   p->ystride = GST_ROUND_UP_4 (p->width * 3);
231   p->endptr = dest + p->ystride * p->height;
232 }
233
234 static void
235 paint_setup_Y41B (paintinfo * p, unsigned char *dest)
236 {
237   p->yp = dest;
238   p->ystride = GST_ROUND_UP_4 (p->width);
239   p->up = p->yp + p->ystride * p->height;
240   p->ustride = GST_ROUND_UP_16 (p->width) / 4;
241   p->vp = p->up + p->ustride * p->height;
242   p->vstride = GST_ROUND_UP_16 (p->width) / 4;
243   p->endptr = p->vp + p->vstride * p->height;
244 }
245
246 static void
247 paint_setup_Y42B (paintinfo * p, unsigned char *dest)
248 {
249   p->yp = dest;
250   p->ystride = GST_ROUND_UP_4 (p->width);
251   p->up = p->yp + p->ystride * p->height;
252   p->ustride = GST_ROUND_UP_8 (p->width) / 2;
253   p->vp = p->up + p->ustride * p->height;
254   p->vstride = GST_ROUND_UP_8 (p->width) / 2;
255   p->endptr = p->vp + p->vstride * p->height;
256 }
257
258 static void
259 paint_setup_Y800 (paintinfo * p, unsigned char *dest)
260 {
261   /* untested */
262   p->yp = dest;
263   p->ystride = GST_ROUND_UP_4 (p->width);
264   p->endptr = dest + p->ystride * p->height;
265 }
266
267 #if 0
268 static void
269 paint_setup_IMC1 (paintinfo * p, unsigned char *dest)
270 {
271   p->yp = dest;
272   p->up = dest + p->width * p->height;
273   p->vp = dest + p->width * p->height + p->width * p->height / 2;
274 }
275
276 static void
277 paint_setup_IMC2 (paintinfo * p, unsigned char *dest)
278 {
279   p->yp = dest;
280   p->vp = dest + p->width * p->height;
281   p->up = dest + p->width * p->height + p->width / 2;
282 }
283
284 static void
285 paint_setup_IMC3 (paintinfo * p, unsigned char *dest)
286 {
287   p->yp = dest;
288   p->up = dest + p->width * p->height + p->width * p->height / 2;
289   p->vp = dest + p->width * p->height;
290 }
291
292 static void
293 paint_setup_IMC4 (paintinfo * p, unsigned char *dest)
294 {
295   p->yp = dest;
296   p->vp = dest + p->width * p->height + p->width / 2;
297   p->up = dest + p->width * p->height;
298 }
299 #endif
300
301 static void
302 paint_setup_YVU9 (paintinfo * p, unsigned char *dest)
303 {
304   p->yp = dest;
305   p->ystride = GST_ROUND_UP_4 (p->width);
306   p->vp = p->yp + p->ystride * p->height;
307   p->vstride = GST_ROUND_UP_4 (p->ystride / 4);
308   p->up = p->vp + p->vstride * (GST_ROUND_UP_4 (p->height) / 4);
309   p->ustride = GST_ROUND_UP_4 (p->ystride / 4);
310   p->endptr = p->up + p->ustride * (GST_ROUND_UP_4 (p->height) / 4);
311 }
312
313 static void
314 paint_setup_YUV9 (paintinfo * p, unsigned char *dest)
315 {
316   p->yp = dest;
317   p->ystride = GST_ROUND_UP_4 (p->width);
318   p->up = p->yp + p->ystride * p->height;
319   p->ustride = GST_ROUND_UP_4 (p->ystride / 4);
320   p->vp = p->up + p->ustride * (GST_ROUND_UP_4 (p->height) / 4);
321   p->vstride = GST_ROUND_UP_4 (p->ystride / 4);
322   p->endptr = p->vp + p->vstride * (GST_ROUND_UP_4 (p->height) / 4);
323 }
324
325 #define gst_video_format_is_packed video_format_is_packed
326 static gboolean
327 video_format_is_packed (GstVideoFormat fmt)
328 {
329   switch (fmt) {
330     case GST_VIDEO_FORMAT_I420:
331     case GST_VIDEO_FORMAT_YV12:
332     case GST_VIDEO_FORMAT_Y41B:
333     case GST_VIDEO_FORMAT_Y42B:
334     case GST_VIDEO_FORMAT_Y800:
335     case GST_VIDEO_FORMAT_YUV9:
336     case GST_VIDEO_FORMAT_YVU9:
337       return FALSE;
338     case GST_VIDEO_FORMAT_IYU1:
339     case GST_VIDEO_FORMAT_YUY2:
340     case GST_VIDEO_FORMAT_YVYU:
341     case GST_VIDEO_FORMAT_UYVY:
342     case GST_VIDEO_FORMAT_AYUV:
343     case GST_VIDEO_FORMAT_RGBx:
344     case GST_VIDEO_FORMAT_BGRx:
345     case GST_VIDEO_FORMAT_xRGB:
346     case GST_VIDEO_FORMAT_xBGR:
347     case GST_VIDEO_FORMAT_RGBA:
348     case GST_VIDEO_FORMAT_BGRA:
349     case GST_VIDEO_FORMAT_ARGB:
350     case GST_VIDEO_FORMAT_ABGR:
351     case GST_VIDEO_FORMAT_RGB:
352     case GST_VIDEO_FORMAT_BGR:
353     case GST_VIDEO_FORMAT_RGB8_PALETTED:
354       return TRUE;
355     default:
356       g_return_val_if_reached (FALSE);
357   }
358   return FALSE;
359 }
360
361 GST_START_TEST (test_video_formats)
362 {
363   guint i;
364
365   for (i = 0; i < G_N_ELEMENTS (fourcc_list); ++i) {
366     GstVideoFormat fmt;
367     const gchar *s;
368     guint32 fourcc;
369     guint w, h;
370
371     s = fourcc_list[i].fourcc;
372     fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]);
373     fmt = gst_video_format_from_fourcc (fourcc);
374
375     if (fmt == GST_VIDEO_FORMAT_UNKNOWN)
376       continue;
377
378     GST_INFO ("Fourcc %s, packed=%d", fourcc_list[i].fourcc,
379         gst_video_format_is_packed (fmt));
380
381     fail_unless (gst_video_format_is_yuv (fmt));
382
383     /* use any non-NULL pointer so we can compare against NULL */
384     {
385       paintinfo paintinfo = { 0, };
386       fourcc_list[i].paint_setup (&paintinfo, (unsigned char *) s);
387       if (paintinfo.ap != NULL) {
388         fail_unless (gst_video_format_has_alpha (fmt));
389       } else {
390         fail_if (gst_video_format_has_alpha (fmt));
391       }
392     }
393
394     for (w = 1; w <= 65; ++w) {
395       for (h = 1; h <= 65; ++h) {
396         paintinfo paintinfo = { 0, };
397         guint off0, off1, off2, off3;
398         guint size;
399
400         GST_LOG ("%s, %dx%d", fourcc_list[i].fourcc, w, h);
401
402         paintinfo.width = w;
403         paintinfo.height = h;
404         fourcc_list[i].paint_setup (&paintinfo, NULL);
405         fail_unless_equals_int (gst_video_format_get_row_stride (fmt, 0, w),
406             paintinfo.ystride);
407         if (!gst_video_format_is_packed (fmt)
408             && !gst_video_format_is_gray (fmt)) {
409           /* planar */
410           fail_unless_equals_int (gst_video_format_get_row_stride (fmt, 1, w),
411               paintinfo.ustride);
412           fail_unless_equals_int (gst_video_format_get_row_stride (fmt, 2, w),
413               paintinfo.vstride);
414           /* check component_width * height against offsets/size somehow? */
415         }
416
417         size = gst_video_format_get_size (fmt, w, h);
418         off0 = gst_video_format_get_component_offset (fmt, 0, w, h);
419         off1 = gst_video_format_get_component_offset (fmt, 1, w, h);
420         off2 = gst_video_format_get_component_offset (fmt, 2, w, h);
421
422         fail_unless_equals_int (size, (unsigned long) paintinfo.endptr);
423         fail_unless_equals_int (off0, (unsigned long) paintinfo.yp);
424         fail_unless_equals_int (off1, (unsigned long) paintinfo.up);
425         fail_unless_equals_int (off2, (unsigned long) paintinfo.vp);
426
427         /* should be 0 if there's no alpha component */
428         off3 = gst_video_format_get_component_offset (fmt, 3, w, h);
429         fail_unless_equals_int (off3, (unsigned long) paintinfo.ap);
430
431         /* some gstvideo checks ... (FIXME: fails for Y41B and Y42B; not sure
432          * if the check or the _get_component_size implementation is wrong) */
433         if (fmt != GST_VIDEO_FORMAT_Y41B && fmt != GST_VIDEO_FORMAT_Y42B
434             && fmt != GST_VIDEO_FORMAT_Y800) {
435           guint cs0, cs1, cs2, cs3;
436
437           cs0 = gst_video_format_get_component_width (fmt, 0, w) *
438               gst_video_format_get_component_height (fmt, 0, h);
439           cs1 = gst_video_format_get_component_width (fmt, 1, w) *
440               gst_video_format_get_component_height (fmt, 1, h);
441           cs2 = gst_video_format_get_component_width (fmt, 2, w) *
442               gst_video_format_get_component_height (fmt, 2, h);
443
444           /* GST_LOG ("cs0=%d,cs1=%d,cs2=%d,off0=%d,off1=%d,off2=%d,size=%d",
445              cs0, cs1, cs2, off0, off1, off2, size); */
446
447           if (!gst_video_format_is_packed (fmt))
448             fail_unless (cs0 <= off1);
449
450           if (gst_video_format_has_alpha (fmt)) {
451             cs3 = gst_video_format_get_component_width (fmt, 3, w) *
452                 gst_video_format_get_component_height (fmt, 3, h);
453             fail_unless (cs3 < size);
454             /* U/V/alpha shouldn't take up more space than the Y component */
455             fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0);
456             fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0);
457             fail_if (cs3 > cs0, "cs3 (%d) should be <= cs0 (%d)", cs3, cs0);
458
459             /* all components together shouldn't take up more space than size */
460             fail_unless (cs0 + cs1 + cs2 + cs3 <= size);
461           } else {
462             /* U/V shouldn't take up more space than the Y component */
463             fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0);
464             fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0);
465
466             /* all components together shouldn't take up more space than size */
467             fail_unless (cs0 + cs1 + cs2 <= size,
468                 "cs0 (%d) + cs1 (%d) + cs2 (%d) should be <= size (%d)",
469                 cs0, cs1, cs2, size);
470           }
471         }
472       }
473     }
474   }
475 }
476
477 GST_END_TEST;
478
479 GST_START_TEST (test_video_formats_rgb)
480 {
481   gint width, height, framerate_n, framerate_d, par_n, par_d;
482   GstCaps *caps =
483       gst_video_format_new_caps (GST_VIDEO_FORMAT_RGB, 800, 600, 0, 1, 1, 1);
484   GstStructure *structure;
485
486   structure = gst_caps_get_structure (caps, 0);
487
488   fail_unless (gst_structure_get_int (structure, "width", &width));
489   fail_unless (gst_structure_get_int (structure, "height", &height));
490   fail_unless (gst_structure_get_fraction (structure, "framerate", &framerate_n,
491           &framerate_d));
492   fail_unless (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
493           &par_n, &par_d));
494
495   fail_unless (width == 800);
496   fail_unless (height == 600);
497   fail_unless (framerate_n == 0);
498   fail_unless (framerate_d == 1);
499   fail_unless (par_n == 1);
500   fail_unless (par_d == 1);
501
502   gst_caps_unref (caps);
503 }
504
505 GST_END_TEST;
506
507 GST_START_TEST (test_video_template_caps)
508 {
509   GstCaps *caps = gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGB);
510   gst_caps_unref (caps);
511 }
512
513 GST_END_TEST;
514
515
516 GST_START_TEST (test_dar_calc)
517 {
518   guint display_ratio_n, display_ratio_d;
519
520   /* Ensure that various Display Ratio calculations are correctly done */
521   /* video 768x576, par 16/15, display par 16/15 = 4/3 */
522   fail_unless (gst_video_calculate_display_ratio (&display_ratio_n,
523           &display_ratio_d, 768, 576, 16, 15, 16, 15));
524   fail_unless (display_ratio_n == 4 && display_ratio_d == 3);
525
526   /* video 720x480, par 32/27, display par 1/1 = 16/9 */
527   fail_unless (gst_video_calculate_display_ratio (&display_ratio_n,
528           &display_ratio_d, 720, 480, 32, 27, 1, 1));
529   fail_unless (display_ratio_n == 16 && display_ratio_d == 9);
530
531   /* video 360x288, par 533333/500000, display par 16/15 = 
532    * dar 1599999/1600000 */
533   fail_unless (gst_video_calculate_display_ratio (&display_ratio_n,
534           &display_ratio_d, 360, 288, 533333, 500000, 16, 15));
535   fail_unless (display_ratio_n == 1599999 && display_ratio_d == 1280000);
536 }
537
538 GST_END_TEST;
539
540 GST_START_TEST (test_parse_caps_rgb)
541 {
542   struct
543   {
544     const gchar *tmpl_caps_string;
545     GstVideoFormat fmt;
546   } formats[] = {
547     /* 24 bit */
548     {
549     GST_VIDEO_CAPS_RGB, GST_VIDEO_FORMAT_RGB}, {
550     GST_VIDEO_CAPS_BGR, GST_VIDEO_FORMAT_BGR},
551         /* 32 bit (no alpha) */
552     {
553     GST_VIDEO_CAPS_RGBx, GST_VIDEO_FORMAT_RGBx}, {
554     GST_VIDEO_CAPS_xRGB, GST_VIDEO_FORMAT_xRGB}, {
555     GST_VIDEO_CAPS_BGRx, GST_VIDEO_FORMAT_BGRx}, {
556     GST_VIDEO_CAPS_xBGR, GST_VIDEO_FORMAT_xBGR},
557         /* 32 bit (with alpha) */
558     {
559     GST_VIDEO_CAPS_RGBA, GST_VIDEO_FORMAT_RGBA}, {
560     GST_VIDEO_CAPS_ARGB, GST_VIDEO_FORMAT_ARGB}, {
561     GST_VIDEO_CAPS_BGRA, GST_VIDEO_FORMAT_BGRA}, {
562     GST_VIDEO_CAPS_ABGR, GST_VIDEO_FORMAT_ABGR}
563   };
564   gint i;
565
566   for (i = 0; i < G_N_ELEMENTS (formats); ++i) {
567     GstVideoFormat fmt = GST_VIDEO_FORMAT_UNKNOWN;
568     GstCaps *caps, *caps2;
569     int w = -1, h = -1;
570
571     caps = gst_caps_from_string (formats[i].tmpl_caps_string);
572     gst_caps_set_simple (caps, "width", G_TYPE_INT, 2 * (i + 1), "height",
573         G_TYPE_INT, i + 1, "framerate", GST_TYPE_FRACTION, 15, 1,
574         "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
575     g_assert (gst_caps_is_fixed (caps));
576
577     GST_DEBUG ("testing caps: %" GST_PTR_FORMAT, caps);
578
579     fail_unless (gst_video_format_parse_caps (caps, &fmt, &w, &h));
580     fail_unless_equals_int (fmt, formats[i].fmt);
581     fail_unless_equals_int (w, 2 * (i + 1));
582     fail_unless_equals_int (h, i + 1);
583
584     /* make sure they're serialised back correctly */
585     caps2 = gst_video_format_new_caps (fmt, w, h, 15, 1, 1, 1);
586     fail_unless (caps != NULL);
587     fail_unless (gst_caps_is_equal (caps, caps2));
588
589     gst_caps_unref (caps);
590     gst_caps_unref (caps2);
591   }
592 }
593
594 GST_END_TEST;
595
596 GST_START_TEST (test_events)
597 {
598   GstEvent *e;
599   gboolean in_still;
600
601   e = gst_video_event_new_still_frame (TRUE);
602   fail_if (e == NULL, "Failed to create still frame event");
603   fail_unless (gst_video_event_parse_still_frame (e, &in_still),
604       "Failed to parse still frame event");
605   fail_unless (gst_video_event_parse_still_frame (e, NULL),
606       "Failed to parse still frame event w/ in_still == NULL");
607   fail_unless (in_still == TRUE);
608   gst_event_unref (e);
609
610   e = gst_video_event_new_still_frame (FALSE);
611   fail_if (e == NULL, "Failed to create still frame event");
612   fail_unless (gst_video_event_parse_still_frame (e, &in_still),
613       "Failed to parse still frame event");
614   fail_unless (gst_video_event_parse_still_frame (e, NULL),
615       "Failed to parse still frame event w/ in_still == NULL");
616   fail_unless (in_still == FALSE);
617   gst_event_unref (e);
618 }
619
620 GST_END_TEST;
621
622 GST_START_TEST (test_convert_frame)
623 {
624   GstCaps *from_caps, *to_caps;
625   GstBuffer *from_buffer, *to_buffer;
626   GError *error = NULL;
627   gint i;
628   guint8 *data;
629
630   from_buffer = gst_buffer_new_and_alloc (640 * 480 * 4);
631   data = GST_BUFFER_DATA (from_buffer);
632
633   for (i = 0; i < 640 * 480; i++) {
634     data[4 * i + 0] = 0;        /* x */
635     data[4 * i + 1] = 255;      /* R */
636     data[4 * i + 2] = 0;        /* G */
637     data[4 * i + 3] = 0;        /* B */
638   }
639   from_caps = gst_video_format_new_caps (GST_VIDEO_FORMAT_xRGB,
640       640, 480, 25, 1, 1, 1);
641   gst_buffer_set_caps (from_buffer, from_caps);
642
643   to_caps =
644       gst_caps_from_string
645       ("something/that, does=(string)not, exist=(boolean)FALSE");
646
647   to_buffer =
648       gst_video_convert_frame (from_buffer, to_caps, GST_CLOCK_TIME_NONE,
649       &error);
650   fail_if (to_buffer != NULL);
651   fail_unless (error != NULL);
652   g_error_free (error);
653   error = NULL;
654
655   gst_caps_unref (to_caps);
656   to_caps =
657       gst_video_format_new_caps (GST_VIDEO_FORMAT_I420, 240, 320, 25, 1, 1, 2);
658   to_buffer =
659       gst_video_convert_frame (from_buffer, to_caps, GST_CLOCK_TIME_NONE,
660       &error);
661   fail_unless (to_buffer != NULL);
662   fail_unless (gst_caps_can_intersect (to_caps, GST_BUFFER_CAPS (to_buffer)));
663   fail_unless (error == NULL);
664
665   gst_buffer_unref (from_buffer);
666   gst_caps_unref (from_caps);
667   gst_buffer_unref (to_buffer);
668   gst_caps_unref (to_caps);
669 }
670
671 GST_END_TEST;
672
673 typedef struct
674 {
675   GMainLoop *loop;
676   GstBuffer *buffer;
677   GError *error;
678 } ConvertFrameContext;
679
680 static void
681 convert_frame_async_callback (GstBuffer * buf, GError * err,
682     ConvertFrameContext * cf_data)
683 {
684   cf_data->buffer = buf;
685   cf_data->error = err;
686
687   g_main_loop_quit (cf_data->loop);
688 }
689
690 GST_START_TEST (test_convert_frame_async)
691 {
692   GstCaps *from_caps, *to_caps;
693   GstBuffer *from_buffer;
694   gint i;
695   guint8 *data;
696   GMainLoop *loop;
697   ConvertFrameContext cf_data = { NULL, NULL, NULL };
698
699   from_buffer = gst_buffer_new_and_alloc (640 * 480 * 4);
700   data = GST_BUFFER_DATA (from_buffer);
701
702   for (i = 0; i < 640 * 480; i++) {
703     data[4 * i + 0] = 0;        /* x */
704     data[4 * i + 1] = 255;      /* R */
705     data[4 * i + 2] = 0;        /* G */
706     data[4 * i + 3] = 0;        /* B */
707   }
708   from_caps = gst_video_format_new_caps (GST_VIDEO_FORMAT_xRGB,
709       640, 480, 25, 1, 1, 1);
710   gst_buffer_set_caps (from_buffer, from_caps);
711
712   to_caps =
713       gst_caps_from_string
714       ("something/that, does=(string)not, exist=(boolean)FALSE");
715
716   loop = cf_data.loop = g_main_loop_new (NULL, FALSE);
717
718   gst_video_convert_frame_async (from_buffer, to_caps, GST_CLOCK_TIME_NONE,
719       (GstVideoConvertFrameCallback) convert_frame_async_callback, &cf_data,
720       NULL);
721
722   g_main_loop_run (loop);
723
724   fail_if (cf_data.buffer != NULL);
725   fail_unless (cf_data.error != NULL);
726   g_error_free (cf_data.error);
727   cf_data.error = NULL;
728
729   gst_caps_unref (to_caps);
730   to_caps =
731       gst_video_format_new_caps (GST_VIDEO_FORMAT_I420, 240, 320, 25, 1, 1, 2);
732   gst_video_convert_frame_async (from_buffer, to_caps, GST_CLOCK_TIME_NONE,
733       (GstVideoConvertFrameCallback) convert_frame_async_callback, &cf_data,
734       NULL);
735   g_main_loop_run (loop);
736   fail_unless (cf_data.buffer != NULL);
737   fail_unless (gst_caps_can_intersect (to_caps,
738           GST_BUFFER_CAPS (cf_data.buffer)));
739   fail_unless (cf_data.error == NULL);
740
741   gst_buffer_unref (from_buffer);
742   gst_caps_unref (from_caps);
743   gst_buffer_unref (cf_data.buffer);
744   gst_caps_unref (to_caps);
745
746   g_main_loop_unref (loop);
747 }
748
749 GST_END_TEST;
750
751 static Suite *
752 video_suite (void)
753 {
754   Suite *s = suite_create ("video support library");
755   TCase *tc_chain = tcase_create ("general");
756
757   suite_add_tcase (s, tc_chain);
758   tcase_add_test (tc_chain, test_video_formats);
759   tcase_add_test (tc_chain, test_video_formats_rgb);
760   tcase_add_test (tc_chain, test_video_template_caps);
761   tcase_add_test (tc_chain, test_dar_calc);
762   tcase_add_test (tc_chain, test_parse_caps_rgb);
763   tcase_add_test (tc_chain, test_events);
764   tcase_add_test (tc_chain, test_convert_frame);
765   tcase_add_test (tc_chain, test_convert_frame_async);
766
767   return s;
768 }
769
770 GST_CHECK_MAIN (video);