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