deinterlace: the field in caps is "interlace-mode" not "interlace-method"
[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),
253       GST_MESSAGE_ERROR | GST_MESSAGE_EOS, -1);
254   if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
255     GST_ERROR ("ERROR: %" GST_PTR_FORMAT, msg);
256     fail ("Unexpected error message");
257   }
258   gst_message_unref (msg);
259
260   /* queue should be empty */
261   fail_unless (g_queue_is_empty (queue));
262
263   fail_unless (gst_element_set_state (pipeline, GST_STATE_NULL) ==
264       GST_STATE_CHANGE_SUCCESS);
265   gst_object_unref (pipeline);
266   g_queue_free (queue);
267 }
268
269 /*
270  * Sets the caps on deinterlace sinkpad and validates the
271  * caps that is set on the srcpad
272  */
273 static void
274 deinterlace_set_caps_and_check (GstCaps * input, gboolean must_deinterlace)
275 {
276   GstCaps *othercaps = NULL;
277
278   fail_unless (gst_pad_set_caps (sinkpad, input));
279   g_object_get (srcpad, "caps", &othercaps, NULL);
280
281   if (must_deinterlace) {
282     fail_if (gst_caps_is_interlaced (othercaps));
283   } else {
284     GstStructure *s;
285
286     fail_unless (gst_caps_is_interlaced (input) ==
287         gst_caps_is_interlaced (othercaps));
288
289     othercaps = gst_caps_make_writable (othercaps);
290     s = gst_caps_get_structure (othercaps, 0);
291     gst_structure_remove_field (s, "interlace-mode");
292
293     input = gst_caps_make_writable (input);
294     s = gst_caps_get_structure (input, 0);
295     gst_structure_remove_field (s, "interlace-mode");
296
297     fail_unless (gst_caps_is_equal (input, othercaps));
298   }
299   gst_caps_unref (input);
300   gst_caps_unref (othercaps);
301 }
302
303 static void
304 deinterlace_set_string_caps_and_check (const gchar * input,
305     gboolean must_deinterlace)
306 {
307   deinterlace_set_caps_and_check (gst_caps_from_string (input),
308       must_deinterlace);
309 }
310
311 GST_START_TEST (test_mode_auto_accept_caps)
312 {
313   setup_deinterlace ();
314
315   /* auto mode */
316   g_object_set (deinterlace, "mode", 0, NULL);
317   fail_unless (gst_element_set_state (deinterlace, GST_STATE_PLAYING) ==
318       GST_STATE_CHANGE_SUCCESS);
319
320   /* try to set non interlaced caps */
321   deinterlace_set_string_caps_and_check (CAPS_YVYU, FALSE);
322   deinterlace_set_string_caps_and_check (CAPS_YUY2, FALSE);
323   deinterlace_set_string_caps_and_check (CAPS_YVYU_IMAGE, FALSE);
324   deinterlace_set_string_caps_and_check (CAPS_YUY2_IMAGE, FALSE);
325
326   /* now try to set interlaced caps */
327   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED, TRUE);
328   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED, TRUE);
329   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED_IMAGE, TRUE);
330   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED_IMAGE, TRUE);
331
332   /* cleanup */
333   gst_object_unref (sinkpad);
334   gst_object_unref (srcpad);
335   fail_unless (gst_element_set_state (deinterlace, GST_STATE_NULL) ==
336       GST_STATE_CHANGE_SUCCESS);
337   gst_object_unref (deinterlace);
338 }
339
340 GST_END_TEST;
341
342 GST_START_TEST (test_mode_forced_accept_caps)
343 {
344   setup_deinterlace ();
345
346   /* forced mode */
347   g_object_set (deinterlace, "mode", 1, NULL);
348   fail_unless (gst_element_set_state (deinterlace, GST_STATE_PLAYING) ==
349       GST_STATE_CHANGE_SUCCESS);
350
351   /* try to set non interlaced caps */
352   deinterlace_set_string_caps_and_check (CAPS_YVYU, TRUE);
353   deinterlace_set_string_caps_and_check (CAPS_YUY2, TRUE);
354   deinterlace_set_string_caps_and_check (CAPS_YVYU_IMAGE, TRUE);
355   deinterlace_set_string_caps_and_check (CAPS_YUY2_IMAGE, TRUE);
356
357   /* now try to set interlaced caps */
358   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED, TRUE);
359   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED, TRUE);
360   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED_IMAGE, TRUE);
361   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED_IMAGE, TRUE);
362
363   /* cleanup */
364   gst_object_unref (sinkpad);
365   gst_object_unref (srcpad);
366   fail_unless (gst_element_set_state (deinterlace, GST_STATE_NULL) ==
367       GST_STATE_CHANGE_SUCCESS);
368   gst_object_unref (deinterlace);
369 }
370
371 GST_END_TEST;
372
373 GST_START_TEST (test_mode_disabled_accept_caps)
374 {
375   setup_deinterlace ();
376
377   /* disabled mode */
378   g_object_set (deinterlace, "mode", 2, NULL);
379   fail_unless (gst_element_set_state (deinterlace, GST_STATE_PLAYING) ==
380       GST_STATE_CHANGE_SUCCESS);
381
382   /* try to set non interlaced caps */
383   deinterlace_set_string_caps_and_check (CAPS_YVYU, FALSE);
384   deinterlace_set_string_caps_and_check (CAPS_YUY2, FALSE);
385   deinterlace_set_string_caps_and_check (CAPS_YVYU_IMAGE, FALSE);
386   deinterlace_set_string_caps_and_check (CAPS_YUY2_IMAGE, FALSE);
387
388   /* now try to set interlaced caps */
389   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED, FALSE);
390   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED, FALSE);
391   deinterlace_set_string_caps_and_check (CAPS_YVYU_INTERLACED_IMAGE, FALSE);
392   deinterlace_set_string_caps_and_check (CAPS_YUY2_INTERLACED_IMAGE, FALSE);
393
394   /* cleanup */
395   gst_object_unref (sinkpad);
396   gst_object_unref (srcpad);
397   fail_unless (gst_element_set_state (deinterlace, GST_STATE_NULL) ==
398       GST_STATE_CHANGE_SUCCESS);
399   gst_object_unref (deinterlace);
400 }
401
402 GST_END_TEST;
403
404 GST_START_TEST (test_mode_disabled_passthrough)
405 {
406   /* 2 is disabled mode */
407   deinterlace_check_passthrough (2, CAPS_YUY2_INTERLACED);
408   deinterlace_check_passthrough (2, CAPS_YVYU_INTERLACED);
409   deinterlace_check_passthrough (2, CAPS_YUY2);
410   deinterlace_check_passthrough (2, CAPS_YVYU);
411
412   deinterlace_check_passthrough (2, CAPS_YUY2_INTERLACED_IMAGE);
413   deinterlace_check_passthrough (2, CAPS_YVYU_INTERLACED_IMAGE);
414   deinterlace_check_passthrough (2, CAPS_YUY2_IMAGE);
415   deinterlace_check_passthrough (2, CAPS_YVYU_IMAGE);
416 }
417
418 GST_END_TEST;
419
420 GST_START_TEST (test_mode_auto_deinterlaced_passthrough)
421 {
422   /* 0 is auto mode */
423   deinterlace_check_passthrough (0, CAPS_YUY2);
424   deinterlace_check_passthrough (0, CAPS_YVYU);
425   deinterlace_check_passthrough (0, CAPS_YUY2_IMAGE);
426   deinterlace_check_passthrough (0, CAPS_YVYU_IMAGE);
427 }
428
429 GST_END_TEST;
430
431 static Suite *
432 deinterlace_suite (void)
433 {
434   Suite *s = suite_create ("deinterlace");
435   TCase *tc_chain = tcase_create ("general");
436
437   suite_add_tcase (s, tc_chain);
438   tcase_set_timeout (tc_chain, 180);
439
440   if (!gst_registry_check_feature_version (gst_registry_get (), "deinterlace",
441           GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO)) {
442     GST_ERROR ("FIXME: port deinterlace element");
443     return s;
444   }
445
446   tcase_add_test (tc_chain, test_create_and_unref);
447   tcase_add_test (tc_chain, test_mode_auto_accept_caps);
448   tcase_add_test (tc_chain, test_mode_forced_accept_caps);
449   tcase_add_test (tc_chain, test_mode_disabled_accept_caps);
450   tcase_add_test (tc_chain, test_mode_disabled_passthrough);
451   tcase_add_test (tc_chain, test_mode_auto_deinterlaced_passthrough);
452
453   return s;
454 }
455
456 GST_CHECK_MAIN (deinterlace);