tests: videorate: remove obsolete color-matrix caps field
[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., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, 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 static GstCaps **
33 videoscale_get_allowed_caps_for_method (int method)
34 {
35   GstElement *scale;
36   GstCaps *caps, **ret;
37   GstPad *pad;
38   GstStructure *s;
39   gint i, n;
40
41   scale = gst_element_factory_make ("videoscale", "vscale");
42   g_object_set (scale, "method", method, NULL);
43   pad = gst_element_get_static_pad (scale, "sink");
44   caps = gst_pad_query_caps (pad, NULL);
45   gst_object_unref (pad);
46   gst_object_unref (scale);
47
48   caps = gst_caps_normalize (caps);
49   n = gst_caps_get_size (caps);
50   ret = g_new0 (GstCaps *, n + 1);
51
52   for (i = 0; i < n; i++) {
53     s = gst_caps_get_structure (caps, i);
54     ret[i] = gst_caps_new_empty ();
55     gst_caps_append_structure (ret[i], gst_structure_copy (s));
56     GST_LOG ("method %d supports: %" GST_PTR_FORMAT, method, s);
57   }
58
59   gst_caps_unref (caps);
60
61   return ret;
62 }
63
64 static void
65 on_sink_handoff (GstElement * element, GstBuffer * buffer, GstPad * pad,
66     gpointer user_data)
67 {
68   guint *n_buffers = user_data;
69
70   *n_buffers = *n_buffers + 1;
71 }
72
73 static gboolean
74 caps_is_supported (const GstCaps * caps)
75 {
76   GstVideoFormat fmt;
77   GstStructure *s;
78   const gchar *format;
79
80   GST_DEBUG ("have caps %" GST_PTR_FORMAT, caps);
81
82   s = gst_caps_get_structure (caps, 0);
83   format = gst_structure_get_string (s, "format");
84   fail_if (format == NULL);
85
86   fmt = gst_video_format_from_string (format);
87   fail_if (fmt == GST_VIDEO_FORMAT_UNKNOWN);
88
89   return (fmt == GST_VIDEO_FORMAT_ARGB64 || fmt == GST_VIDEO_FORMAT_AYUV64
90       || fmt == GST_VIDEO_FORMAT_GRAY8 || fmt == GST_VIDEO_FORMAT_GRAY16_BE
91       || fmt == GST_VIDEO_FORMAT_GRAY16_LE);
92 }
93
94 static void
95 run_test (const GstCaps * caps, gint src_width, gint src_height,
96     gint dest_width, gint dest_height, gint method,
97     GCallback src_handoff, gpointer src_handoff_user_data,
98     GCallback sink_handoff, gpointer sink_handoff_user_data)
99 {
100   GstElement *pipeline;
101   GstElement *src, *videoconvert, *capsfilter1, *identity, *scale,
102       *capsfilter2, *sink;
103   GstMessage *msg;
104   GstBus *bus;
105   GstCaps *copy;
106   guint n_buffers = 0;
107
108   /* skip formats that videoconvert can't handle */
109   if (caps_is_supported (caps))
110     return;
111
112   pipeline = gst_element_factory_make ("pipeline", "pipeline");
113   fail_unless (pipeline != NULL);
114
115   src = gst_element_factory_make ("videotestsrc", "src");
116   fail_unless (src != NULL);
117   g_object_set (G_OBJECT (src), "num-buffers", 1, NULL);
118
119   videoconvert = gst_element_factory_make ("videoconvert", "csp");
120   fail_unless (videoconvert != NULL);
121
122   capsfilter1 = gst_element_factory_make ("capsfilter", "filter1");
123   fail_unless (capsfilter1 != NULL);
124   copy = gst_caps_copy (caps);
125   gst_caps_set_simple (copy, "width", G_TYPE_INT, src_width, "height",
126       G_TYPE_INT, src_height, "framerate", GST_TYPE_FRACTION, 30, 1, NULL);
127   g_object_set (G_OBJECT (capsfilter1), "caps", copy, NULL);
128   gst_caps_unref (copy);
129
130   identity = gst_element_factory_make ("identity", "identity");
131   fail_unless (identity != NULL);
132   if (src_handoff) {
133     g_object_set (G_OBJECT (identity), "signal-handoffs", TRUE, NULL);
134     g_signal_connect (identity, "handoff", G_CALLBACK (src_handoff),
135         src_handoff_user_data);
136   }
137
138   scale = gst_element_factory_make ("videoscale", "scale");
139   fail_unless (scale != NULL);
140   g_object_set (G_OBJECT (scale), "method", method, NULL);
141
142   capsfilter2 = gst_element_factory_make ("capsfilter", "filter2");
143   fail_unless (capsfilter2 != NULL);
144   copy = gst_caps_copy (caps);
145   gst_caps_set_simple (copy, "width", G_TYPE_INT, dest_width, "height",
146       G_TYPE_INT, dest_height, NULL);
147   g_object_set (G_OBJECT (capsfilter2), "caps", copy, NULL);
148   gst_caps_unref (copy);
149
150   sink = gst_element_factory_make ("fakesink", "sink");
151   fail_unless (sink != NULL);
152   g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, "async", FALSE, NULL);
153   g_signal_connect (sink, "handoff", G_CALLBACK (on_sink_handoff), &n_buffers);
154   if (sink_handoff) {
155     g_signal_connect (sink, "handoff", G_CALLBACK (sink_handoff),
156         sink_handoff_user_data);
157   }
158
159   gst_bin_add_many (GST_BIN (pipeline), src, videoconvert, capsfilter1,
160       identity, scale, capsfilter2, sink, NULL);
161
162   fail_unless (gst_element_link_pads_full (src, "src", videoconvert, "sink",
163           LINK_CHECK_FLAGS));
164   fail_unless (gst_element_link_pads_full (videoconvert, "src", capsfilter1,
165           "sink", LINK_CHECK_FLAGS));
166   fail_unless (gst_element_link_pads_full (capsfilter1, "src", identity, "sink",
167           LINK_CHECK_FLAGS));
168   fail_unless (gst_element_link_pads_full (identity, "src", scale, "sink",
169           LINK_CHECK_FLAGS));
170   fail_unless (gst_element_link_pads_full (scale, "src", capsfilter2, "sink",
171           LINK_CHECK_FLAGS));
172   fail_unless (gst_element_link_pads_full (capsfilter2, "src", sink, "sink",
173           LINK_CHECK_FLAGS));
174
175   bus = gst_element_get_bus (pipeline);
176   fail_unless (bus != NULL);
177
178   fail_unless (gst_element_set_state (pipeline,
179           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
180
181   msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
182       GST_MESSAGE_EOS | GST_MESSAGE_ERROR | GST_MESSAGE_WARNING);
183
184   fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_EOS);
185
186   fail_unless (gst_element_set_state (pipeline,
187           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
188
189   fail_unless (n_buffers == 1);
190
191   gst_object_unref (pipeline);
192   gst_message_unref (msg);
193   gst_object_unref (bus);
194 }
195
196 static void
197 on_sink_handoff_passthrough (GstElement * element, GstBuffer * buffer,
198     GstPad * pad, gpointer user_data)
199 {
200   GList **list = user_data;
201
202   *list = g_list_prepend (*list, gst_buffer_ref (buffer));
203 }
204
205 static void
206 on_src_handoff_passthrough (GstElement * element, GstBuffer * buffer,
207     gpointer user_data)
208 {
209   GList **list = user_data;
210
211   *list = g_list_prepend (*list, gst_buffer_ref (buffer));
212 }
213
214 static void
215 test_passthrough (int method)
216 {
217   GList *l1, *l2, *src_buffers = NULL, *sink_buffers = NULL;
218   GstCaps **allowed_caps = NULL, **p;
219   static const gint src_width = 640, src_height = 480;
220   static const gint dest_width = 640, dest_height = 480;
221
222   p = allowed_caps = videoscale_get_allowed_caps_for_method (method);
223
224   while (*p) {
225     GstCaps *caps = *p;
226
227     /* skip formats that videoconvert can't handle */
228     if (caps_is_supported (caps)) {
229       goto next;
230     }
231
232     GST_DEBUG ("Running test for caps '%" GST_PTR_FORMAT "'"
233         " from %dx%u to %dx%d with method %d", caps, src_width, src_height,
234         dest_width, dest_height, method);
235     run_test (caps, src_width, src_height,
236         dest_width, dest_height, method,
237         G_CALLBACK (on_src_handoff_passthrough), &src_buffers,
238         G_CALLBACK (on_sink_handoff_passthrough), &sink_buffers);
239
240     fail_unless (src_buffers && sink_buffers);
241     fail_unless_equals_int (g_list_length (src_buffers),
242         g_list_length (sink_buffers));
243
244     for (l1 = src_buffers, l2 = sink_buffers; l1 && l2;
245         l1 = l1->next, l2 = l2->next) {
246       GstBuffer *a = l1->data;
247       GstBuffer *b = l2->data;
248       GstMapInfo mapa, mapb;
249
250       gst_buffer_map (a, &mapa, GST_MAP_READ);
251       gst_buffer_map (b, &mapb, GST_MAP_READ);
252       fail_unless_equals_int (mapa.size, mapb.size);
253       fail_unless (mapa.data == mapb.data);
254       gst_buffer_unmap (b, &mapb);
255       gst_buffer_unmap (a, &mapa);
256
257       gst_buffer_unref (a);
258       gst_buffer_unref (b);
259     }
260     g_list_free (src_buffers);
261     src_buffers = NULL;
262     g_list_free (sink_buffers);
263     sink_buffers = NULL;
264
265   next:
266     gst_caps_unref (caps);
267     p++;
268   }
269   g_free (allowed_caps);
270 }
271
272 GST_START_TEST (test_passthrough_method_0)
273 {
274   test_passthrough (0);
275 }
276
277 GST_END_TEST;
278
279 GST_START_TEST (test_passthrough_method_1)
280 {
281   test_passthrough (1);
282 }
283
284 GST_END_TEST;
285
286 GST_START_TEST (test_passthrough_method_2)
287 {
288   test_passthrough (2);
289 }
290
291 GST_END_TEST;
292
293 GST_START_TEST (test_passthrough_method_3)
294 {
295   test_passthrough (3);
296 }
297
298 GST_END_TEST;
299
300 #define CREATE_TEST(name,method,src_width,src_height,dest_width,dest_height) \
301 GST_START_TEST (name) \
302 { \
303   GstCaps **allowed_caps = NULL, **p; \
304   \
305   p = allowed_caps = videoscale_get_allowed_caps_for_method (method); \
306   \
307   while (*p) { \
308     GstCaps *caps = *p; \
309     \
310     GST_DEBUG ("Running test for caps '%" GST_PTR_FORMAT "'" \
311         " from %dx%u to %dx%d with method %d", caps, src_width, src_height, \
312         dest_width, dest_height, method); \
313     run_test (caps, src_width, src_height, \
314         dest_width, dest_height, method, \
315         NULL, NULL, NULL, NULL); \
316     gst_caps_unref (caps); \
317     p++; \
318   } \
319   g_free (allowed_caps); \
320 } \
321 \
322 GST_END_TEST;
323
324 CREATE_TEST (test_downscale_640x480_320x240_method_0, 0, 640, 480, 320, 240);
325 CREATE_TEST (test_downscale_640x480_320x240_method_1, 1, 640, 480, 320, 240);
326 CREATE_TEST (test_downscale_640x480_320x240_method_2, 2, 640, 480, 320, 240);
327 CREATE_TEST (test_downscale_640x480_320x240_method_3, 3, 640, 480, 320, 240);
328 CREATE_TEST (test_upscale_320x240_640x480_method_0, 0, 320, 240, 640, 480);
329 CREATE_TEST (test_upscale_320x240_640x480_method_1, 1, 320, 240, 640, 480);
330 CREATE_TEST (test_upscale_320x240_640x480_method_2, 2, 320, 240, 640, 480);
331 CREATE_TEST (test_upscale_320x240_640x480_method_3, 3, 320, 240, 640, 480);
332 CREATE_TEST (test_downscale_640x480_1x1_method_0, 0, 640, 480, 1, 1);
333 CREATE_TEST (test_downscale_640x480_1x1_method_1, 1, 640, 480, 1, 1);
334 CREATE_TEST (test_downscale_640x480_1x1_method_2, 2, 640, 480, 1, 1);
335 CREATE_TEST (test_downscale_640x480_1x1_method_3, 3, 640, 480, 1, 1);
336 CREATE_TEST (test_upscale_1x1_640x480_method_0, 0, 1, 1, 640, 480);
337 CREATE_TEST (test_upscale_1x1_640x480_method_1, 1, 1, 1, 640, 480);
338 CREATE_TEST (test_upscale_1x1_640x480_method_2, 2, 1, 1, 640, 480);
339 CREATE_TEST (test_upscale_1x1_640x480_method_3, 3, 1, 1, 640, 480);
340 CREATE_TEST (test_downscale_641x481_111x30_method_0, 0, 641, 481, 111, 30);
341 CREATE_TEST (test_downscale_641x481_111x30_method_1, 1, 641, 481, 111, 30);
342 CREATE_TEST (test_downscale_641x481_111x30_method_2, 2, 641, 481, 111, 30);
343 CREATE_TEST (test_downscale_641x481_111x30_method_3, 3, 641, 481, 111, 30);
344 CREATE_TEST (test_upscale_111x30_641x481_method_0, 0, 111, 30, 641, 481);
345 CREATE_TEST (test_upscale_111x30_641x481_method_1, 1, 111, 30, 641, 481);
346 CREATE_TEST (test_upscale_111x30_641x481_method_2, 2, 111, 30, 641, 481);
347 CREATE_TEST (test_upscale_111x30_641x481_method_3, 2, 111, 30, 641, 481);
348 CREATE_TEST (test_downscale_641x481_30x111_method_0, 0, 641, 481, 30, 111);
349 CREATE_TEST (test_downscale_641x481_30x111_method_1, 1, 641, 481, 30, 111);
350 CREATE_TEST (test_downscale_641x481_30x111_method_2, 2, 641, 481, 30, 111);
351 CREATE_TEST (test_downscale_641x481_30x111_method_3, 3, 641, 481, 30, 111);
352 CREATE_TEST (test_upscale_30x111_641x481_method_0, 0, 30, 111, 641, 481);
353 CREATE_TEST (test_upscale_30x111_641x481_method_1, 1, 30, 111, 641, 481);
354 CREATE_TEST (test_upscale_30x111_641x481_method_2, 2, 30, 111, 641, 481);
355 CREATE_TEST (test_upscale_30x111_641x481_method_3, 3, 30, 111, 641, 481);
356 CREATE_TEST (test_downscale_640x480_320x1_method_0, 0, 640, 480, 320, 1);
357 CREATE_TEST (test_downscale_640x480_320x1_method_1, 1, 640, 480, 320, 1);
358 CREATE_TEST (test_downscale_640x480_320x1_method_2, 2, 640, 480, 320, 1);
359 CREATE_TEST (test_downscale_640x480_320x1_method_3, 3, 640, 480, 320, 1);
360 CREATE_TEST (test_upscale_320x1_640x480_method_0, 0, 320, 1, 640, 480);
361 CREATE_TEST (test_upscale_320x1_640x480_method_1, 1, 320, 1, 640, 480);
362 CREATE_TEST (test_upscale_320x1_640x480_method_2, 2, 320, 1, 640, 480);
363 CREATE_TEST (test_upscale_320x1_640x480_method_3, 3, 320, 1, 640, 480);
364 CREATE_TEST (test_downscale_640x480_1x240_method_0, 0, 640, 480, 1, 240);
365 CREATE_TEST (test_downscale_640x480_1x240_method_1, 1, 640, 480, 1, 240);
366 CREATE_TEST (test_downscale_640x480_1x240_method_2, 2, 640, 480, 1, 240);
367 CREATE_TEST (test_downscale_640x480_1x240_method_3, 3, 640, 480, 1, 240);
368 CREATE_TEST (test_upscale_1x240_640x480_method_0, 0, 1, 240, 640, 480);
369 CREATE_TEST (test_upscale_1x240_640x480_method_1, 1, 1, 240, 640, 480);
370 CREATE_TEST (test_upscale_1x240_640x480_method_2, 2, 1, 240, 640, 480);
371 CREATE_TEST (test_upscale_1x240_640x480_method_3, 3, 1, 240, 640, 480);
372
373 typedef struct
374 {
375   gint width, height;
376   gint par_n, par_d;
377   gboolean ok;
378   GMainLoop *loop;
379 } TestNegotiationData;
380
381 static void
382 _test_negotiation_message (GstBus * bus, GstMessage * message,
383     TestNegotiationData * data)
384 {
385   GError *err = NULL;
386   gchar *debug;
387
388   switch (GST_MESSAGE_TYPE (message)) {
389     case GST_MESSAGE_ERROR:
390       gst_message_parse_error (message, &err, &debug);
391       gst_object_default_error (GST_MESSAGE_SRC (message), err, debug);
392       g_error_free (err);
393       g_free (debug);
394       g_assert_not_reached ();
395       break;
396     case GST_MESSAGE_WARNING:
397       gst_message_parse_warning (message, &err, &debug);
398       gst_object_default_error (GST_MESSAGE_SRC (message), err, debug);
399       g_error_free (err);
400       g_free (debug);
401       g_assert_not_reached ();
402       break;
403     case GST_MESSAGE_EOS:
404       g_main_loop_quit (data->loop);
405       break;
406     default:
407       break;
408   }
409 }
410
411 static void
412 _test_negotiation_notify_caps (GObject * src, GParamSpec * pspec,
413     TestNegotiationData * data)
414 {
415   GstCaps *caps;
416   GstStructure *s;
417   gint width, height;
418   gint par_n = 0, par_d = 0;
419
420   g_object_get (src, "caps", &caps, NULL);
421   if (caps == NULL)
422     return;
423
424   s = gst_caps_get_structure (caps, 0);
425
426   fail_unless (gst_structure_get_int (s, "width", &width));
427   fail_unless (gst_structure_get_int (s, "height", &height));
428   fail_unless (gst_structure_get_fraction (s, "pixel-aspect-ratio", &par_n,
429           &par_d) || (data->par_n == 1 && data->par_d == 1));
430
431   gst_caps_unref (caps);
432
433   fail_unless_equals_int (width, data->width);
434   fail_unless_equals_int (height, data->height);
435   if (par_n != 0 || par_d != 0) {
436     fail_unless_equals_int (par_n, data->par_n);
437     fail_unless_equals_int (par_d, data->par_d);
438   }
439
440   data->ok = (width == data->width) && (height == data->height)
441       && (par_n == data->par_n) && (par_d == data->par_d);
442
443   g_main_loop_quit (data->loop);
444 }
445
446 static void
447 _test_negotiation (const gchar * src_templ, const gchar * sink_templ,
448     gint width, gint height, gint par_n, gint par_d)
449 {
450   GstElement *pipeline;
451   GstElement *src, *capsfilter1, *scale, *capsfilter2, *sink;
452   GstBus *bus;
453   GMainLoop *loop;
454   GstCaps *caps;
455   TestNegotiationData data = { 0, 0, 0, 0, FALSE, NULL };
456   GstPad *pad;
457
458   GST_DEBUG ("Running test for src templ caps '%s' and sink templ caps '%s'",
459       src_templ, sink_templ);
460
461   pipeline = gst_element_factory_make ("pipeline", "pipeline");
462   fail_unless (pipeline != NULL);
463
464   src = gst_element_factory_make ("videotestsrc", "src");
465   fail_unless (src != NULL);
466   g_object_set (G_OBJECT (src), "num-buffers", 1, NULL);
467
468   capsfilter1 = gst_element_factory_make ("capsfilter", "filter1");
469   fail_unless (capsfilter1 != NULL);
470   caps = gst_caps_from_string (src_templ);
471   fail_unless (caps != NULL);
472   g_object_set (G_OBJECT (capsfilter1), "caps", caps, NULL);
473   gst_caps_unref (caps);
474
475   scale = gst_element_factory_make ("videoscale", "scale");
476   fail_unless (scale != NULL);
477
478   capsfilter2 = gst_element_factory_make ("capsfilter", "filter2");
479   fail_unless (capsfilter2 != NULL);
480   caps = gst_caps_from_string (sink_templ);
481   fail_unless (caps != NULL);
482   g_object_set (G_OBJECT (capsfilter2), "caps", caps, NULL);
483   gst_caps_unref (caps);
484
485   pad = gst_element_get_static_pad (capsfilter2, "sink");
486   fail_unless (pad != NULL);
487   g_signal_connect (pad, "notify::caps",
488       G_CALLBACK (_test_negotiation_notify_caps), &data);
489   gst_object_unref (pad);
490
491   sink = gst_element_factory_make ("fakesink", "sink");
492   fail_unless (sink != NULL);
493   g_object_set (sink, "async", FALSE, NULL);
494
495   gst_bin_add_many (GST_BIN (pipeline), src, capsfilter1, scale, capsfilter2,
496       sink, NULL);
497
498   fail_unless (gst_element_link_pads_full (src, "src", capsfilter1, "sink",
499           LINK_CHECK_FLAGS));
500   fail_unless (gst_element_link_pads_full (capsfilter1, "src", scale, "sink",
501           LINK_CHECK_FLAGS));
502   fail_unless (gst_element_link_pads_full (scale, "src", capsfilter2, "sink",
503           LINK_CHECK_FLAGS));
504   fail_unless (gst_element_link_pads_full (capsfilter2, "src", sink, "sink",
505           LINK_CHECK_FLAGS));
506
507   loop = g_main_loop_new (NULL, FALSE);
508
509   bus = gst_element_get_bus (pipeline);
510   fail_unless (bus != NULL);
511   gst_bus_add_signal_watch (bus);
512
513   data.loop = loop;
514   data.width = width;
515   data.height = height;
516   data.par_n = par_n;
517   data.par_d = par_d;
518   data.ok = FALSE;
519
520   g_signal_connect (bus, "message", G_CALLBACK (_test_negotiation_message),
521       &data);
522
523   gst_object_unref (bus);
524
525   fail_unless (gst_element_set_state (pipeline,
526           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
527
528   g_main_loop_run (loop);
529
530   fail_unless (data.ok == TRUE);
531
532   fail_unless (gst_element_set_state (pipeline,
533           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
534
535   gst_object_unref (pipeline);
536   g_main_loop_unref (loop);
537 }
538
539 GST_START_TEST (test_negotiation)
540 {
541   _test_negotiation
542       ("video/x-raw,format=(string)AYUV,width=720,height=576,pixel-aspect-ratio=16/15",
543       "video/x-raw,format=(string)AYUV,width=768,height=576", 768, 576, 1, 1);
544
545   _test_negotiation
546       ("video/x-raw,format=(string)AYUV,width=320,height=240",
547       "video/x-raw,format=(string)AYUV,width=640,height=320", 640, 320, 2, 3);
548
549   _test_negotiation
550       ("video/x-raw,format=(string)AYUV,width=320,height=240",
551       "video/x-raw,format=(string)AYUV,width=640,height=320,pixel-aspect-ratio=[0/1, 1/1]",
552       640, 320, 2, 3);
553
554   _test_negotiation
555       ("video/x-raw,format=(string)AYUV,width=1920,height=2560,pixel-aspect-ratio=1/1",
556       "video/x-raw,format=(string)AYUV,width=[1, 2048],height=[1, 2048],pixel-aspect-ratio=1/1",
557       1536, 2048, 1, 1);
558
559   _test_negotiation
560       ("video/x-raw,format=(string)AYUV,width=1920,height=2560,pixel-aspect-ratio=1/1",
561       "video/x-raw,format=(string)AYUV,width=[1, 2048],height=[1, 2048]",
562       1920, 2048, 4, 5);
563
564   _test_negotiation
565       ("video/x-raw,format=(string)AYUV,width=1920,height=2560",
566       "video/x-raw,format=(string)AYUV,width=[1, 2048],height=[1, 2048]",
567       1920, 2048, 4, 5);
568
569   _test_negotiation
570       ("video/x-raw,format=(string)AYUV,width=1920,height=2560",
571       "video/x-raw,format=(string)AYUV,width=1200,height=[1, 2048],pixel-aspect-ratio=1/1",
572       1200, 1600, 1, 1);
573
574   /* Doesn't keep DAR but must be possible! */
575   _test_negotiation
576       ("video/x-raw,format=(string)AYUV,width=320,height=240,pixel-aspect-ratio=1/1",
577       "video/x-raw,format=(string)AYUV,width=200,height=200,pixel-aspect-ratio=1/2",
578       200, 200, 1, 2);
579 }
580
581 GST_END_TEST;
582
583 #define GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK \
584   (gst_test_reverse_negotiation_sink_get_type())
585 #define GST_TEST_REVERSE_NEGOTIATION_SINK(obj) \
586   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK,GstTestReverseNegotiationSink))
587 #define GST_TEST_REVERSE_NEGOTIATION_SINK_CLASS(klass) \
588   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK,GstTestReverseNegotiationSinkClass))
589 #define GST_IS_TEST_REVERSE_NEGOTIATION_SINK(obj) \
590   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK))
591 #define GST_IS_TEST_REVERSE_NEGOTIATION_SINK_CLASS(klass) \
592   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK))
593 #define GST_TEST_REVERSE_NEGOTIATION_SINK_CAST(obj) ((GstTestReverseNegotiationSink *)obj)
594
595 typedef struct _GstTestReverseNegotiationSink GstTestReverseNegotiationSink;
596 typedef struct _GstTestReverseNegotiationSinkClass
597     GstTestReverseNegotiationSinkClass;
598 struct _GstTestReverseNegotiationSink
599 {
600   GstBaseSink element;
601   gint nbuffers;
602 };
603
604 struct _GstTestReverseNegotiationSinkClass
605 {
606   GstBaseSinkClass parent_class;
607 };
608
609 GType gst_test_reverse_negotiation_sink_get_type (void);
610
611 G_DEFINE_TYPE (GstTestReverseNegotiationSink,
612     gst_test_reverse_negotiation_sink, GST_TYPE_BASE_SINK);
613
614 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
615     GST_PAD_SINK,
616     GST_PAD_ALWAYS,
617     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("xRGB")));
618
619 #if 0
620 static GstFlowReturn
621 gst_test_reverse_negotiation_sink_buffer_alloc (GstBaseSink * bsink,
622     guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf)
623 {
624   GstTestReverseNegotiationSink *sink =
625       GST_TEST_REVERSE_NEGOTIATION_SINK (bsink);
626   GstVideoFormat fmt;
627   gint width, height;
628
629   fail_unless (gst_video_format_parse_caps (caps, &fmt, &width, &height));
630
631   if (sink->nbuffers < 2) {
632     *buf =
633         gst_buffer_new_and_alloc (gst_video_format_get_size (fmt, width,
634             height));
635     gst_buffer_set_caps (*buf, caps);
636   } else {
637     gint fps_n, fps_d;
638
639     fail_unless (gst_video_parse_caps_framerate (caps, &fps_n, &fps_d));
640
641     width = 512;
642     height = 128;
643     *buf =
644         gst_buffer_new_and_alloc (gst_video_format_get_size (fmt, width,
645             height));
646     caps = gst_video_format_new_caps (fmt, width, height, fps_n, fps_d, 1, 1);
647     gst_buffer_set_caps (*buf, caps);
648     gst_caps_unref (caps);
649   }
650
651   return GST_FLOW_OK;
652 }
653 #endif
654
655 static GstFlowReturn
656 gst_test_reverse_negotiation_sink_render (GstBaseSink * bsink,
657     GstBuffer * buffer)
658 {
659   GstTestReverseNegotiationSink *sink =
660       GST_TEST_REVERSE_NEGOTIATION_SINK (bsink);
661   GstCaps *caps;
662   GstVideoInfo info;
663
664   caps = gst_pad_get_current_caps (GST_BASE_SINK_PAD (bsink));
665
666   fail_unless (caps != NULL);
667   fail_unless (gst_video_info_from_caps (&info, caps));
668
669   sink->nbuffers++;
670
671   /* The third buffer is still in the old size
672    * because the videoconverts can't convert
673    * the frame sizes
674    */
675   if (sink->nbuffers > 3) {
676     fail_unless_equals_int (GST_VIDEO_INFO_WIDTH (&info), 512);
677     fail_unless_equals_int (GST_VIDEO_INFO_HEIGHT (&info), 128);
678   }
679
680   gst_caps_unref (caps);
681
682   return GST_FLOW_OK;
683 }
684
685 static void
686 gst_test_reverse_negotiation_sink_class_init (GstTestReverseNegotiationSinkClass
687     * klass)
688 {
689   GstElementClass *gstelement_class;
690   GstBaseSinkClass *gstbase_sink_class;
691
692   gstelement_class = GST_ELEMENT_CLASS (klass);
693   gstbase_sink_class = GST_BASE_SINK_CLASS (klass);
694
695   gst_element_class_set_details_simple (gstelement_class,
696       "Test Reverse Negotiation Sink",
697       "Sink",
698       "Some test sink", "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
699   gst_element_class_add_pad_template (gstelement_class,
700       gst_static_pad_template_get (&sinktemplate));
701
702 #if 0
703   gstbase_sink_class->buffer_alloc =
704       GST_DEBUG_FUNCPTR (gst_test_reverse_negotiation_sink_buffer_alloc);
705 #endif
706   gstbase_sink_class->render =
707       GST_DEBUG_FUNCPTR (gst_test_reverse_negotiation_sink_render);
708 }
709
710 static void
711 gst_test_reverse_negotiation_sink_init (GstTestReverseNegotiationSink * sink)
712 {
713   sink->nbuffers = 0;
714 }
715
716 #if 0
717 static void
718 _test_reverse_negotiation_message (GstBus * bus, GstMessage * message,
719     GMainLoop * loop)
720 {
721   GError *err = NULL;
722   gchar *debug;
723
724   switch (GST_MESSAGE_TYPE (message)) {
725     case GST_MESSAGE_ERROR:
726       gst_message_parse_error (message, &err, &debug);
727       gst_object_default_error (GST_MESSAGE_SRC (message), err, debug);
728       g_error_free (err);
729       g_free (debug);
730       g_assert_not_reached ();
731       break;
732     case GST_MESSAGE_WARNING:
733       gst_message_parse_warning (message, &err, &debug);
734       gst_object_default_error (GST_MESSAGE_SRC (message), err, debug);
735       g_error_free (err);
736       g_free (debug);
737       g_assert_not_reached ();
738       break;
739     case GST_MESSAGE_EOS:
740       g_main_loop_quit (loop);
741       break;
742     default:
743       break;
744   }
745 }
746 #endif
747
748 #if 0
749 GST_START_TEST (test_reverse_negotiation)
750 {
751   GstElement *pipeline;
752   GstElement *src, *csp1, *scale, *csp2, *sink;
753   GstBus *bus;
754   GMainLoop *loop;
755
756   pipeline = gst_element_factory_make ("pipeline", "pipeline");
757   fail_unless (pipeline != NULL);
758
759   src = gst_element_factory_make ("videotestsrc", "src");
760   fail_unless (src != NULL);
761   g_object_set (G_OBJECT (src), "num-buffers", 8, NULL);
762
763   csp1 = gst_element_factory_make ("videoconvert", "csp1");
764   fail_unless (csp1 != NULL);
765
766   scale = gst_element_factory_make ("videoscale", "scale");
767   fail_unless (scale != NULL);
768
769   csp2 = gst_element_factory_make ("videoconvert", "csp2");
770   fail_unless (csp2 != NULL);
771
772   sink = g_object_new (GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK, NULL);
773   fail_unless (sink != NULL);
774   g_object_set (sink, "async", FALSE, NULL);
775
776   gst_bin_add_many (GST_BIN (pipeline), src, csp1, scale, csp2, sink, NULL);
777
778   fail_unless (gst_element_link_pads_full (src, "src", csp1, "sink",
779           LINK_CHECK_FLAGS));
780   fail_unless (gst_element_link_pads_full (csp1, "src", scale, "sink",
781           LINK_CHECK_FLAGS));
782   fail_unless (gst_element_link_pads_full (scale, "src", csp2, "sink",
783           LINK_CHECK_FLAGS));
784   fail_unless (gst_element_link_pads_full (csp2, "src", sink, "sink",
785           LINK_CHECK_FLAGS));
786
787   loop = g_main_loop_new (NULL, FALSE);
788
789   bus = gst_element_get_bus (pipeline);
790   fail_unless (bus != NULL);
791   gst_bus_add_signal_watch (bus);
792
793   g_signal_connect (bus, "message",
794       G_CALLBACK (_test_reverse_negotiation_message), loop);
795
796   gst_object_unref (bus);
797
798   fail_unless (gst_element_set_state (pipeline,
799           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
800
801   g_main_loop_run (loop);
802
803   fail_unless (gst_element_set_state (pipeline,
804           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
805
806   gst_object_unref (pipeline);
807   g_main_loop_unref (loop);
808 }
809
810 GST_END_TEST;
811 #endif
812
813 GST_START_TEST (test_basetransform_negotiation)
814 {
815   GstElement *pipeline, *src, *sink, *scale, *capsfilter1, *capsfilter2;
816   GstMessage *msg;
817   GstCaps *caps;
818
819   pipeline = gst_pipeline_new (NULL);
820   src = gst_element_factory_make ("videotestsrc", NULL);
821   capsfilter1 = gst_element_factory_make ("capsfilter", NULL);
822   scale = gst_element_factory_make ("videoscale", NULL);
823   capsfilter2 = gst_element_factory_make ("capsfilter", NULL);
824   sink = gst_element_factory_make ("fakesink", NULL);
825   fail_unless (pipeline && src && capsfilter1 && scale && capsfilter2 && sink);
826
827   g_object_set (src, "num-buffers", 3, NULL);
828
829   caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
830       "UYVY", "width", G_TYPE_INT, 352,
831       "height", G_TYPE_INT, 288, "framerate", GST_TYPE_FRACTION, 30, 1,
832       "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
833   g_object_set (capsfilter1, "caps", caps, NULL);
834   gst_caps_unref (caps);
835
836   /* same caps, just different pixel-aspect-ratio */
837   caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
838       "UYVY", "width", G_TYPE_INT, 352,
839       "height", G_TYPE_INT, 288, "framerate", GST_TYPE_FRACTION, 30, 1,
840       "pixel-aspect-ratio", GST_TYPE_FRACTION, 12, 11, NULL);
841   g_object_set (capsfilter2, "caps", caps, NULL);
842   gst_caps_unref (caps);
843
844   gst_bin_add_many (GST_BIN (pipeline), src, capsfilter1, scale, capsfilter2,
845       sink, NULL);
846   fail_unless (gst_element_link_many (src, capsfilter1, scale, capsfilter2,
847           sink, NULL));
848
849   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
850       GST_STATE_CHANGE_ASYNC);
851
852   msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipeline), -1,
853       GST_MESSAGE_EOS | GST_MESSAGE_ERROR);
854   fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_EOS);
855   gst_message_unref (msg);
856
857   gst_element_set_state (pipeline, GST_STATE_NULL);
858   gst_object_unref (pipeline);
859 }
860
861 GST_END_TEST;
862
863 #ifndef tcase_skip_broken_test
864 #define tcase_skip_broken_test(chain,test_func) \
865   if (0) { tcase_add_test(chain,test_func); } else { \
866     GST_ERROR ("FIXME: skipping test %s because it's broken.", G_STRINGIFY (test_func)); \
867   }
868 #endif
869
870 static Suite *
871 videoscale_suite (void)
872 {
873   Suite *s = suite_create ("videoscale");
874   TCase *tc_chain = tcase_create ("general");
875
876   suite_add_tcase (s, tc_chain);
877   tcase_set_timeout (tc_chain, 180);
878   tcase_add_test (tc_chain, test_passthrough_method_0);
879   tcase_add_test (tc_chain, test_passthrough_method_1);
880   tcase_add_test (tc_chain, test_passthrough_method_2);
881   tcase_add_test (tc_chain, test_passthrough_method_3);
882   tcase_add_test (tc_chain, test_downscale_640x480_320x240_method_0);
883   tcase_add_test (tc_chain, test_downscale_640x480_320x240_method_1);
884   tcase_add_test (tc_chain, test_downscale_640x480_320x240_method_2);
885   tcase_add_test (tc_chain, test_downscale_640x480_320x240_method_3);
886   tcase_add_test (tc_chain, test_upscale_320x240_640x480_method_0);
887   tcase_add_test (tc_chain, test_upscale_320x240_640x480_method_1);
888   tcase_add_test (tc_chain, test_upscale_320x240_640x480_method_2);
889   tcase_add_test (tc_chain, test_upscale_320x240_640x480_method_3);
890   tcase_add_test (tc_chain, test_downscale_640x480_1x1_method_0);
891   tcase_add_test (tc_chain, test_downscale_640x480_1x1_method_1);
892   tcase_add_test (tc_chain, test_downscale_640x480_1x1_method_2);
893   tcase_skip_broken_test (tc_chain, test_downscale_640x480_1x1_method_3);
894   tcase_add_test (tc_chain, test_upscale_1x1_640x480_method_0);
895   tcase_add_test (tc_chain, test_upscale_1x1_640x480_method_1);
896   tcase_add_test (tc_chain, test_upscale_1x1_640x480_method_2);
897   tcase_add_test (tc_chain, test_upscale_1x1_640x480_method_3);
898   tcase_add_test (tc_chain, test_downscale_641x481_111x30_method_0);
899   tcase_add_test (tc_chain, test_downscale_641x481_111x30_method_1);
900   tcase_add_test (tc_chain, test_downscale_641x481_111x30_method_2);
901   tcase_add_test (tc_chain, test_downscale_641x481_111x30_method_3);
902   tcase_add_test (tc_chain, test_upscale_111x30_641x481_method_0);
903   tcase_add_test (tc_chain, test_upscale_111x30_641x481_method_1);
904   tcase_add_test (tc_chain, test_upscale_111x30_641x481_method_2);
905   tcase_add_test (tc_chain, test_upscale_111x30_641x481_method_3);
906   tcase_add_test (tc_chain, test_downscale_641x481_30x111_method_0);
907   tcase_add_test (tc_chain, test_downscale_641x481_30x111_method_1);
908   tcase_add_test (tc_chain, test_downscale_641x481_30x111_method_2);
909   tcase_add_test (tc_chain, test_downscale_641x481_30x111_method_3);
910   tcase_add_test (tc_chain, test_upscale_30x111_641x481_method_0);
911   tcase_add_test (tc_chain, test_upscale_30x111_641x481_method_1);
912   tcase_add_test (tc_chain, test_upscale_30x111_641x481_method_2);
913   tcase_add_test (tc_chain, test_upscale_30x111_641x481_method_3);
914   tcase_add_test (tc_chain, test_downscale_640x480_320x1_method_0);
915   tcase_add_test (tc_chain, test_downscale_640x480_320x1_method_1);
916   tcase_add_test (tc_chain, test_downscale_640x480_320x1_method_2);
917   tcase_skip_broken_test (tc_chain, test_downscale_640x480_320x1_method_3);
918   tcase_add_test (tc_chain, test_upscale_320x1_640x480_method_0);
919   tcase_add_test (tc_chain, test_upscale_320x1_640x480_method_1);
920   tcase_add_test (tc_chain, test_upscale_320x1_640x480_method_2);
921   tcase_skip_broken_test (tc_chain, test_upscale_320x1_640x480_method_3);
922   tcase_add_test (tc_chain, test_downscale_640x480_1x240_method_0);
923   tcase_add_test (tc_chain, test_downscale_640x480_1x240_method_1);
924   tcase_add_test (tc_chain, test_downscale_640x480_1x240_method_2);
925   tcase_skip_broken_test (tc_chain, test_downscale_640x480_1x240_method_3);
926   tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_0);
927   tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_1);
928   tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_2);
929   tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_3);
930   tcase_add_test (tc_chain, test_negotiation);
931 #if 0
932   tcase_add_test (tc_chain, test_reverse_negotiation);
933 #endif
934   tcase_add_test (tc_chain, test_basetransform_negotiation);
935
936   GST_ERROR ("FIXME: test 64-bpp formats as well");
937   return s;
938 }
939
940 GST_CHECK_MAIN (videoscale);