258c8750ad9bd74264435fdb392bd1cee66ca172
[platform/upstream/gstreamer.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   GstVideoInfo info;
32
33   fail_unless (gst_caps_is_fixed (caps));
34   fail_unless (gst_video_info_from_caps (&info, caps));
35
36   return GST_VIDEO_INFO_IS_INTERLACED (&info);
37 }
38
39 GST_START_TEST (test_create_and_unref)
40 {
41   GstElement *deinterlace;
42
43   deinterlace = gst_element_factory_make ("deinterlace", NULL);
44   fail_unless (deinterlace != NULL);
45
46   gst_element_set_state (deinterlace, GST_STATE_NULL);
47   gst_object_unref (deinterlace);
48 }
49
50 GST_END_TEST;
51
52 #define CAPS_VIDEO_COMMON \
53     "width=(int)800, height=(int)600, framerate=(fraction)15/1"
54
55 #define CAPS_IMAGE_COMMON \
56     "width=(int)3200, height=(int)3400, framerate=(fraction)0/1"
57
58 #define CAPS_YUY2 \
59     "video/x-raw, " \
60     CAPS_VIDEO_COMMON ", " \
61     "format=(string)YUY2"
62
63 #define CAPS_YUY2_INTERLACED \
64     CAPS_YUY2 ", " \
65     "interlace-mode=interleaved"
66
67 #define CAPS_YVYU \
68     "video/x-raw, " \
69     CAPS_VIDEO_COMMON ", " \
70     "format=(string)YVYU"
71
72 #define CAPS_YVYU_INTERLACED \
73     CAPS_YVYU ", " \
74     "interlace-mode=interleaved"
75
76 #define CAPS_YUY2_IMAGE \
77     "video/x-raw, " \
78     CAPS_IMAGE_COMMON ", " \
79     "format=(string)YUY2"
80
81 #define CAPS_YUY2_INTERLACED_IMAGE \
82     CAPS_YUY2_IMAGE ", " \
83     "interlace-mode=interleaved"
84
85 #define CAPS_YVYU_IMAGE \
86     "video/x-raw, " \
87     CAPS_IMAGE_COMMON ", " \
88     "format=(string)YVYU"
89
90 #define CAPS_YVYU_INTERLACED_IMAGE \
91     CAPS_YVYU_IMAGE ", " \
92     "interlace-mode=interleaved"
93
94 static GstElement *deinterlace;
95 static GstPad *srcpad;
96 static GstPad *sinkpad;
97
98 static GstElement *pipeline;
99
100 /* sets up deinterlace and shortcut pointers to its pads */
101 static void
102 setup_deinterlace (void)
103 {
104   deinterlace = gst_element_factory_make ("deinterlace", NULL);
105   fail_unless (deinterlace != NULL);
106
107   sinkpad = gst_element_get_static_pad (deinterlace, "sink");
108   fail_unless (sinkpad != NULL);
109   srcpad = gst_element_get_static_pad (deinterlace, "src");
110   fail_unless (srcpad != NULL);
111 }
112
113 /* sets up a basic test pipeline containing:
114  *
115  * videotestsrc ! capsfilter ! deinterlace ! fakesink
116  *
117  * The parameters set the capsfilter caps and the num-buffers
118  * property of videotestsrc
119  *
120  * It is useful for adding buffer probes to deinterlace pads
121  * and validating inputs/outputs
122  */
123 static void
124 setup_test_pipeline (gint mode, GstCaps * infiltercaps, GstCaps * outfiltercaps,
125     gint numbuffers)
126 {
127   GstElement *src;
128   GstElement *infilter;
129   GstElement *outfilter;
130   GstElement *sink;
131
132   setup_deinterlace ();
133
134   pipeline = gst_pipeline_new ("pipeline");
135   src = gst_element_factory_make ("videotestsrc", NULL);
136   infilter = gst_element_factory_make ("capsfilter", "infilter");
137   outfilter = gst_element_factory_make ("capsfilter", "outfilter");
138   sink = gst_element_factory_make ("fakesink", NULL);
139   fail_if (src == NULL);
140   fail_if (infilter == NULL);
141   fail_if (outfilter == NULL);
142   fail_if (sink == NULL);
143
144   fail_unless (gst_bin_add (GST_BIN (pipeline), src));
145   fail_unless (gst_bin_add (GST_BIN (pipeline), infilter));
146   fail_unless (gst_bin_add (GST_BIN (pipeline), deinterlace));
147   fail_unless (gst_bin_add (GST_BIN (pipeline), outfilter));
148   fail_unless (gst_bin_add (GST_BIN (pipeline), sink));
149
150   /* set the properties */
151   g_object_set (deinterlace, "mode", mode, NULL);
152   if (numbuffers > 0)
153     g_object_set (src, "num-buffers", numbuffers, NULL);
154   if (infiltercaps)
155     g_object_set (infilter, "caps", infiltercaps, NULL);
156   if (outfiltercaps)
157     g_object_set (outfilter, "caps", outfiltercaps, NULL);
158
159   fail_unless (gst_element_link_many (src, infilter, deinterlace, outfilter,
160           sink, NULL));
161   if (infiltercaps)
162     gst_caps_unref (infiltercaps);
163   if (outfiltercaps)
164     gst_caps_unref (outfiltercaps);
165 }
166
167 /*
168  * Checks if 2 buffers are equal
169  *
170  * Equals means same data
171  */
172 static gboolean
173 test_buffer_equals (GstBuffer * buf_a, GstBuffer * buf_b)
174 {
175   GstMapInfo m1, m2;
176   gboolean res = FALSE;
177
178   gst_buffer_map (buf_a, &m1, GST_MAP_READ);
179   gst_buffer_map (buf_b, &m2, GST_MAP_READ);
180
181   if (m1.size == m2.size) {
182     res = memcmp (m1.data, m2.data, m1.size) == 0;
183   }
184   gst_buffer_unmap (buf_a, &m1);
185   gst_buffer_unmap (buf_b, &m2);
186
187   return res;
188 }
189
190 static GstPadProbeReturn
191 sinkpad_enqueue_buffer (GstPad * pad, GstPadProbeInfo * info, gpointer data)
192 {
193   GQueue *queue = (GQueue *) data;
194   GstBuffer *buf = GST_PAD_PROBE_INFO_BUFFER (info);
195
196   /* enqueue a copy for being compared later */
197   g_queue_push_tail (queue, gst_buffer_copy (buf));
198
199   return GST_PAD_PROBE_OK;
200 }
201
202 /*
203  * pad buffer probe that compares the buffer with the top one
204  * in the GQueue passed as the user data
205  */
206 static GstPadProbeReturn
207 srcpad_dequeue_and_compare_buffer (GstPad * pad, GstPadProbeInfo * info,
208     gpointer data)
209 {
210   GQueue *queue = (GQueue *) data;
211   GstBuffer *buf = GST_PAD_PROBE_INFO_BUFFER (info);
212   GstBuffer *queue_buf;
213
214   queue_buf = (GstBuffer *) g_queue_pop_head (queue);
215   fail_if (queue_buf == NULL);
216
217   fail_unless (test_buffer_equals (buf, queue_buf));
218
219   gst_buffer_unref (queue_buf);
220
221   return GST_PAD_PROBE_OK;
222 }
223
224 /*
225  * Utility function that sets up a pipeline with deinterlace for
226  * validanting that it operates in passthrough mode when receiving
227  * data with 'infiltercaps' as the input caps and operating in 'mode' mode
228  */
229 static void
230 deinterlace_check_passthrough (gint mode, const gchar * infiltercaps)
231 {
232   GstMessage *msg;
233   GQueue *queue;
234   GstCaps *incaps = NULL;
235
236   if (infiltercaps)
237     incaps = gst_caps_from_string (infiltercaps);
238
239   setup_test_pipeline (mode, incaps, NULL, 20);
240
241   queue = g_queue_new ();
242
243   /* set up probes for testing */
244   gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BUFFER, sinkpad_enqueue_buffer,
245       queue, NULL);
246   gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BUFFER,
247       srcpad_dequeue_and_compare_buffer, queue, NULL);
248
249   fail_unless (gst_element_set_state (pipeline, GST_STATE_PLAYING) !=
250       GST_STATE_CHANGE_FAILURE);
251
252   msg = gst_bus_poll (GST_ELEMENT_BUS (pipeline), GST_MESSAGE_EOS, -1);
253   gst_message_unref (msg);
254
255   /* queue should be empty */
256   fail_unless (g_queue_is_empty (queue));
257
258   fail_unless (gst_element_set_state (pipeline, GST_STATE_NULL) ==
259       GST_STATE_CHANGE_SUCCESS);
260   gst_object_unref (pipeline);
261   g_queue_free (queue);
262 }
263
264 /*
265  * Sets the caps on deinterlace sinkpad and validates the
266  * caps that is set on the srcpad
267  */
268 static void
269 deinterlace_set_caps_and_check (GstCaps * input, gboolean must_deinterlace)
270 {
271   GstCaps *othercaps = NULL;
272
273   fail_unless (gst_pad_set_caps (sinkpad, input));
274   g_object_get (srcpad, "caps", &othercaps, NULL);
275
276   if (must_deinterlace) {
277     fail_if (gst_caps_is_interlaced (othercaps));
278   } else {
279     GstStructure *s;
280
281     fail_unless (gst_caps_is_interlaced (input) ==
282         gst_caps_is_interlaced (othercaps));
283
284     othercaps = gst_caps_make_writable (othercaps);
285     s = gst_caps_get_structure (othercaps, 0);
286     gst_structure_remove_field (s, "interlaced");
287
288     input = gst_caps_make_writable (input);
289     s = gst_caps_get_structure (input, 0);
290     gst_structure_remove_field (s, "interlaced");
291
292     fail_unless (gst_caps_is_equal (input, othercaps));
293   }
294   gst_caps_unref (input);
295   gst_caps_unref (othercaps);
296 }
297
298 static void
299 deinterlace_set_string_caps_and_check (const gchar * input,
300     gboolean must_deinterlace)
301 {
302   deinterlace_set_caps_and_check (gst_caps_from_string (input),
303       must_deinterlace);
304 }
305
306 GST_START_TEST (test_mode_auto_accept_caps)
307 {
308   setup_deinterlace ();
309
310   /* auto mode */
311   g_object_set (deinterlace, "mode", 0, NULL);
312   fail_unless (gst_element_set_state (deinterlace, GST_STATE_PLAYING) ==
313       GST_STATE_CHANGE_SUCCESS);
314
315   /* try to set non interlaced caps */
316   deinterlace_set_string_caps_and_check (CAPS_YVYU, FALSE);
317   deinterlace_set_string_caps_and_check (CAPS_YUY2, FALSE);
318   deinterlace_set_string_caps_and_check (CAPS_YVYU_IMAGE, FALSE);
319   deinterlace_set_string_caps_and_check (CAPS_YUY2_IMAGE, FALSE);
320
321   /* now try to set interlaced caps */
322   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED, TRUE);
323   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED, TRUE);
324   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED_IMAGE, TRUE);
325   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED_IMAGE, TRUE);
326
327   /* cleanup */
328   gst_object_unref (sinkpad);
329   gst_object_unref (srcpad);
330   fail_unless (gst_element_set_state (deinterlace, GST_STATE_NULL) ==
331       GST_STATE_CHANGE_SUCCESS);
332   gst_object_unref (deinterlace);
333 }
334
335 GST_END_TEST;
336
337 GST_START_TEST (test_mode_forced_accept_caps)
338 {
339   setup_deinterlace ();
340
341   /* forced mode */
342   g_object_set (deinterlace, "mode", 1, NULL);
343   fail_unless (gst_element_set_state (deinterlace, GST_STATE_PLAYING) ==
344       GST_STATE_CHANGE_SUCCESS);
345
346   /* try to set non interlaced caps */
347   deinterlace_set_string_caps_and_check (CAPS_YVYU, TRUE);
348   deinterlace_set_string_caps_and_check (CAPS_YUY2, TRUE);
349   deinterlace_set_string_caps_and_check (CAPS_YVYU_IMAGE, TRUE);
350   deinterlace_set_string_caps_and_check (CAPS_YUY2_IMAGE, TRUE);
351
352   /* now try to set interlaced caps */
353   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED, TRUE);
354   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED, TRUE);
355   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED_IMAGE, TRUE);
356   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED_IMAGE, TRUE);
357
358   /* cleanup */
359   gst_object_unref (sinkpad);
360   gst_object_unref (srcpad);
361   fail_unless (gst_element_set_state (deinterlace, GST_STATE_NULL) ==
362       GST_STATE_CHANGE_SUCCESS);
363   gst_object_unref (deinterlace);
364 }
365
366 GST_END_TEST;
367
368 GST_START_TEST (test_mode_disabled_accept_caps)
369 {
370   setup_deinterlace ();
371
372   /* disabled mode */
373   g_object_set (deinterlace, "mode", 2, NULL);
374   fail_unless (gst_element_set_state (deinterlace, GST_STATE_PLAYING) ==
375       GST_STATE_CHANGE_SUCCESS);
376
377   /* try to set non interlaced caps */
378   deinterlace_set_string_caps_and_check (CAPS_YVYU, FALSE);
379   deinterlace_set_string_caps_and_check (CAPS_YUY2, FALSE);
380   deinterlace_set_string_caps_and_check (CAPS_YVYU_IMAGE, FALSE);
381   deinterlace_set_string_caps_and_check (CAPS_YUY2_IMAGE, FALSE);
382
383   /* now try to set interlaced caps */
384   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED, FALSE);
385   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED, FALSE);
386   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED_IMAGE, FALSE);
387   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED_IMAGE, FALSE);
388
389   /* cleanup */
390   gst_object_unref (sinkpad);
391   gst_object_unref (srcpad);
392   fail_unless (gst_element_set_state (deinterlace, GST_STATE_NULL) ==
393       GST_STATE_CHANGE_SUCCESS);
394   gst_object_unref (deinterlace);
395 }
396
397 GST_END_TEST;
398
399 GST_START_TEST (test_mode_disabled_passthrough)
400 {
401   /* 2 is disabled mode */
402   deinterlace_check_passthrough (2, CAPS_YUY2_INTERLACED);
403   deinterlace_check_passthrough (2, CAPS_YVYU_INTERLACED);
404   deinterlace_check_passthrough (2, CAPS_YUY2);
405   deinterlace_check_passthrough (2, CAPS_YVYU);
406
407   deinterlace_check_passthrough (2, CAPS_YUY2_INTERLACED_IMAGE);
408   deinterlace_check_passthrough (2, CAPS_YVYU_INTERLACED_IMAGE);
409   deinterlace_check_passthrough (2, CAPS_YUY2_IMAGE);
410   deinterlace_check_passthrough (2, CAPS_YVYU_IMAGE);
411 }
412
413 GST_END_TEST;
414
415 GST_START_TEST (test_mode_auto_deinterlaced_passthrough)
416 {
417   /* 0 is auto mode */
418   deinterlace_check_passthrough (0, CAPS_YUY2);
419   deinterlace_check_passthrough (0, CAPS_YVYU);
420   deinterlace_check_passthrough (0, CAPS_YUY2_IMAGE);
421   deinterlace_check_passthrough (0, CAPS_YVYU_IMAGE);
422 }
423
424 GST_END_TEST;
425
426 static Suite *
427 deinterlace_suite (void)
428 {
429   Suite *s = suite_create ("deinterlace");
430   TCase *tc_chain = tcase_create ("general");
431
432   suite_add_tcase (s, tc_chain);
433   tcase_set_timeout (tc_chain, 180);
434
435   if (!gst_registry_check_feature_version (gst_registry_get (), "deinterlace",
436           GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO)) {
437     GST_ERROR ("FIXME: port deinterlace element");
438     return s;
439   }
440
441   tcase_add_test (tc_chain, test_create_and_unref);
442   tcase_add_test (tc_chain, test_mode_auto_accept_caps);
443   tcase_add_test (tc_chain, test_mode_forced_accept_caps);
444   tcase_add_test (tc_chain, test_mode_disabled_accept_caps);
445   tcase_add_test (tc_chain, test_mode_disabled_passthrough);
446   tcase_add_test (tc_chain, test_mode_auto_deinterlaced_passthrough);
447
448   return s;
449 }
450
451 GST_CHECK_MAIN (deinterlace);