Tizen 2.0 Release
[framework/multimedia/gst-plugins-good0.10.git] / tests / check / elements / deinterlace.c
1 /* GStreamer unit tests for the deinterlace element
2  * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
23
24 #include <stdio.h>
25 #include <gst/check/gstcheck.h>
26 #include <gst/video/video.h>
27
28 static gboolean
29 gst_caps_is_interlaced (GstCaps * caps)
30 {
31   GstStructure G_GNUC_UNUSED *structure;
32   gboolean interlaced = FALSE;
33
34   fail_unless (gst_caps_is_fixed (caps));
35   structure = gst_caps_get_structure (caps, 0);
36   fail_unless (gst_video_format_parse_caps_interlaced (caps, &interlaced));
37   return interlaced;
38 }
39
40 GST_START_TEST (test_create_and_unref)
41 {
42   GstElement *deinterlace;
43
44   deinterlace = gst_element_factory_make ("deinterlace", NULL);
45   fail_unless (deinterlace != NULL);
46
47   gst_element_set_state (deinterlace, GST_STATE_NULL);
48   gst_object_unref (deinterlace);
49 }
50
51 GST_END_TEST;
52
53 #define CAPS_VIDEO_COMMON \
54     "width=(int)800, height=(int)600, framerate=(fraction)15/1"
55
56 #define CAPS_IMAGE_COMMON \
57     "width=(int)3200, height=(int)3400, framerate=(fraction)0/1"
58
59 #define CAPS_YUY2 \
60     "video/x-raw-yuv, " \
61     CAPS_VIDEO_COMMON ", " \
62     "format=(fourcc)YUY2"
63
64 #define CAPS_YUY2_INTERLACED \
65     CAPS_YUY2 ", " \
66     "interlaced=(boolean)true"
67
68 #define CAPS_YVYU \
69     "video/x-raw-yuv, " \
70     CAPS_VIDEO_COMMON ", " \
71     "format=(fourcc)YVYU"
72
73 #define CAPS_YVYU_INTERLACED \
74     CAPS_YVYU ", " \
75     "interlaced=(boolean)true"
76
77 #define CAPS_YUY2_IMAGE \
78     "video/x-raw-yuv, " \
79     CAPS_IMAGE_COMMON ", " \
80     "format=(fourcc)YUY2"
81
82 #define CAPS_YUY2_INTERLACED_IMAGE \
83     CAPS_YUY2_IMAGE ", " \
84     "interlaced=(boolean)true"
85
86 #define CAPS_YVYU_IMAGE \
87     "video/x-raw-yuv, " \
88     CAPS_IMAGE_COMMON ", " \
89     "format=(fourcc)YVYU"
90
91 #define CAPS_YVYU_INTERLACED_IMAGE \
92     CAPS_YVYU_IMAGE ", " \
93     "interlaced=(boolean)true"
94
95 static GstElement *deinterlace;
96 static GstPad *srcpad;
97 static GstPad *sinkpad;
98
99 static GstElement *pipeline;
100
101 /* sets up deinterlace and shortcut pointers to its pads */
102 static void
103 setup_deinterlace (void)
104 {
105   deinterlace = gst_element_factory_make ("deinterlace", NULL);
106   fail_unless (deinterlace != NULL);
107
108   sinkpad = gst_element_get_static_pad (deinterlace, "sink");
109   fail_unless (sinkpad != NULL);
110   srcpad = gst_element_get_static_pad (deinterlace, "src");
111   fail_unless (srcpad != NULL);
112 }
113
114 /* sets up a basic test pipeline containing:
115  *
116  * videotestsrc ! capsfilter ! deinterlace ! fakesink
117  *
118  * The parameters set the capsfilter caps and the num-buffers
119  * property of videotestsrc
120  *
121  * It is useful for adding buffer probes to deinterlace pads
122  * and validating inputs/outputs
123  */
124 static void
125 setup_test_pipeline (gint mode, GstCaps * infiltercaps, GstCaps * outfiltercaps,
126     gint numbuffers)
127 {
128   GstElement *src;
129   GstElement *infilter;
130   GstElement *outfilter;
131   GstElement *sink;
132
133   setup_deinterlace ();
134
135   pipeline = gst_pipeline_new ("pipeline");
136   src = gst_element_factory_make ("videotestsrc", NULL);
137   infilter = gst_element_factory_make ("capsfilter", "infilter");
138   outfilter = gst_element_factory_make ("capsfilter", "outfilter");
139   sink = gst_element_factory_make ("fakesink", NULL);
140   fail_if (src == NULL);
141   fail_if (infilter == NULL);
142   fail_if (outfilter == NULL);
143   fail_if (sink == NULL);
144
145   fail_unless (gst_bin_add (GST_BIN (pipeline), src));
146   fail_unless (gst_bin_add (GST_BIN (pipeline), infilter));
147   fail_unless (gst_bin_add (GST_BIN (pipeline), deinterlace));
148   fail_unless (gst_bin_add (GST_BIN (pipeline), outfilter));
149   fail_unless (gst_bin_add (GST_BIN (pipeline), sink));
150
151   /* set the properties */
152   g_object_set (deinterlace, "mode", mode, NULL);
153   if (numbuffers > 0)
154     g_object_set (src, "num-buffers", numbuffers, NULL);
155   if (infiltercaps)
156     g_object_set (infilter, "caps", infiltercaps, NULL);
157   if (outfiltercaps)
158     g_object_set (outfilter, "caps", outfiltercaps, NULL);
159
160   fail_unless (gst_element_link_many (src, infilter, deinterlace, outfilter,
161           sink, NULL));
162   if (infiltercaps)
163     gst_caps_unref (infiltercaps);
164   if (outfiltercaps)
165     gst_caps_unref (outfiltercaps);
166 }
167
168 /*
169  * Checks if 2 buffers are equal
170  *
171  * Equals means same caps and same data
172  */
173 static gboolean
174 test_buffer_equals (GstBuffer * buf_a, GstBuffer * buf_b)
175 {
176   GstCaps *caps_a;
177   GstCaps *caps_b;
178
179   if (GST_BUFFER_SIZE (buf_a) != GST_BUFFER_SIZE (buf_b))
180     return FALSE;
181
182   caps_a = gst_buffer_get_caps (buf_a);
183   caps_b = gst_buffer_get_caps (buf_b);
184
185   if (!gst_caps_is_equal (caps_a, caps_b))
186     return FALSE;
187
188   gst_caps_unref (caps_a);
189   gst_caps_unref (caps_b);
190
191   return memcmp (GST_BUFFER_DATA (buf_a), GST_BUFFER_DATA (buf_b),
192       GST_BUFFER_SIZE (buf_a)) == 0;
193 }
194
195 static gboolean
196 sinkpad_enqueue_buffer (GstPad * pad, GstBuffer * buf, gpointer data)
197 {
198   GQueue *queue = (GQueue *) data;
199
200   /* enqueue a copy for being compared later */
201   g_queue_push_tail (queue, gst_buffer_copy (buf));
202
203   return TRUE;
204 }
205
206 /*
207  * pad buffer probe that compares the buffer with the top one
208  * in the GQueue passed as the user data
209  */
210 static gboolean
211 srcpad_dequeue_and_compare_buffer (GstPad * pad, GstBuffer * buf, gpointer data)
212 {
213   GQueue *queue = (GQueue *) data;
214   GstBuffer *queue_buf;
215
216   queue_buf = (GstBuffer *) g_queue_pop_head (queue);
217   fail_if (queue_buf == NULL);
218
219   fail_unless (test_buffer_equals (buf, queue_buf));
220
221   gst_buffer_unref (queue_buf);
222
223   return TRUE;
224 }
225
226 /*
227  * Utility function that sets up a pipeline with deinterlace for
228  * validanting that it operates in passthrough mode when receiving
229  * data with 'infiltercaps' as the input caps and operating in 'mode' mode
230  */
231 static void
232 deinterlace_check_passthrough (gint mode, const gchar * infiltercaps)
233 {
234   GstMessage *msg;
235   GQueue *queue;
236   GstCaps *incaps = NULL;
237
238   if (infiltercaps)
239     incaps = gst_caps_from_string (infiltercaps);
240
241   setup_test_pipeline (mode, incaps, NULL, 20);
242
243   queue = g_queue_new ();
244
245   /* set up probes for testing */
246   gst_pad_add_buffer_probe (sinkpad, (GCallback) sinkpad_enqueue_buffer, queue);
247   gst_pad_add_buffer_probe (srcpad,
248       (GCallback) srcpad_dequeue_and_compare_buffer, queue);
249
250   fail_unless (gst_element_set_state (pipeline, GST_STATE_PLAYING) !=
251       GST_STATE_CHANGE_FAILURE);
252
253   msg = gst_bus_poll (GST_ELEMENT_BUS (pipeline), GST_MESSAGE_EOS, -1);
254   gst_message_unref (msg);
255
256   /* queue should be empty */
257   fail_unless (g_queue_is_empty (queue));
258
259   fail_unless (gst_element_set_state (pipeline, GST_STATE_NULL) ==
260       GST_STATE_CHANGE_SUCCESS);
261   gst_object_unref (pipeline);
262   g_queue_free (queue);
263 }
264
265 /*
266  * Sets the caps on deinterlace sinkpad and validates the
267  * caps that is set on the srcpad
268  */
269 static void
270 deinterlace_set_caps_and_check (GstCaps * input, gboolean must_deinterlace)
271 {
272   GstCaps *othercaps = NULL;
273
274   fail_unless (gst_pad_set_caps (sinkpad, input));
275   g_object_get (srcpad, "caps", &othercaps, NULL);
276
277   if (must_deinterlace) {
278     fail_if (gst_caps_is_interlaced (othercaps));
279   } else {
280     GstStructure *s;
281
282     fail_unless (gst_caps_is_interlaced (input) ==
283         gst_caps_is_interlaced (othercaps));
284
285     othercaps = gst_caps_make_writable (othercaps);
286     s = gst_caps_get_structure (othercaps, 0);
287     gst_structure_remove_field (s, "interlaced");
288
289     input = gst_caps_make_writable (input);
290     s = gst_caps_get_structure (input, 0);
291     gst_structure_remove_field (s, "interlaced");
292
293     fail_unless (gst_caps_is_equal (input, othercaps));
294   }
295   gst_caps_unref (input);
296   gst_caps_unref (othercaps);
297 }
298
299 static void
300 deinterlace_set_string_caps_and_check (const gchar * input,
301     gboolean must_deinterlace)
302 {
303   deinterlace_set_caps_and_check (gst_caps_from_string (input),
304       must_deinterlace);
305 }
306
307 GST_START_TEST (test_mode_auto_accept_caps)
308 {
309   setup_deinterlace ();
310
311   /* auto mode */
312   g_object_set (deinterlace, "mode", 0, NULL);
313   fail_unless (gst_element_set_state (deinterlace, GST_STATE_PLAYING) ==
314       GST_STATE_CHANGE_SUCCESS);
315
316   /* try to set non interlaced caps */
317   deinterlace_set_string_caps_and_check (CAPS_YVYU, FALSE);
318   deinterlace_set_string_caps_and_check (CAPS_YUY2, FALSE);
319   deinterlace_set_string_caps_and_check (CAPS_YVYU_IMAGE, FALSE);
320   deinterlace_set_string_caps_and_check (CAPS_YUY2_IMAGE, FALSE);
321
322   /* now try to set interlaced caps */
323   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED, TRUE);
324   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED, TRUE);
325   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED_IMAGE, TRUE);
326   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED_IMAGE, TRUE);
327
328   /* cleanup */
329   gst_object_unref (sinkpad);
330   gst_object_unref (srcpad);
331   fail_unless (gst_element_set_state (deinterlace, GST_STATE_NULL) ==
332       GST_STATE_CHANGE_SUCCESS);
333   gst_object_unref (deinterlace);
334 }
335
336 GST_END_TEST;
337
338 GST_START_TEST (test_mode_forced_accept_caps)
339 {
340   setup_deinterlace ();
341
342   /* forced mode */
343   g_object_set (deinterlace, "mode", 1, NULL);
344   fail_unless (gst_element_set_state (deinterlace, GST_STATE_PLAYING) ==
345       GST_STATE_CHANGE_SUCCESS);
346
347   /* try to set non interlaced caps */
348   deinterlace_set_string_caps_and_check (CAPS_YVYU, TRUE);
349   deinterlace_set_string_caps_and_check (CAPS_YUY2, TRUE);
350   deinterlace_set_string_caps_and_check (CAPS_YVYU_IMAGE, TRUE);
351   deinterlace_set_string_caps_and_check (CAPS_YUY2_IMAGE, TRUE);
352
353   /* now try to set interlaced caps */
354   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED, TRUE);
355   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED, TRUE);
356   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED_IMAGE, TRUE);
357   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED_IMAGE, TRUE);
358
359   /* cleanup */
360   gst_object_unref (sinkpad);
361   gst_object_unref (srcpad);
362   fail_unless (gst_element_set_state (deinterlace, GST_STATE_NULL) ==
363       GST_STATE_CHANGE_SUCCESS);
364   gst_object_unref (deinterlace);
365 }
366
367 GST_END_TEST;
368
369 GST_START_TEST (test_mode_disabled_accept_caps)
370 {
371   setup_deinterlace ();
372
373   /* disabled mode */
374   g_object_set (deinterlace, "mode", 2, NULL);
375   fail_unless (gst_element_set_state (deinterlace, GST_STATE_PLAYING) ==
376       GST_STATE_CHANGE_SUCCESS);
377
378   /* try to set non interlaced caps */
379   deinterlace_set_string_caps_and_check (CAPS_YVYU, FALSE);
380   deinterlace_set_string_caps_and_check (CAPS_YUY2, FALSE);
381   deinterlace_set_string_caps_and_check (CAPS_YVYU_IMAGE, FALSE);
382   deinterlace_set_string_caps_and_check (CAPS_YUY2_IMAGE, FALSE);
383
384   /* now try to set interlaced caps */
385   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED, FALSE);
386   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED, FALSE);
387   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED_IMAGE, FALSE);
388   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED_IMAGE, FALSE);
389
390   /* cleanup */
391   gst_object_unref (sinkpad);
392   gst_object_unref (srcpad);
393   fail_unless (gst_element_set_state (deinterlace, GST_STATE_NULL) ==
394       GST_STATE_CHANGE_SUCCESS);
395   gst_object_unref (deinterlace);
396 }
397
398 GST_END_TEST;
399
400 GST_START_TEST (test_mode_disabled_passthrough)
401 {
402   /* 2 is disabled mode */
403   deinterlace_check_passthrough (2, CAPS_YUY2_INTERLACED);
404   deinterlace_check_passthrough (2, CAPS_YVYU_INTERLACED);
405   deinterlace_check_passthrough (2, CAPS_YUY2);
406   deinterlace_check_passthrough (2, CAPS_YVYU);
407
408   deinterlace_check_passthrough (2, CAPS_YUY2_INTERLACED_IMAGE);
409   deinterlace_check_passthrough (2, CAPS_YVYU_INTERLACED_IMAGE);
410   deinterlace_check_passthrough (2, CAPS_YUY2_IMAGE);
411   deinterlace_check_passthrough (2, CAPS_YVYU_IMAGE);
412 }
413
414 GST_END_TEST;
415
416 GST_START_TEST (test_mode_auto_deinterlaced_passthrough)
417 {
418   /* 0 is auto mode */
419   deinterlace_check_passthrough (0, CAPS_YUY2);
420   deinterlace_check_passthrough (0, CAPS_YVYU);
421   deinterlace_check_passthrough (0, CAPS_YUY2_IMAGE);
422   deinterlace_check_passthrough (0, CAPS_YVYU_IMAGE);
423 }
424
425 GST_END_TEST;
426
427 static Suite *
428 deinterlace_suite (void)
429 {
430   Suite *s = suite_create ("deinterlace");
431   TCase *tc_chain = tcase_create ("general");
432
433   suite_add_tcase (s, tc_chain);
434   tcase_set_timeout (tc_chain, 180);
435   tcase_add_test (tc_chain, test_create_and_unref);
436   tcase_add_test (tc_chain, test_mode_auto_accept_caps);
437   tcase_add_test (tc_chain, test_mode_forced_accept_caps);
438   tcase_add_test (tc_chain, test_mode_disabled_accept_caps);
439   tcase_add_test (tc_chain, test_mode_disabled_passthrough);
440   tcase_add_test (tc_chain, test_mode_auto_deinterlaced_passthrough);
441
442   return s;
443 }
444
445 GST_CHECK_MAIN (deinterlace);