0ecf1f5cae1329b91076913a0cbafce4e27e6c1d
[platform/upstream/gstreamer.git] / tests / check / elements / videoscale.c
1 /* GStreamer
2  *
3  * unit test for videoscale
4  *
5  * Copyright (C) <2009,2010> Sebastian Dröge <sebastian.droege@collabora.co.uk>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include <gst/video/video.h>
24 #include <gst/base/gstbasesink.h>
25
26 #include <gst/check/gstcheck.h>
27 #include <string.h>
28
29 /* kids, don't do this at home, skipping checks is *BAD* */
30 #define LINK_CHECK_FLAGS GST_PAD_LINK_CHECK_NOTHING
31
32 #ifndef VSCALE_TEST_GROUP
33
34 static guint
35 get_num_formats (void)
36 {
37   guint i = 2;
38
39   while (gst_video_format_to_string ((GstVideoFormat) i) != NULL)
40     ++i;
41
42   return i;
43 }
44
45 static void
46 check_pad_template (GstPadTemplate * tmpl)
47 {
48   const GValue *list_val, *fmt_val;
49   GstStructure *s;
50   gboolean *formats_supported;
51   GstCaps *caps;
52   guint i, num_formats;
53
54   num_formats = get_num_formats ();
55   formats_supported = g_new0 (gboolean, num_formats);
56
57   caps = gst_pad_template_get_caps (tmpl);
58
59   /* If this fails, we need to update this unit test */
60   fail_unless_equals_int (gst_caps_get_size (caps), 2);
61   /* Remove the ANY caps features structure */
62   caps = gst_caps_truncate (caps);
63   s = gst_caps_get_structure (caps, 0);
64
65   fail_unless (gst_structure_has_name (s, "video/x-raw"));
66
67   list_val = gst_structure_get_value (s, "format");
68   fail_unless (list_val != NULL);
69   /* If this fails, we need to update this unit test */
70   fail_unless (GST_VALUE_HOLDS_LIST (list_val));
71
72   for (i = 0; i < gst_value_list_get_size (list_val); ++i) {
73     GstVideoFormat fmt;
74     const gchar *fmt_str;
75
76     fmt_val = gst_value_list_get_value (list_val, i);
77     fail_unless (G_VALUE_HOLDS_STRING (fmt_val));
78     fmt_str = g_value_get_string (fmt_val);
79     GST_LOG ("format string: '%s'", fmt_str);
80     fmt = gst_video_format_from_string (fmt_str);
81     if (fmt == GST_VIDEO_FORMAT_UNKNOWN)
82       g_error ("Unknown raw format '%s' in pad template caps", fmt_str);
83     formats_supported[(guint) fmt] = TRUE;
84   }
85
86   gst_caps_unref (caps);
87
88   for (i = 2; i < num_formats; ++i) {
89     if (!formats_supported[i]) {
90       const gchar *fmt_str = gst_video_format_to_string ((GstVideoFormat) i);
91
92       switch (i) {
93         case GST_VIDEO_FORMAT_v210:
94         case GST_VIDEO_FORMAT_v216:
95         case GST_VIDEO_FORMAT_NV12:
96         case GST_VIDEO_FORMAT_NV16:
97         case GST_VIDEO_FORMAT_NV21:
98         case GST_VIDEO_FORMAT_NV24:
99         case GST_VIDEO_FORMAT_UYVP:
100         case GST_VIDEO_FORMAT_A420:
101         case GST_VIDEO_FORMAT_YUV9:
102         case GST_VIDEO_FORMAT_YVU9:
103         case GST_VIDEO_FORMAT_IYU1:
104         case GST_VIDEO_FORMAT_r210:{
105           static gboolean shown_fixme[100] = { FALSE, };
106
107           if (!shown_fixme[i]) {
108             GST_FIXME ("FIXME: add %s support to videoscale", fmt_str);
109             shown_fixme[i] = TRUE;
110           }
111           break;
112         }
113         case GST_VIDEO_FORMAT_BGR16:
114         case GST_VIDEO_FORMAT_BGR15:
115         case GST_VIDEO_FORMAT_RGB8P:
116         case GST_VIDEO_FORMAT_I420_10BE:
117         case GST_VIDEO_FORMAT_I420_10LE:
118         case GST_VIDEO_FORMAT_I422_10BE:
119         case GST_VIDEO_FORMAT_I422_10LE:
120         case GST_VIDEO_FORMAT_Y444_10BE:
121         case GST_VIDEO_FORMAT_Y444_10LE:
122         case GST_VIDEO_FORMAT_GBR:
123         case GST_VIDEO_FORMAT_GBR_10BE:
124         case GST_VIDEO_FORMAT_GBR_10LE:
125         case GST_VIDEO_FORMAT_NV12_64Z32:
126           GST_LOG ("Ignoring lack of support for format %s", fmt_str);
127           break;
128         default:
129           g_error ("videoscale doesn't support format '%s'", fmt_str);
130           break;
131       }
132     }
133   }
134
135   g_free (formats_supported);
136 }
137
138 GST_START_TEST (test_template_formats)
139 {
140   GstElementFactory *f;
141   GstPadTemplate *t;
142   const GList *pad_templates;
143
144   f = gst_element_factory_find ("videoscale");
145   fail_unless (f != NULL);
146
147   pad_templates = gst_element_factory_get_static_pad_templates (f);
148   fail_unless_equals_int (g_list_length ((GList *) pad_templates), 2);
149
150   t = gst_static_pad_template_get (pad_templates->data);
151   check_pad_template (GST_PAD_TEMPLATE (t));
152   gst_object_unref (t);
153   t = gst_static_pad_template_get (pad_templates->next->data);
154   check_pad_template (GST_PAD_TEMPLATE (t));
155   gst_object_unref (t);
156
157   gst_object_unref (f);
158 }
159
160 GST_END_TEST;
161
162 #endif /* !defined(VSCALE_TEST_GROUP) */
163
164 static GstCaps **
165 videoscale_get_allowed_caps_for_method (int method)
166 {
167   GstElement *scale;
168   GstCaps *caps, **ret;
169   GstPad *pad;
170   GstStructure *s;
171   gint i, n;
172
173   scale = gst_element_factory_make ("videoscale", "vscale");
174   g_object_set (scale, "method", method, NULL);
175   pad = gst_element_get_static_pad (scale, "sink");
176   caps = gst_pad_query_caps (pad, NULL);
177   gst_object_unref (pad);
178   gst_object_unref (scale);
179
180   caps = gst_caps_normalize (caps);
181   n = gst_caps_get_size (caps);
182   ret = g_new0 (GstCaps *, n + 1);
183
184   for (i = 0; i < n; i++) {
185     s = gst_caps_get_structure (caps, i);
186     ret[i] = gst_caps_new_empty ();
187     gst_caps_append_structure (ret[i], gst_structure_copy (s));
188     GST_LOG ("method %d supports: %" GST_PTR_FORMAT, method, s);
189   }
190
191   gst_caps_unref (caps);
192
193   return ret;
194 }
195
196 static void
197 on_sink_handoff (GstElement * element, GstBuffer * buffer, GstPad * pad,
198     gpointer user_data)
199 {
200   guint *n_buffers = user_data;
201
202   *n_buffers = *n_buffers + 1;
203 }
204
205 static gboolean
206 videoconvert_supports_caps (const GstCaps * caps)
207 {
208   GST_DEBUG ("have caps %" GST_PTR_FORMAT, caps);
209   return TRUE;
210 }
211
212 static void
213 run_test (const GstCaps * caps, gint src_width, gint src_height,
214     gint dest_width, gint dest_height, gint method,
215     GCallback src_handoff, gpointer src_handoff_user_data,
216     GCallback sink_handoff, gpointer sink_handoff_user_data)
217 {
218   GstElement *pipeline;
219   GstElement *src, *videoconvert, *capsfilter1, *identity, *scale,
220       *capsfilter2, *sink;
221   GstMessage *msg;
222   GstBus *bus;
223   GstCaps *copy;
224   guint n_buffers = 0;
225
226   /* skip formats that videoconvert can't handle */
227   if (!videoconvert_supports_caps (caps))
228     return;
229
230   pipeline = gst_element_factory_make ("pipeline", "pipeline");
231   fail_unless (pipeline != NULL);
232
233   src = gst_element_factory_make ("videotestsrc", "src");
234   fail_unless (src != NULL);
235   g_object_set (G_OBJECT (src), "num-buffers", 1, NULL);
236
237   videoconvert = gst_element_factory_make ("videoconvert", "csp");
238   fail_unless (videoconvert != NULL);
239
240   capsfilter1 = gst_element_factory_make ("capsfilter", "filter1");
241   fail_unless (capsfilter1 != NULL);
242   copy = gst_caps_copy (caps);
243   gst_caps_set_simple (copy, "width", G_TYPE_INT, src_width, "height",
244       G_TYPE_INT, src_height, "framerate", GST_TYPE_FRACTION, 30, 1, NULL);
245   g_object_set (G_OBJECT (capsfilter1), "caps", copy, NULL);
246   gst_caps_unref (copy);
247
248   identity = gst_element_factory_make ("identity", "identity");
249   fail_unless (identity != NULL);
250   if (src_handoff) {
251     g_object_set (G_OBJECT (identity), "signal-handoffs", TRUE, NULL);
252     g_signal_connect (identity, "handoff", G_CALLBACK (src_handoff),
253         src_handoff_user_data);
254   }
255
256   scale = gst_element_factory_make ("videoscale", "scale");
257   fail_unless (scale != NULL);
258   g_object_set (G_OBJECT (scale), "method", method, NULL);
259
260   capsfilter2 = gst_element_factory_make ("capsfilter", "filter2");
261   fail_unless (capsfilter2 != NULL);
262   copy = gst_caps_copy (caps);
263   gst_caps_set_simple (copy, "width", G_TYPE_INT, dest_width, "height",
264       G_TYPE_INT, dest_height, NULL);
265   g_object_set (G_OBJECT (capsfilter2), "caps", copy, NULL);
266   gst_caps_unref (copy);
267
268   sink = gst_element_factory_make ("fakesink", "sink");
269   fail_unless (sink != NULL);
270   g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, "async", FALSE, NULL);
271   g_signal_connect (sink, "handoff", G_CALLBACK (on_sink_handoff), &n_buffers);
272   if (sink_handoff) {
273     g_signal_connect (sink, "handoff", G_CALLBACK (sink_handoff),
274         sink_handoff_user_data);
275   }
276
277   gst_bin_add_many (GST_BIN (pipeline), src, videoconvert, capsfilter1,
278       identity, scale, capsfilter2, sink, NULL);
279
280   fail_unless (gst_element_link_pads_full (src, "src", videoconvert, "sink",
281           LINK_CHECK_FLAGS));
282   fail_unless (gst_element_link_pads_full (videoconvert, "src", capsfilter1,
283           "sink", LINK_CHECK_FLAGS));
284   fail_unless (gst_element_link_pads_full (capsfilter1, "src", identity, "sink",
285           LINK_CHECK_FLAGS));
286   fail_unless (gst_element_link_pads_full (identity, "src", scale, "sink",
287           LINK_CHECK_FLAGS));
288   fail_unless (gst_element_link_pads_full (scale, "src", capsfilter2, "sink",
289           LINK_CHECK_FLAGS));
290   fail_unless (gst_element_link_pads_full (capsfilter2, "src", sink, "sink",
291           LINK_CHECK_FLAGS));
292
293   bus = gst_element_get_bus (pipeline);
294   fail_unless (bus != NULL);
295
296   fail_unless (gst_element_set_state (pipeline,
297           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
298
299   msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
300       GST_MESSAGE_EOS | GST_MESSAGE_ERROR | GST_MESSAGE_WARNING);
301
302   fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_EOS);
303
304   fail_unless (gst_element_set_state (pipeline,
305           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
306
307   fail_unless (n_buffers == 1);
308
309   gst_object_unref (pipeline);
310   gst_message_unref (msg);
311   gst_object_unref (bus);
312 }
313
314 #ifndef VSCALE_TEST_GROUP
315
316 static void
317 on_sink_handoff_passthrough (GstElement * element, GstBuffer * buffer,
318     GstPad * pad, gpointer user_data)
319 {
320   GList **list = user_data;
321
322   *list = g_list_prepend (*list, gst_buffer_ref (buffer));
323 }
324
325 static void
326 on_src_handoff_passthrough (GstElement * element, GstBuffer * buffer,
327     gpointer user_data)
328 {
329   GList **list = user_data;
330
331   *list = g_list_prepend (*list, gst_buffer_ref (buffer));
332 }
333
334 static void
335 test_passthrough (int method)
336 {
337   GList *l1, *l2, *src_buffers = NULL, *sink_buffers = NULL;
338   GstCaps **allowed_caps = NULL, **p;
339   static const gint src_width = 640, src_height = 480;
340   static const gint dest_width = 640, dest_height = 480;
341
342   p = allowed_caps = videoscale_get_allowed_caps_for_method (method);
343
344   while (*p) {
345     GstCaps *caps = *p;
346
347     /* skip formats that videoconvert can't handle */
348     if (!videoconvert_supports_caps (caps))
349       goto next;
350
351     GST_DEBUG ("Running test for caps '%" GST_PTR_FORMAT "'"
352         " from %dx%u to %dx%d with method %d", caps, src_width, src_height,
353         dest_width, dest_height, method);
354     run_test (caps, src_width, src_height,
355         dest_width, dest_height, method,
356         G_CALLBACK (on_src_handoff_passthrough), &src_buffers,
357         G_CALLBACK (on_sink_handoff_passthrough), &sink_buffers);
358
359     fail_unless (src_buffers && sink_buffers);
360     fail_unless_equals_int (g_list_length (src_buffers),
361         g_list_length (sink_buffers));
362
363     for (l1 = src_buffers, l2 = sink_buffers; l1 && l2;
364         l1 = l1->next, l2 = l2->next) {
365       GstBuffer *a = l1->data;
366       GstBuffer *b = l2->data;
367       GstMapInfo mapa, mapb;
368
369       gst_buffer_map (a, &mapa, GST_MAP_READ);
370       gst_buffer_map (b, &mapb, GST_MAP_READ);
371       fail_unless_equals_int (mapa.size, mapb.size);
372       fail_unless (mapa.data == mapb.data);
373       gst_buffer_unmap (b, &mapb);
374       gst_buffer_unmap (a, &mapa);
375
376       gst_buffer_unref (a);
377       gst_buffer_unref (b);
378     }
379     g_list_free (src_buffers);
380     src_buffers = NULL;
381     g_list_free (sink_buffers);
382     sink_buffers = NULL;
383
384   next:
385     gst_caps_unref (caps);
386     p++;
387   }
388   g_free (allowed_caps);
389 }
390
391 GST_START_TEST (test_passthrough_method_0)
392 {
393   test_passthrough (0);
394 }
395
396 GST_END_TEST;
397
398 GST_START_TEST (test_passthrough_method_1)
399 {
400   test_passthrough (1);
401 }
402
403 GST_END_TEST;
404
405 GST_START_TEST (test_passthrough_method_2)
406 {
407   test_passthrough (2);
408 }
409
410 GST_END_TEST;
411
412 GST_START_TEST (test_passthrough_method_3)
413 {
414   test_passthrough (3);
415 }
416
417 GST_END_TEST;
418 #endif /* !defined(VSCALE_TEST_GROUP) */
419
420 #define CREATE_TEST(name,method,src_width,src_height,dest_width,dest_height) \
421 GST_START_TEST (name) \
422 { \
423   GstCaps **allowed_caps = NULL, **p; \
424   \
425   p = allowed_caps = videoscale_get_allowed_caps_for_method (method); \
426   \
427   while (*p) { \
428     GstCaps *caps = *p; \
429     \
430     GST_DEBUG ("Running test for caps '%" GST_PTR_FORMAT "'" \
431         " from %dx%u to %dx%d with method %d", caps, src_width, src_height, \
432         dest_width, dest_height, method); \
433     run_test (caps, src_width, src_height, \
434         dest_width, dest_height, method, \
435         NULL, NULL, NULL, NULL); \
436     gst_caps_unref (caps); \
437     p++; \
438   } \
439   g_free (allowed_caps); \
440 } \
441 \
442 GST_END_TEST;
443
444 #if defined(VSCALE_TEST_GROUP) && VSCALE_TEST_GROUP == 1
445 CREATE_TEST (test_downscale_640x480_320x240_method_0, 0, 640, 480, 320, 240);
446 CREATE_TEST (test_downscale_640x480_320x240_method_1, 1, 640, 480, 320, 240);
447 CREATE_TEST (test_downscale_640x480_320x240_method_2, 2, 640, 480, 320, 240);
448 CREATE_TEST (test_downscale_640x480_320x240_method_3, 3, 640, 480, 320, 240);
449 CREATE_TEST (test_upscale_320x240_640x480_method_0, 0, 320, 240, 640, 480);
450 CREATE_TEST (test_upscale_320x240_640x480_method_1, 1, 320, 240, 640, 480);
451 CREATE_TEST (test_upscale_320x240_640x480_method_2, 2, 320, 240, 640, 480);
452 CREATE_TEST (test_upscale_320x240_640x480_method_3, 3, 320, 240, 640, 480);
453 #elif defined(VSCALE_TEST_GROUP) && VSCALE_TEST_GROUP == 2
454 CREATE_TEST (test_downscale_640x480_1x1_method_0, 0, 640, 480, 1, 1);
455 CREATE_TEST (test_downscale_640x480_1x1_method_1, 1, 640, 480, 1, 1);
456 CREATE_TEST (test_downscale_640x480_1x1_method_2, 2, 640, 480, 1, 1);
457 CREATE_TEST (test_downscale_640x480_1x1_method_3, 3, 640, 480, 1, 1);
458 CREATE_TEST (test_upscale_1x1_640x480_method_0, 0, 1, 1, 640, 480);
459 CREATE_TEST (test_upscale_1x1_640x480_method_1, 1, 1, 1, 640, 480);
460 CREATE_TEST (test_upscale_1x1_640x480_method_2, 2, 1, 1, 640, 480);
461 CREATE_TEST (test_upscale_1x1_640x480_method_3, 3, 1, 1, 640, 480);
462 #elif defined(VSCALE_TEST_GROUP) && VSCALE_TEST_GROUP == 3
463 CREATE_TEST (test_downscale_641x481_111x30_method_0, 0, 641, 481, 111, 30);
464 CREATE_TEST (test_downscale_641x481_111x30_method_1, 1, 641, 481, 111, 30);
465 CREATE_TEST (test_downscale_641x481_111x30_method_2, 2, 641, 481, 111, 30);
466 CREATE_TEST (test_downscale_641x481_111x30_method_3, 3, 641, 481, 111, 30);
467 CREATE_TEST (test_upscale_111x30_641x481_method_0, 0, 111, 30, 641, 481);
468 CREATE_TEST (test_upscale_111x30_641x481_method_1, 1, 111, 30, 641, 481);
469 CREATE_TEST (test_upscale_111x30_641x481_method_2, 2, 111, 30, 641, 481);
470 CREATE_TEST (test_upscale_111x30_641x481_method_3, 2, 111, 30, 641, 481);
471 #elif defined(VSCALE_TEST_GROUP) && VSCALE_TEST_GROUP == 4
472 CREATE_TEST (test_downscale_641x481_30x111_method_0, 0, 641, 481, 30, 111);
473 CREATE_TEST (test_downscale_641x481_30x111_method_1, 1, 641, 481, 30, 111);
474 CREATE_TEST (test_downscale_641x481_30x111_method_2, 2, 641, 481, 30, 111);
475 CREATE_TEST (test_downscale_641x481_30x111_method_3, 3, 641, 481, 30, 111);
476 CREATE_TEST (test_upscale_30x111_641x481_method_0, 0, 30, 111, 641, 481);
477 CREATE_TEST (test_upscale_30x111_641x481_method_1, 1, 30, 111, 641, 481);
478 CREATE_TEST (test_upscale_30x111_641x481_method_2, 2, 30, 111, 641, 481);
479 CREATE_TEST (test_upscale_30x111_641x481_method_3, 3, 30, 111, 641, 481);
480 #elif defined(VSCALE_TEST_GROUP) && VSCALE_TEST_GROUP == 5
481 CREATE_TEST (test_downscale_640x480_320x1_method_0, 0, 640, 480, 320, 1);
482 CREATE_TEST (test_downscale_640x480_320x1_method_1, 1, 640, 480, 320, 1);
483 CREATE_TEST (test_downscale_640x480_320x1_method_2, 2, 640, 480, 320, 1);
484 CREATE_TEST (test_downscale_640x480_320x1_method_3, 3, 640, 480, 320, 1);
485 CREATE_TEST (test_upscale_320x1_640x480_method_0, 0, 320, 1, 640, 480);
486 CREATE_TEST (test_upscale_320x1_640x480_method_1, 1, 320, 1, 640, 480);
487 CREATE_TEST (test_upscale_320x1_640x480_method_2, 2, 320, 1, 640, 480);
488 CREATE_TEST (test_upscale_320x1_640x480_method_3, 3, 320, 1, 640, 480);
489 #elif defined(VSCALE_TEST_GROUP) && VSCALE_TEST_GROUP == 6
490 CREATE_TEST (test_downscale_640x480_1x240_method_0, 0, 640, 480, 1, 240);
491 CREATE_TEST (test_downscale_640x480_1x240_method_1, 1, 640, 480, 1, 240);
492 CREATE_TEST (test_downscale_640x480_1x240_method_2, 2, 640, 480, 1, 240);
493 CREATE_TEST (test_downscale_640x480_1x240_method_3, 3, 640, 480, 1, 240);
494 CREATE_TEST (test_upscale_1x240_640x480_method_0, 0, 1, 240, 640, 480);
495 CREATE_TEST (test_upscale_1x240_640x480_method_1, 1, 1, 240, 640, 480);
496 CREATE_TEST (test_upscale_1x240_640x480_method_2, 2, 1, 240, 640, 480);
497 CREATE_TEST (test_upscale_1x240_640x480_method_3, 3, 1, 240, 640, 480);
498 #endif
499
500 #ifndef VSCALE_TEST_GROUP
501
502 static void
503 _test_negotiation (const gchar * src_templ, const gchar * sink_templ,
504     gint width, gint height, gint par_n, gint par_d)
505 {
506   GstElement *pipeline;
507   GstElement *src, *capsfilter1, *scale, *capsfilter2, *sink;
508   GstCaps *caps;
509   GstPad *pad;
510
511   GST_DEBUG ("Running test for src templ caps '%s' and sink templ caps '%s'",
512       src_templ, sink_templ);
513
514   pipeline = gst_element_factory_make ("pipeline", "pipeline");
515   fail_unless (pipeline != NULL);
516
517   src = gst_element_factory_make ("videotestsrc", "src");
518   fail_unless (src != NULL);
519   g_object_set (G_OBJECT (src), "num-buffers", 1, "pattern", 2, NULL);
520
521   capsfilter1 = gst_element_factory_make ("capsfilter", "filter1");
522   fail_unless (capsfilter1 != NULL);
523   caps = gst_caps_from_string (src_templ);
524   fail_unless (caps != NULL);
525   g_object_set (G_OBJECT (capsfilter1), "caps", caps, NULL);
526   gst_caps_unref (caps);
527
528   scale = gst_element_factory_make ("videoscale", "scale");
529   fail_unless (scale != NULL);
530
531   capsfilter2 = gst_element_factory_make ("capsfilter", "filter2");
532   fail_unless (capsfilter2 != NULL);
533   caps = gst_caps_from_string (sink_templ);
534   fail_unless (caps != NULL);
535   g_object_set (G_OBJECT (capsfilter2), "caps", caps, NULL);
536   gst_caps_unref (caps);
537
538   sink = gst_element_factory_make ("fakesink", "sink");
539   fail_unless (sink != NULL);
540
541   gst_bin_add_many (GST_BIN (pipeline), src, capsfilter1, scale, capsfilter2,
542       sink, NULL);
543
544   fail_unless (gst_element_link_pads_full (src, "src", capsfilter1, "sink",
545           LINK_CHECK_FLAGS));
546   fail_unless (gst_element_link_pads_full (capsfilter1, "src", scale, "sink",
547           LINK_CHECK_FLAGS));
548   fail_unless (gst_element_link_pads_full (scale, "src", capsfilter2, "sink",
549           LINK_CHECK_FLAGS));
550   fail_unless (gst_element_link_pads_full (capsfilter2, "src", sink, "sink",
551           LINK_CHECK_FLAGS));
552
553   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED),
554       GST_STATE_CHANGE_ASYNC);
555
556   /* Wait for pipeline to preroll, at which point negotiation is finished */
557   fail_unless_equals_int (gst_element_get_state (pipeline, NULL, NULL, -1),
558       GST_STATE_CHANGE_SUCCESS);
559
560   /* Get negotiated caps */
561   pad = gst_element_get_static_pad (capsfilter2, "sink");
562   fail_unless (pad != NULL);
563   caps = gst_pad_get_current_caps (pad);
564   fail_unless (caps != NULL);
565   gst_object_unref (pad);
566
567   /* Check negotiated caps */
568   {
569     gint out_par_n = 0, out_par_d = 0;
570     gint out_width, out_height;
571     GstStructure *s;
572
573     s = gst_caps_get_structure (caps, 0);
574
575     fail_unless (gst_structure_get_int (s, "width", &out_width));
576     fail_unless (gst_structure_get_int (s, "height", &out_height));
577     fail_unless (gst_structure_get_fraction (s, "pixel-aspect-ratio",
578             &out_par_n, &out_par_d) || (par_n == 1 && par_d == 1));
579
580     fail_unless_equals_int (width, out_width);
581     fail_unless_equals_int (height, out_height);
582     if (par_n != 0 || par_d != 0) {
583       fail_unless_equals_int (par_n, out_par_n);
584       fail_unless_equals_int (par_d, out_par_d);
585     }
586   }
587   gst_caps_unref (caps);
588
589   /* clean up */
590   fail_unless (gst_element_set_state (pipeline,
591           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
592
593   gst_object_unref (pipeline);
594 }
595
596 GST_START_TEST (test_negotiation)
597 {
598   _test_negotiation
599       ("video/x-raw,format=(string)AYUV,width=720,height=576,pixel-aspect-ratio=16/15",
600       "video/x-raw,format=(string)AYUV,width=768,height=576", 768, 576, 1, 1);
601
602   _test_negotiation
603       ("video/x-raw,format=(string)AYUV,width=320,height=240",
604       "video/x-raw,format=(string)AYUV,width=640,height=320", 640, 320, 2, 3);
605
606   _test_negotiation
607       ("video/x-raw,format=(string)AYUV,width=320,height=240",
608       "video/x-raw,format=(string)AYUV,width=640,height=320,pixel-aspect-ratio=[0/1, 1/1]",
609       640, 320, 2, 3);
610
611   _test_negotiation
612       ("video/x-raw,format=(string)AYUV,width=1920,height=2560,pixel-aspect-ratio=1/1",
613       "video/x-raw,format=(string)AYUV,width=[1, 2048],height=[1, 2048],pixel-aspect-ratio=1/1",
614       1536, 2048, 1, 1);
615
616   _test_negotiation
617       ("video/x-raw,format=(string)AYUV,width=1920,height=2560,pixel-aspect-ratio=1/1",
618       "video/x-raw,format=(string)AYUV,width=[1, 2048],height=[1, 2048]",
619       1920, 2048, 4, 5);
620
621   _test_negotiation
622       ("video/x-raw,format=(string)AYUV,width=1920,height=2560",
623       "video/x-raw,format=(string)AYUV,width=[1, 2048],height=[1, 2048]",
624       1920, 2048, 4, 5);
625
626   _test_negotiation
627       ("video/x-raw,format=(string)AYUV,width=1920,height=2560",
628       "video/x-raw,format=(string)AYUV,width=1200,height=[1, 2048],pixel-aspect-ratio=1/1",
629       1200, 1600, 1, 1);
630
631   /* Doesn't keep DAR but must be possible! */
632   _test_negotiation
633       ("video/x-raw,format=(string)AYUV,width=320,height=240,pixel-aspect-ratio=1/1",
634       "video/x-raw,format=(string)AYUV,width=200,height=200,pixel-aspect-ratio=1/2",
635       200, 200, 1, 2);
636
637   _test_negotiation
638       ("video/x-raw,format=(string)AYUV,width=854,height=480",
639       "video/x-raw,format=(string)AYUV,width=[2, 512, 2],height=[2, 512, 2],pixel-aspect-ratio=1/1",
640       512, 288, 1, 1);
641 }
642
643 GST_END_TEST;
644
645 #define GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK \
646   (gst_test_reverse_negotiation_sink_get_type())
647 #define GST_TEST_REVERSE_NEGOTIATION_SINK(obj) \
648   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK,GstTestReverseNegotiationSink))
649 #define GST_TEST_REVERSE_NEGOTIATION_SINK_CLASS(klass) \
650   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK,GstTestReverseNegotiationSinkClass))
651 #define GST_IS_TEST_REVERSE_NEGOTIATION_SINK(obj) \
652   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK))
653 #define GST_IS_TEST_REVERSE_NEGOTIATION_SINK_CLASS(klass) \
654   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK))
655 #define GST_TEST_REVERSE_NEGOTIATION_SINK_CAST(obj) ((GstTestReverseNegotiationSink *)obj)
656
657 typedef struct _GstTestReverseNegotiationSink GstTestReverseNegotiationSink;
658 typedef struct _GstTestReverseNegotiationSinkClass
659     GstTestReverseNegotiationSinkClass;
660 struct _GstTestReverseNegotiationSink
661 {
662   GstBaseSink element;
663   gint nbuffers;
664 };
665
666 struct _GstTestReverseNegotiationSinkClass
667 {
668   GstBaseSinkClass parent_class;
669 };
670
671 GType gst_test_reverse_negotiation_sink_get_type (void);
672
673 G_DEFINE_TYPE (GstTestReverseNegotiationSink,
674     gst_test_reverse_negotiation_sink, GST_TYPE_BASE_SINK);
675
676 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
677     GST_PAD_SINK,
678     GST_PAD_ALWAYS,
679     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("xRGB")));
680
681 #if 0
682 static GstFlowReturn
683 gst_test_reverse_negotiation_sink_buffer_alloc (GstBaseSink * bsink,
684     guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf)
685 {
686   GstTestReverseNegotiationSink *sink =
687       GST_TEST_REVERSE_NEGOTIATION_SINK (bsink);
688   GstVideoFormat fmt;
689   gint width, height;
690
691   fail_unless (gst_video_format_parse_caps (caps, &fmt, &width, &height));
692
693   if (sink->nbuffers < 2) {
694     *buf =
695         gst_buffer_new_and_alloc (gst_video_format_get_size (fmt, width,
696             height));
697     gst_buffer_set_caps (*buf, caps);
698   } else {
699     gint fps_n, fps_d;
700
701     fail_unless (gst_video_parse_caps_framerate (caps, &fps_n, &fps_d));
702
703     width = 512;
704     height = 128;
705     *buf =
706         gst_buffer_new_and_alloc (gst_video_format_get_size (fmt, width,
707             height));
708     caps = gst_video_format_new_caps (fmt, width, height, fps_n, fps_d, 1, 1);
709     gst_buffer_set_caps (*buf, caps);
710     gst_caps_unref (caps);
711   }
712
713   return GST_FLOW_OK;
714 }
715 #endif
716
717 static GstFlowReturn
718 gst_test_reverse_negotiation_sink_render (GstBaseSink * bsink,
719     GstBuffer * buffer)
720 {
721   GstTestReverseNegotiationSink *sink =
722       GST_TEST_REVERSE_NEGOTIATION_SINK (bsink);
723   GstCaps *caps;
724   GstVideoInfo info;
725
726   caps = gst_pad_get_current_caps (GST_BASE_SINK_PAD (bsink));
727
728   fail_unless (caps != NULL);
729   fail_unless (gst_video_info_from_caps (&info, caps));
730
731   sink->nbuffers++;
732
733   /* The third buffer is still in the old size
734    * because the videoconverts can't convert
735    * the frame sizes
736    */
737   if (sink->nbuffers > 3) {
738     fail_unless_equals_int (GST_VIDEO_INFO_WIDTH (&info), 512);
739     fail_unless_equals_int (GST_VIDEO_INFO_HEIGHT (&info), 128);
740   }
741
742   gst_caps_unref (caps);
743
744   return GST_FLOW_OK;
745 }
746
747 static void
748 gst_test_reverse_negotiation_sink_class_init (GstTestReverseNegotiationSinkClass
749     * klass)
750 {
751   GstElementClass *gstelement_class;
752   GstBaseSinkClass *gstbase_sink_class;
753
754   gstelement_class = GST_ELEMENT_CLASS (klass);
755   gstbase_sink_class = GST_BASE_SINK_CLASS (klass);
756
757   gst_element_class_set_metadata (gstelement_class,
758       "Test Reverse Negotiation Sink",
759       "Sink",
760       "Some test sink", "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
761   gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
762
763 #if 0
764   gstbase_sink_class->buffer_alloc =
765       GST_DEBUG_FUNCPTR (gst_test_reverse_negotiation_sink_buffer_alloc);
766 #endif
767   gstbase_sink_class->render =
768       GST_DEBUG_FUNCPTR (gst_test_reverse_negotiation_sink_render);
769 }
770
771 static void
772 gst_test_reverse_negotiation_sink_init (GstTestReverseNegotiationSink * sink)
773 {
774   sink->nbuffers = 0;
775 }
776
777 #if 0
778 static void
779 _test_reverse_negotiation_message (GstBus * bus, GstMessage * message,
780     GMainLoop * loop)
781 {
782   GError *err = NULL;
783   gchar *debug;
784
785   switch (GST_MESSAGE_TYPE (message)) {
786     case GST_MESSAGE_ERROR:
787       gst_message_parse_error (message, &err, &debug);
788       gst_object_default_error (GST_MESSAGE_SRC (message), err, debug);
789       g_error_free (err);
790       g_free (debug);
791       g_assert_not_reached ();
792       break;
793     case GST_MESSAGE_WARNING:
794       gst_message_parse_warning (message, &err, &debug);
795       gst_object_default_error (GST_MESSAGE_SRC (message), err, debug);
796       g_error_free (err);
797       g_free (debug);
798       g_assert_not_reached ();
799       break;
800     case GST_MESSAGE_EOS:
801       g_main_loop_quit (loop);
802       break;
803     default:
804       break;
805   }
806 }
807 #endif
808
809 #if 0
810 GST_START_TEST (test_reverse_negotiation)
811 {
812   GstElement *pipeline;
813   GstElement *src, *csp1, *scale, *csp2, *sink;
814   GstBus *bus;
815   GMainLoop *loop;
816
817   pipeline = gst_element_factory_make ("pipeline", "pipeline");
818   fail_unless (pipeline != NULL);
819
820   src = gst_element_factory_make ("videotestsrc", "src");
821   fail_unless (src != NULL);
822   g_object_set (G_OBJECT (src), "num-buffers", 8, NULL);
823
824   csp1 = gst_element_factory_make ("videoconvert", "csp1");
825   fail_unless (csp1 != NULL);
826
827   scale = gst_element_factory_make ("videoscale", "scale");
828   fail_unless (scale != NULL);
829
830   csp2 = gst_element_factory_make ("videoconvert", "csp2");
831   fail_unless (csp2 != NULL);
832
833   sink = g_object_new (GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK, NULL);
834   fail_unless (sink != NULL);
835   g_object_set (sink, "async", FALSE, NULL);
836
837   gst_bin_add_many (GST_BIN (pipeline), src, csp1, scale, csp2, sink, NULL);
838
839   fail_unless (gst_element_link_pads_full (src, "src", csp1, "sink",
840           LINK_CHECK_FLAGS));
841   fail_unless (gst_element_link_pads_full (csp1, "src", scale, "sink",
842           LINK_CHECK_FLAGS));
843   fail_unless (gst_element_link_pads_full (scale, "src", csp2, "sink",
844           LINK_CHECK_FLAGS));
845   fail_unless (gst_element_link_pads_full (csp2, "src", sink, "sink",
846           LINK_CHECK_FLAGS));
847
848   loop = g_main_loop_new (NULL, FALSE);
849
850   bus = gst_element_get_bus (pipeline);
851   fail_unless (bus != NULL);
852   gst_bus_add_signal_watch (bus);
853
854   g_signal_connect (bus, "message",
855       G_CALLBACK (_test_reverse_negotiation_message), loop);
856
857   gst_object_unref (bus);
858
859   fail_unless (gst_element_set_state (pipeline,
860           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
861
862   g_main_loop_run (loop);
863
864   fail_unless (gst_element_set_state (pipeline,
865           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
866
867   gst_object_unref (pipeline);
868   g_main_loop_unref (loop);
869 }
870
871 GST_END_TEST;
872 #endif
873
874 GST_START_TEST (test_basetransform_negotiation)
875 {
876   GstElement *pipeline, *src, *sink, *scale, *capsfilter1, *capsfilter2;
877   GstMessage *msg;
878   GstCaps *caps;
879
880   pipeline = gst_pipeline_new (NULL);
881   src = gst_element_factory_make ("videotestsrc", NULL);
882   capsfilter1 = gst_element_factory_make ("capsfilter", NULL);
883   scale = gst_element_factory_make ("videoscale", NULL);
884   capsfilter2 = gst_element_factory_make ("capsfilter", NULL);
885   sink = gst_element_factory_make ("fakesink", NULL);
886   fail_unless (pipeline && src && capsfilter1 && scale && capsfilter2 && sink);
887
888   g_object_set (src, "num-buffers", 3, NULL);
889
890   caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
891       "UYVY", "width", G_TYPE_INT, 352,
892       "height", G_TYPE_INT, 288, "framerate", GST_TYPE_FRACTION, 30, 1,
893       "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
894   g_object_set (capsfilter1, "caps", caps, NULL);
895   gst_caps_unref (caps);
896
897   /* same caps, just different pixel-aspect-ratio */
898   caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
899       "UYVY", "width", G_TYPE_INT, 352,
900       "height", G_TYPE_INT, 288, "framerate", GST_TYPE_FRACTION, 30, 1,
901       "pixel-aspect-ratio", GST_TYPE_FRACTION, 12, 11, NULL);
902   g_object_set (capsfilter2, "caps", caps, NULL);
903   gst_caps_unref (caps);
904
905   gst_bin_add_many (GST_BIN (pipeline), src, capsfilter1, scale, capsfilter2,
906       sink, NULL);
907   fail_unless (gst_element_link_many (src, capsfilter1, scale, capsfilter2,
908           sink, NULL));
909
910   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
911       GST_STATE_CHANGE_ASYNC);
912
913   msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipeline), -1,
914       GST_MESSAGE_EOS | GST_MESSAGE_ERROR);
915   fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_EOS);
916   gst_message_unref (msg);
917
918   gst_element_set_state (pipeline, GST_STATE_NULL);
919   gst_object_unref (pipeline);
920 }
921
922 GST_END_TEST;
923
924 #endif /* !defined(VSCALE_TEST_GROUP) */
925
926 static Suite *
927 videoscale_suite (void)
928 {
929   Suite *s = suite_create ("videoscale");
930   TCase *tc_chain = tcase_create ("general");
931
932   suite_add_tcase (s, tc_chain);
933   tcase_set_timeout (tc_chain, 180);
934 #ifndef VSCALE_TEST_GROUP
935   tcase_add_test (tc_chain, test_template_formats);
936   tcase_add_test (tc_chain, test_passthrough_method_0);
937   tcase_add_test (tc_chain, test_passthrough_method_1);
938   tcase_add_test (tc_chain, test_passthrough_method_2);
939   tcase_add_test (tc_chain, test_passthrough_method_3);
940   tcase_add_test (tc_chain, test_negotiation);
941 #if 0
942   tcase_add_test (tc_chain, test_reverse_negotiation);
943 #endif
944   tcase_add_test (tc_chain, test_basetransform_negotiation);
945 #elif VSCALE_TEST_GROUP == 1
946   tcase_add_test (tc_chain, test_downscale_640x480_320x240_method_0);
947   tcase_add_test (tc_chain, test_downscale_640x480_320x240_method_1);
948   tcase_add_test (tc_chain, test_downscale_640x480_320x240_method_2);
949   tcase_add_test (tc_chain, test_downscale_640x480_320x240_method_3);
950   tcase_add_test (tc_chain, test_upscale_320x240_640x480_method_0);
951   tcase_add_test (tc_chain, test_upscale_320x240_640x480_method_1);
952   tcase_add_test (tc_chain, test_upscale_320x240_640x480_method_2);
953   tcase_add_test (tc_chain, test_upscale_320x240_640x480_method_3);
954 #elif VSCALE_TEST_GROUP == 2
955   tcase_add_test (tc_chain, test_downscale_640x480_1x1_method_0);
956   tcase_add_test (tc_chain, test_downscale_640x480_1x1_method_1);
957   tcase_add_test (tc_chain, test_downscale_640x480_1x1_method_2);
958   tcase_skip_broken_test (tc_chain, test_downscale_640x480_1x1_method_3);
959   tcase_add_test (tc_chain, test_upscale_1x1_640x480_method_0);
960   tcase_add_test (tc_chain, test_upscale_1x1_640x480_method_1);
961   tcase_add_test (tc_chain, test_upscale_1x1_640x480_method_2);
962   tcase_add_test (tc_chain, test_upscale_1x1_640x480_method_3);
963 #elif VSCALE_TEST_GROUP == 3
964   tcase_add_test (tc_chain, test_downscale_641x481_111x30_method_0);
965   tcase_add_test (tc_chain, test_downscale_641x481_111x30_method_1);
966   tcase_add_test (tc_chain, test_downscale_641x481_111x30_method_2);
967   tcase_add_test (tc_chain, test_downscale_641x481_111x30_method_3);
968   tcase_add_test (tc_chain, test_upscale_111x30_641x481_method_0);
969   tcase_add_test (tc_chain, test_upscale_111x30_641x481_method_1);
970   tcase_add_test (tc_chain, test_upscale_111x30_641x481_method_2);
971   tcase_add_test (tc_chain, test_upscale_111x30_641x481_method_3);
972 #elif VSCALE_TEST_GROUP == 4
973   tcase_add_test (tc_chain, test_downscale_641x481_30x111_method_0);
974   tcase_add_test (tc_chain, test_downscale_641x481_30x111_method_1);
975   tcase_add_test (tc_chain, test_downscale_641x481_30x111_method_2);
976   tcase_add_test (tc_chain, test_downscale_641x481_30x111_method_3);
977   tcase_add_test (tc_chain, test_upscale_30x111_641x481_method_0);
978   tcase_add_test (tc_chain, test_upscale_30x111_641x481_method_1);
979   tcase_add_test (tc_chain, test_upscale_30x111_641x481_method_2);
980   tcase_add_test (tc_chain, test_upscale_30x111_641x481_method_3);
981 #elif VSCALE_TEST_GROUP == 5
982   tcase_add_test (tc_chain, test_downscale_640x480_320x1_method_0);
983   tcase_add_test (tc_chain, test_downscale_640x480_320x1_method_1);
984   tcase_add_test (tc_chain, test_downscale_640x480_320x1_method_2);
985   tcase_skip_broken_test (tc_chain, test_downscale_640x480_320x1_method_3);
986   tcase_add_test (tc_chain, test_upscale_320x1_640x480_method_0);
987   tcase_add_test (tc_chain, test_upscale_320x1_640x480_method_1);
988   tcase_add_test (tc_chain, test_upscale_320x1_640x480_method_2);
989   tcase_skip_broken_test (tc_chain, test_upscale_320x1_640x480_method_3);
990 #elif VSCALE_TEST_GROUP == 6
991   tcase_add_test (tc_chain, test_downscale_640x480_1x240_method_0);
992   tcase_add_test (tc_chain, test_downscale_640x480_1x240_method_1);
993   tcase_add_test (tc_chain, test_downscale_640x480_1x240_method_2);
994   tcase_skip_broken_test (tc_chain, test_downscale_640x480_1x240_method_3);
995   tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_0);
996   tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_1);
997   tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_2);
998   tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_3);
999 #endif
1000
1001   return s;
1002 }
1003
1004 /* NOTE:
1005  * We need to do the filename dance below in order to avoid having
1006  * multiple parallel tests (identified by VSCALE_TEST_GROUP) going
1007  * to the same output xml file (when using GST_CHECK_XML) */
1008 int
1009 main (int argc, char **argv)
1010 {
1011   Suite *s;
1012
1013   gst_check_init (&argc, &argv);
1014   s = videoscale_suite ();
1015 #ifndef VSCALE_TEST_GROUP
1016 #define FULL_RUN_NAME __FILE__
1017 #else
1018 #define STR_HELPER(x) #x
1019 #define STR(x) STR_HELPER(x)
1020 #define FULL_RUN_NAME __FILE__ STR(VSCALE_TEST_GROUP)".c"
1021 #endif
1022   return gst_check_run_suite (s, "videoscale", FULL_RUN_NAME);
1023 }