Tizen 2.0 Release
[framework/multimedia/gst-plugins-good0.10.git] / tests / check / pipelines / tagschecking.c
1 /* GStreamer
2  * Copyright (C) 2008 Nokia Corporation. (contact <stefan.kost@nokia.com>)
3  * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <gst/check/gstcheck.h>
22
23 static GstTagList *received_tags = NULL;
24
25 static gboolean
26 bus_handler (GstBus * bus, GstMessage * message, gpointer data)
27 {
28   GMainLoop *loop = (GMainLoop *) data;
29
30   switch (message->type) {
31     case GST_MESSAGE_EOS:
32       g_main_loop_quit (loop);
33       break;
34     case GST_MESSAGE_WARNING:
35     case GST_MESSAGE_ERROR:{
36       GError *gerror;
37
38       gchar *debug;
39
40       gst_message_parse_error (message, &gerror, &debug);
41       gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
42       g_error_free (gerror);
43       g_free (debug);
44       g_main_loop_quit (loop);
45       break;
46     }
47     case GST_MESSAGE_TAG:{
48       if (received_tags == NULL) {
49         gst_message_parse_tag (message, &received_tags);
50       } else {
51         GstTagList *tl = NULL, *ntl = NULL;
52
53         gst_message_parse_tag (message, &tl);
54         if (tl) {
55           ntl = gst_tag_list_merge (received_tags, tl, GST_TAG_MERGE_PREPEND);
56           if (ntl) {
57             GST_LOG ("taglists merged: %" GST_PTR_FORMAT, ntl);
58             gst_tag_list_free (received_tags);
59             received_tags = ntl;
60           }
61           gst_tag_list_free (tl);
62         }
63       }
64       break;
65     }
66     default:
67       break;
68   }
69
70   return TRUE;
71 }
72
73 /*
74  * Creates a pipeline in the form:
75  * fakesrc num-buffers=1 ! caps ! muxer ! filesink location=file
76  *
77  * And sets the tags in tag_str into the muxer via tagsetter.
78  */
79 static void
80 test_mux_tags (const gchar * tag_str, const gchar * caps,
81     const gchar * muxer, const gchar * file)
82 {
83   GstElement *pipeline;
84   GstBus *bus;
85   GMainLoop *loop;
86   GstTagList *sent_tags;
87   GstElement *mux;
88   GstTagSetter *setter;
89   gchar *launch_str;
90   guint bus_watch = 0;
91
92   GST_DEBUG ("testing xmp muxing on : %s", muxer);
93
94   launch_str = g_strdup_printf ("fakesrc num-buffers=1 ! %s ! %s name=mux ! "
95       "filesink location=%s name=sink", caps, muxer, file);
96   pipeline = gst_parse_launch (launch_str, NULL);
97   g_free (launch_str);
98   fail_unless (pipeline != NULL);
99
100   mux = gst_bin_get_by_name (GST_BIN (pipeline), "mux");
101   fail_unless (mux != NULL);
102
103   loop = g_main_loop_new (NULL, TRUE);
104   fail_unless (loop != NULL);
105
106   bus = gst_element_get_bus (pipeline);
107   fail_unless (bus != NULL);
108   bus_watch = gst_bus_add_watch (bus, bus_handler, loop);
109   gst_object_unref (bus);
110
111   gst_element_set_state (pipeline, GST_STATE_READY);
112
113   setter = GST_TAG_SETTER (mux);
114   fail_unless (setter != NULL);
115   sent_tags = gst_structure_from_string (tag_str, NULL);
116   fail_unless (sent_tags != NULL);
117   gst_tag_setter_merge_tags (setter, sent_tags, GST_TAG_MERGE_REPLACE);
118   gst_tag_list_free (sent_tags);
119
120   gst_element_set_state (pipeline, GST_STATE_PLAYING);
121   g_main_loop_run (loop);
122
123   gst_element_set_state (pipeline, GST_STATE_NULL);
124
125   g_main_loop_unref (loop);
126   g_object_unref (mux);
127   g_object_unref (pipeline);
128   g_source_remove (bus_watch);
129 }
130
131 /*
132  * Makes a pipeline in the form:
133  * filesrc location=file ! demuxer ! fakesink
134  *
135  * And gets the tags that are posted on the bus to compare
136  * with the tags in 'tag_str'
137  */
138 static void
139 test_demux_tags (const gchar * tag_str, const gchar * demuxer,
140     const gchar * file)
141 {
142   GstElement *pipeline;
143   GstBus *bus;
144   GMainLoop *loop;
145   GstTagList *sent_tags;
146   gint i, j, n_recv, n_sent;
147   const gchar *name_sent, *name_recv;
148   const GValue *value_sent, *value_recv;
149   gboolean found;
150   gint comparison;
151   GstElement *demux;
152   gchar *launch_str;
153   guint bus_watch = 0;
154
155   GST_DEBUG ("testing tags : %s", tag_str);
156
157   if (received_tags) {
158     gst_tag_list_free (received_tags);
159     received_tags = NULL;
160   }
161
162   launch_str = g_strdup_printf ("filesrc location=%s ! %s name=demux ! "
163       "fakesink", file, demuxer);
164   pipeline = gst_parse_launch (launch_str, NULL);
165   g_free (launch_str);
166   fail_unless (pipeline != NULL);
167
168   demux = gst_bin_get_by_name (GST_BIN (pipeline), "demux");
169   fail_unless (demux != NULL);
170
171   loop = g_main_loop_new (NULL, TRUE);
172   fail_unless (loop != NULL);
173
174   bus = gst_element_get_bus (pipeline);
175   fail_unless (bus != NULL);
176   bus_watch = gst_bus_add_watch (bus, bus_handler, loop);
177   gst_object_unref (bus);
178
179   sent_tags = gst_structure_from_string (tag_str, NULL);
180   fail_unless (sent_tags != NULL);
181
182   gst_element_set_state (pipeline, GST_STATE_PLAYING);
183   g_main_loop_run (loop);
184
185   GST_DEBUG ("mainloop done : %p", received_tags);
186
187   /* verify tags */
188   fail_unless (received_tags != NULL);
189   n_recv = gst_structure_n_fields (received_tags);
190   n_sent = gst_structure_n_fields (sent_tags);
191   fail_unless (n_recv >= n_sent);
192   /* FIXME: compare taglits values */
193   for (i = 0; i < n_sent; i++) {
194     name_sent = gst_structure_nth_field_name (sent_tags, i);
195     value_sent = gst_structure_get_value (sent_tags, name_sent);
196     found = FALSE;
197     for (j = 0; j < n_recv; j++) {
198       name_recv = gst_structure_nth_field_name (received_tags, j);
199       if (!strcmp (name_sent, name_recv)) {
200         value_recv = gst_structure_get_value (received_tags, name_recv);
201         comparison = gst_value_compare (value_sent, value_recv);
202         if (comparison != GST_VALUE_EQUAL) {
203           gchar *vs = g_strdup_value_contents (value_sent);
204           gchar *vr = g_strdup_value_contents (value_recv);
205           GST_DEBUG ("sent = %s:'%s', recv = %s:'%s'",
206               G_VALUE_TYPE_NAME (value_sent), vs,
207               G_VALUE_TYPE_NAME (value_recv), vr);
208           g_free (vs);
209           g_free (vr);
210         }
211         fail_unless (comparison == GST_VALUE_EQUAL,
212             "tag item %s has been received with different type or value",
213             name_sent);
214         found = TRUE;
215         break;
216       }
217     }
218     fail_unless (found, "tag item %s is lost", name_sent);
219   }
220
221   gst_tag_list_free (received_tags);
222   received_tags = NULL;
223   gst_tag_list_free (sent_tags);
224
225   gst_element_set_state (pipeline, GST_STATE_NULL);
226
227   g_main_loop_unref (loop);
228   g_object_unref (demux);
229   g_object_unref (pipeline);
230   g_source_remove (bus_watch);
231 }
232
233 /*
234  * Tests if the muxer/demuxer pair can serialize the tags in 'tag_str'
235  * to a file and recover them correctly.
236  *
237  * 'caps' are used to assure the muxer accepts the fake buffer fakesrc
238  * will send to it.
239  */
240 static void
241 test_tags (const gchar * tag_str, const gchar * caps, const gchar * muxer,
242     const gchar * demuxer)
243 {
244   gchar *tmpfile;
245   gchar *tmp;
246
247   tmp = g_strdup_printf ("%s%d", "gst-check-xmp-test-", g_random_int ());
248   tmpfile = g_build_filename (g_get_tmp_dir (), tmp, NULL);
249   g_free (tmp);
250
251   GST_DEBUG ("testing tags : %s", tag_str);
252   test_mux_tags (tag_str, caps, muxer, tmpfile);
253   test_demux_tags (tag_str, demuxer, tmpfile);
254   g_free (tmpfile);
255 }
256
257 #define H264_CAPS "video/x-h264, width=(int)320, height=(int)240," \
258                   " framerate=(fraction)30/1, codec_data=(buffer)" \
259                   "01401592ffe10017674d401592540a0fd8088000000300" \
260                   "8000001e478b175001000468ee3c80, stream-format=(string)avc"
261
262 #define COMMON_TAGS \
263     "taglist,title=test_title,"    \
264     "artist=test_artist,"          \
265     "keywords=\"key1,key2\","      \
266     "description=test_desc"
267
268 GST_START_TEST (test_common_tags)
269 {
270   if (!gst_default_registry_check_feature_version ("qtdemux", 0, 10, 23)) {
271     GST_INFO ("Skipping test, qtdemux either not available or too old");
272     return;
273   }
274   test_tags (COMMON_TAGS, H264_CAPS, "qtmux", "qtdemux");
275   test_tags (COMMON_TAGS, H264_CAPS, "mp4mux", "qtdemux");
276   test_tags (COMMON_TAGS, H264_CAPS, "gppmux", "qtdemux");
277 }
278
279 GST_END_TEST;
280
281 #define GEO_LOCATION_TAGS \
282     "taglist,geo-location-country=Brazil,"    \
283       "geo-location-city=\"Campina Grande\"," \
284       "geo-location-sublocation=Bodocongo,"   \
285       "geo-location-latitude=-12.125,"        \
286       "geo-location-longitude=56.75,"         \
287       "geo-location-elevation=327.5"
288
289 GST_START_TEST (test_geo_location_tags)
290 {
291   if (!gst_default_registry_check_feature_version ("qtdemux", 0, 10, 23)) {
292     GST_INFO ("Skipping test, qtdemux either not available or too old");
293     return;
294   }
295   test_tags (GEO_LOCATION_TAGS, H264_CAPS, "qtmux", "qtdemux");
296   test_tags (GEO_LOCATION_TAGS, H264_CAPS, "mp4mux", "qtdemux");
297   test_tags (GEO_LOCATION_TAGS, H264_CAPS, "gppmux", "qtdemux");
298 }
299
300 GST_END_TEST;
301
302
303 #define USER_TAGS \
304     "taglist,user-rating=(uint)85"
305
306 GST_START_TEST (test_user_tags)
307 {
308   if (!gst_default_registry_check_feature_version ("qtdemux", 0, 10, 23)) {
309     GST_INFO ("Skipping test, qtdemux either not available or too old");
310     return;
311   }
312
313   test_tags (USER_TAGS, H264_CAPS, "qtmux", "qtdemux");
314   test_tags (USER_TAGS, H264_CAPS, "mp4mux", "qtdemux");
315   test_tags (USER_TAGS, H264_CAPS, "gppmux", "qtdemux");
316 }
317
318 GST_END_TEST;
319
320 static Suite *
321 metadata_suite (void)
322 {
323   Suite *s = suite_create ("tagschecking");
324
325   TCase *tc_chain = tcase_create ("general");
326
327   /* time out after 60s, not the default 3 */
328   tcase_set_timeout (tc_chain, 60);
329
330   suite_add_tcase (s, tc_chain);
331   tcase_add_test (tc_chain, test_common_tags);
332   tcase_add_test (tc_chain, test_geo_location_tags);
333   tcase_add_test (tc_chain, test_user_tags);
334
335   return s;
336 }
337
338 int
339 main (int argc, char **argv)
340 {
341   int nf;
342
343   Suite *s = metadata_suite ();
344
345   SRunner *sr = srunner_create (s);
346
347   gst_check_init (&argc, &argv);
348
349   srunner_run_all (sr, CK_NORMAL);
350   nf = srunner_ntests_failed (sr);
351   srunner_free (sr);
352
353   return nf;
354 }