Initialize Tizen 2.3
[framework/multimedia/gst-plugins-base0.10.git] / mobile / tests / check / libs / tag.c
1 /* GStreamer
2  *
3  * unit tests for the tag support library
4  *
5  * Copyright (C) 2006-2011 Tim-Philipp Müller <tim centricular net>
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 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <gst/check/gstcheck.h>
28
29 #include <gst/tag/tag.h>
30 #include <gst/base/gstbytewriter.h>
31 #include <string.h>
32 #include <locale.h>
33
34 GST_START_TEST (test_parse_extended_comment)
35 {
36   gchar *key, *val, *lang;
37
38   /* first check the g_return_val_if_fail conditions */
39   ASSERT_CRITICAL (gst_tag_parse_extended_comment (NULL, NULL, NULL, NULL,
40           FALSE));
41   ASSERT_CRITICAL (gst_tag_parse_extended_comment ("\377\000", NULL, NULL, NULL,
42           FALSE));
43
44   key = val = lang = NULL;
45   fail_unless (gst_tag_parse_extended_comment ("a=b", &key, &lang, &val,
46           FALSE) == TRUE);
47   fail_unless (key != NULL);
48   fail_unless (lang == NULL);
49   fail_unless (val != NULL);
50   fail_unless_equals_string (key, "a");
51   fail_unless_equals_string (val, "b");
52   g_free (key);
53   g_free (lang);
54   g_free (val);
55
56   key = val = lang = NULL;
57   fail_unless (gst_tag_parse_extended_comment ("a[l]=b", &key, &lang, &val,
58           FALSE) == TRUE);
59   fail_unless (key != NULL);
60   fail_unless (lang != NULL);
61   fail_unless (val != NULL);
62   fail_unless_equals_string (key, "a");
63   fail_unless_equals_string (lang, "l");
64   fail_unless_equals_string (val, "b");
65   g_free (key);
66   g_free (lang);
67   g_free (val);
68
69   key = val = lang = NULL;
70   fail_unless (gst_tag_parse_extended_comment ("foo=bar", &key, &lang, &val,
71           FALSE) == TRUE);
72   fail_unless (key != NULL);
73   fail_unless (lang == NULL);
74   fail_unless (val != NULL);
75   fail_unless_equals_string (key, "foo");
76   fail_unless_equals_string (val, "bar");
77   g_free (key);
78   g_free (lang);
79   g_free (val);
80
81   key = val = lang = NULL;
82   fail_unless (gst_tag_parse_extended_comment ("foo[fr]=bar", &key, &lang, &val,
83           FALSE) == TRUE);
84   fail_unless (key != NULL);
85   fail_unless (lang != NULL);
86   fail_unless (val != NULL);
87   fail_unless_equals_string (key, "foo");
88   fail_unless_equals_string (lang, "fr");
89   fail_unless_equals_string (val, "bar");
90   g_free (key);
91   g_free (lang);
92   g_free (val);
93
94   key = val = lang = NULL;
95   fail_unless (gst_tag_parse_extended_comment ("foo=[fr]bar", &key, &lang, &val,
96           FALSE) == TRUE);
97   fail_unless (key != NULL);
98   fail_unless (lang == NULL);
99   fail_unless (val != NULL);
100   fail_unless_equals_string (key, "foo");
101   fail_unless_equals_string (val, "[fr]bar");
102   g_free (key);
103   g_free (lang);
104   g_free (val);
105
106   /* test NULL for output locations */
107   fail_unless (gst_tag_parse_extended_comment ("foo[fr]=bar", NULL, NULL, NULL,
108           FALSE) == TRUE);
109
110   /* test strict mode (key must be specified) */
111   fail_unless (gst_tag_parse_extended_comment ("foo[fr]=bar", NULL, NULL, NULL,
112           TRUE) == TRUE);
113   fail_unless (gst_tag_parse_extended_comment ("foo=bar", NULL, NULL, NULL,
114           TRUE) == TRUE);
115   fail_unless (gst_tag_parse_extended_comment ("foobar", NULL, NULL, NULL,
116           TRUE) == FALSE);
117
118   /* test non-strict mode (if there's no key, that's fine too) */
119   fail_unless (gst_tag_parse_extended_comment ("foobar", NULL, NULL, NULL,
120           FALSE) == TRUE);
121   fail_unless (gst_tag_parse_extended_comment ("[fr]bar", NULL, NULL, NULL,
122           FALSE) == TRUE);
123
124   key = val = lang = NULL;
125   fail_unless (gst_tag_parse_extended_comment ("[fr]bar", &key, &lang, &val,
126           FALSE) == TRUE);
127   fail_unless (key == NULL);
128   fail_unless (lang == NULL);
129   fail_unless (val != NULL);
130   fail_unless_equals_string (val, "[fr]bar");
131   g_free (key);
132   g_free (lang);
133   g_free (val);
134 }
135
136 GST_END_TEST;
137
138 #define ASSERT_TAG_LIST_HAS_STRING(list,field,string)                      \
139   {                                                                        \
140     gboolean got_match = FALSE;                                            \
141     guint i, size;                                                         \
142                                                                            \
143     fail_unless (gst_tag_list_get_tag_size (list,field) > 0);              \
144     size = gst_tag_list_get_tag_size (list,field);                         \
145     for (i = 0; i < size; ++i) {                                           \
146       gchar *___s = NULL;                                                  \
147                                                                            \
148       fail_unless (gst_tag_list_get_string_index (list, field, i, &___s)); \
149       fail_unless (___s != NULL);                                          \
150       if (g_str_equal (___s, string)) {                                    \
151         got_match = TRUE;                                                  \
152         g_free (___s);                                                     \
153         break;                                                             \
154       }                                                                    \
155       g_free (___s);                                                       \
156     }                                                                      \
157     fail_unless (got_match);                                               \
158   }
159
160 #define ASSERT_TAG_LIST_HAS_UINT(list,field,num)                           \
161   {                                                                        \
162     guint ___n;                                                            \
163                                                                            \
164     fail_unless (gst_tag_list_get_tag_size (list,field) > 0);              \
165     fail_unless (gst_tag_list_get_tag_size (list,field) == 1);             \
166     fail_unless (gst_tag_list_get_uint_index (list, field, 0, &___n));     \
167     fail_unless_equals_int (___n, num);                                    \
168   }
169
170 #define MATCH_DOUBLE(p1, p2) ((p1 < p2 + 1e-6) && (p2 < p1 + 1e-6))
171 #define ASSERT_TAG_LIST_HAS_DOUBLE(list,field,d)                           \
172   {                                                                        \
173     gdouble ___d;                                                          \
174                                                                            \
175     fail_unless (gst_tag_list_get_tag_size (list,field) > 0);              \
176     fail_unless (gst_tag_list_get_tag_size (list,field) == 1);             \
177     fail_unless (gst_tag_list_get_double_index (list, field, 0, &___d));   \
178     fail_unless (MATCH_DOUBLE (d, ___d),                                   \
179         "%f does not match expected %f", ___d, d);                         \
180   }
181
182 GST_START_TEST (test_musicbrainz_tag_registration)
183 {
184   GstTagList *list;
185
186   gst_tag_register_musicbrainz_tags ();
187
188   list = gst_tag_list_new ();
189
190   /* musicbrainz tags aren't registered yet */
191   gst_vorbis_tag_add (list, "MUSICBRAINZ_TRACKID", "123456");
192   gst_vorbis_tag_add (list, "MUSICBRAINZ_ARTISTID", "234567");
193   gst_vorbis_tag_add (list, "MUSICBRAINZ_ALBUMID", "345678");
194   gst_vorbis_tag_add (list, "MUSICBRAINZ_ALBUMARTISTID", "4567890");
195   gst_vorbis_tag_add (list, "MUSICBRAINZ_TRMID", "5678901");
196   /* MUSICBRAINZ_SORTNAME = GST_TAG_ARTIST_SORTNAME now */
197   gst_vorbis_tag_add (list, "MUSICBRAINZ_SORTNAME", "Five, 678901");
198
199   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_TRACKID, "123456");
200   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_ARTISTID, "234567");
201   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_ALBUMID, "345678");
202   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_ALBUMARTISTID,
203       "4567890");
204   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_TRMID, "5678901");
205   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST_SORTNAME, "Five, 678901");
206
207   gst_tag_list_free (list);
208 }
209
210 GST_END_TEST;
211
212 /* is there an easier way to compare two structures / tagslists? */
213 static gboolean
214 taglists_are_equal (const GstTagList * list_1, const GstTagList * list_2)
215 {
216   GstCaps *c_list_1 = gst_caps_new_empty ();
217   GstCaps *c_list_2 = gst_caps_new_empty ();
218   gboolean ret;
219
220   gst_caps_append_structure (c_list_1,
221       gst_structure_copy ((GstStructure *) list_1));
222   gst_caps_append_structure (c_list_2,
223       gst_structure_copy ((GstStructure *) list_2));
224
225   ret = gst_caps_is_equal (c_list_2, c_list_1);
226
227   gst_caps_unref (c_list_1);
228   gst_caps_unref (c_list_2);
229
230   return ret;
231 }
232
233 GST_START_TEST (test_vorbis_tags)
234 {
235   GstTagList *list;
236
237   list = gst_tag_list_new ();
238
239   /* NULL pointers aren't allowed */
240   ASSERT_CRITICAL (gst_vorbis_tag_add (NULL, "key", "value"));
241   ASSERT_CRITICAL (gst_vorbis_tag_add (list, NULL, "value"));
242   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "key", NULL));
243
244   /* must be UTF-8 */
245   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "key", "v\377lue"));
246   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "k\377y", "value"));
247
248   /* key can't have a '=' in it */
249   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "k=y", "value"));
250   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "key=", "value"));
251
252   /* should be allowed in values though */
253   gst_vorbis_tag_add (list, "keeey", "va=ue");
254
255   /* add some tags */
256   gst_vorbis_tag_add (list, "TITLE", "Too");
257   gst_vorbis_tag_add (list, "ALBUM", "Aoo");
258   gst_vorbis_tag_add (list, "ARTIST", "Alboo");
259   gst_vorbis_tag_add (list, "PERFORMER", "Perfoo");
260   gst_vorbis_tag_add (list, "COPYRIGHT", "Copyfoo");
261   gst_vorbis_tag_add (list, "DESCRIPTION", "Descoo");
262   gst_vorbis_tag_add (list, "LICENSE", "Licoo");
263   gst_vorbis_tag_add (list, "LICENSE",
264       "http://creativecommons.org/licenses/by/3.0/");
265   gst_vorbis_tag_add (list, "LOCATION", "Bristol, UK");
266   gst_vorbis_tag_add (list, "ORGANIZATION", "Orgoo");
267   gst_vorbis_tag_add (list, "GENRE", "Goo");
268   gst_vorbis_tag_add (list, "CONTACT", "Coo");
269   gst_vorbis_tag_add (list, "COMMENT", "Stroodle is good");
270   gst_vorbis_tag_add (list, "COMMENT", "Peroxysulfid stroodles the brain");
271
272   gst_vorbis_tag_add (list, "TRACKNUMBER", "5");
273   gst_vorbis_tag_add (list, "TRACKTOTAL", "77");
274   gst_vorbis_tag_add (list, "DISCNUMBER", "1");
275   gst_vorbis_tag_add (list, "DISCTOTAL", "2");
276   gst_vorbis_tag_add (list, "DATE", "1954-12-31");
277
278   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_TITLE, "Too");
279   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ALBUM, "Aoo");
280   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST, "Alboo");
281   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_PERFORMER, "Perfoo");
282   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_COPYRIGHT, "Copyfoo");
283   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_DESCRIPTION, "Descoo");
284   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LICENSE, "Licoo");
285   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LICENSE_URI,
286       "http://creativecommons.org/licenses/by/3.0/");
287   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_GEO_LOCATION_NAME, "Bristol, UK");
288   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ORGANIZATION, "Orgoo");
289   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_GENRE, "Goo");
290   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_CONTACT, "Coo");
291   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_COMMENT,
292       "Peroxysulfid stroodles the brain");
293   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_COMMENT, "Stroodle is good");
294   ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_TRACK_NUMBER, 5);
295   ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_TRACK_COUNT, 77);
296   ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_ALBUM_VOLUME_NUMBER, 1);
297   ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_ALBUM_VOLUME_COUNT, 2);
298
299   {
300     GDate *date = NULL;
301
302     fail_unless (gst_tag_list_get_date (list, GST_TAG_DATE, &date));
303     fail_unless (date != NULL);
304     fail_unless (g_date_get_day (date) == 31);
305     fail_unless (g_date_get_month (date) == G_DATE_DECEMBER);
306     fail_unless (g_date_get_year (date) == 1954);
307
308     g_date_free (date);
309   }
310
311   /* unknown vorbis comments should go into a GST_TAG_EXTENDED_COMMENT */
312   gst_vorbis_tag_add (list, "CoEdSub_ID", "98172AF-973-10-B");
313   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_EXTENDED_COMMENT,
314       "CoEdSub_ID=98172AF-973-10-B");
315   gst_vorbis_tag_add (list, "RuBuWuHash", "1337BA42F91");
316   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_EXTENDED_COMMENT,
317       "RuBuWuHash=1337BA42F91");
318
319   gst_vorbis_tag_add (list, "REPLAYGAIN_REFERENCE_LOUDNESS", "89.");
320   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_REFERENCE_LEVEL, 89.);
321   gst_vorbis_tag_add (list, "REPLAYGAIN_TRACK_GAIN", "+12.36");
322   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_TRACK_GAIN, +12.36);
323   gst_vorbis_tag_add (list, "REPLAYGAIN_TRACK_PEAK", "0.96349");
324   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_TRACK_PEAK, 0.96349);
325   gst_vorbis_tag_add (list, "REPLAYGAIN_ALBUM_GAIN", "+10.12");
326   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_ALBUM_GAIN, +10.12);
327   /* now check that we can parse floating point numbers with any separator
328    * (',' or '.') regardless of the current locale */
329   gst_vorbis_tag_add (list, "REPLAYGAIN_ALBUM_PEAK", "0,98107");
330   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_ALBUM_PEAK, 0.98107);
331   gst_vorbis_tag_add (list, "LICENSE", "http://foo.com/license-1.html");
332
333   /* make sure we can convert back and forth without loss */
334   {
335     GstTagList *new_list, *even_newer_list;
336     GstBuffer *buf, *buf2;
337     gchar *vendor_id = NULL;
338
339     buf = gst_tag_list_to_vorbiscomment_buffer (list,
340         (const guint8 *) "\003vorbis", 7, "libgstunittest");
341     fail_unless (buf != NULL);
342     new_list = gst_tag_list_from_vorbiscomment_buffer (buf,
343         (const guint8 *) "\003vorbis", 7, &vendor_id);
344     fail_unless (new_list != NULL);
345     fail_unless (vendor_id != NULL);
346     g_free (vendor_id);
347     vendor_id = NULL;
348
349     GST_LOG ("new_list = %" GST_PTR_FORMAT, new_list);
350     fail_unless (taglists_are_equal (list, new_list));
351
352     buf2 = gst_tag_list_to_vorbiscomment_buffer (new_list,
353         (const guint8 *) "\003vorbis", 7, "libgstunittest");
354     fail_unless (buf2 != NULL);
355     even_newer_list = gst_tag_list_from_vorbiscomment_buffer (buf2,
356         (const guint8 *) "\003vorbis", 7, &vendor_id);
357     fail_unless (even_newer_list != NULL);
358     fail_unless (vendor_id != NULL);
359     g_free (vendor_id);
360     vendor_id = NULL;
361
362     GST_LOG ("even_newer_list = %" GST_PTR_FORMAT, even_newer_list);
363     fail_unless (taglists_are_equal (new_list, even_newer_list));
364
365     gst_tag_list_free (new_list);
366     gst_tag_list_free (even_newer_list);
367     gst_buffer_unref (buf);
368     gst_buffer_unref (buf2);
369   }
370
371   /* there can only be one language per taglist ... */
372   gst_tag_list_free (list);
373   list = gst_tag_list_new ();
374   gst_vorbis_tag_add (list, "LANGUAGE", "fr");
375   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "fr");
376
377   gst_tag_list_free (list);
378   list = gst_tag_list_new ();
379   gst_vorbis_tag_add (list, "LANGUAGE", "[fr]");
380   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "fr");
381
382   gst_tag_list_free (list);
383   list = gst_tag_list_new ();
384   gst_vorbis_tag_add (list, "LANGUAGE", "French [fr]");
385   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "fr");
386
387   gst_tag_list_free (list);
388   list = gst_tag_list_new ();
389   gst_vorbis_tag_add (list, "LANGUAGE", "[eng] English");
390   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "eng");
391
392   gst_tag_list_free (list);
393   list = gst_tag_list_new ();
394   gst_vorbis_tag_add (list, "LANGUAGE", "eng");
395   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "eng");
396
397   gst_tag_list_free (list);
398   list = gst_tag_list_new ();
399   gst_vorbis_tag_add (list, "LANGUAGE", "[eng]");
400   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "eng");
401
402   /* free-form *sigh* */
403   gst_tag_list_free (list);
404   list = gst_tag_list_new ();
405   gst_vorbis_tag_add (list, "LANGUAGE", "English");
406   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "English");
407
408   /* now, while we still have a taglist, test _to_vorbiscomment_buffer() */
409   {
410     GstBuffer *buf1, *buf2;
411
412     ASSERT_CRITICAL (gst_tag_list_to_vorbiscomment_buffer (NULL,
413             (const guint8 *) "x", 1, "x"));
414
415     buf1 = gst_tag_list_to_vorbiscomment_buffer (list, NULL, 0, NULL);
416     fail_unless (buf1 != NULL);
417
418     buf2 = gst_tag_list_to_vorbiscomment_buffer (list,
419         (const guint8 *) "foo", 3, NULL);
420     fail_unless (buf2 != NULL);
421
422     fail_unless (memcmp (GST_BUFFER_DATA (buf1), GST_BUFFER_DATA (buf2) + 3,
423             GST_BUFFER_SIZE (buf1)) == 0);
424
425     gst_buffer_unref (buf1);
426     gst_buffer_unref (buf2);
427   }
428
429   gst_tag_list_free (list);
430
431   /* make sure gst_tag_list_from_vorbiscomment_buffer() works with an
432    * empty ID (for Speex) */
433   {
434     const guint8 speex_comments_buf1[] = { 0x03, 0x00, 0x00, 0x00, 'f', 'o',
435       'o', 0x00, 0x00, 0x00, 0x00
436     };
437     GstBuffer *buf;
438     gchar *vendor = NULL;
439
440     buf = gst_buffer_new ();
441     GST_BUFFER_DATA (buf) = (guint8 *) speex_comments_buf1;
442     GST_BUFFER_SIZE (buf) = sizeof (speex_comments_buf1);
443
444     /* make sure it doesn't memcmp over the end of the buffer */
445     fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf,
446             (const guint8 *) "averylongstringbrownfoxjumpoverthefence", 39,
447             &vendor) == NULL);
448     fail_unless (vendor == NULL);
449
450     /* make sure it bails out if the ID doesn't match */
451     fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf,
452             (guint8 *) "short", 4, &vendor) == NULL);
453     fail_unless (vendor == NULL);
454
455     /* now read properly */
456     list = gst_tag_list_from_vorbiscomment_buffer (buf, NULL, 0, &vendor);
457     fail_unless (vendor != NULL);
458     fail_unless_equals_string (vendor, "foo");
459     fail_unless (list != NULL);
460     fail_unless (gst_structure_n_fields ((GstStructure *) list) == 0);
461     g_free (vendor);
462     gst_tag_list_free (list);
463
464     /* now again without vendor */
465     list = gst_tag_list_from_vorbiscomment_buffer (buf, NULL, 0, NULL);
466     fail_unless (list != NULL);
467     fail_unless (gst_structure_n_fields ((GstStructure *) list) == 0);
468     gst_tag_list_free (list);
469
470     gst_buffer_unref (buf);
471   }
472
473   /* the same with an ID */
474   {
475     const guint8 vorbis_comments_buf[] = { 0x03, 'v', 'o', 'r', 'b', 'i', 's',
476       0x03, 0x00, 0x00, 0x00, 'f', 'o', 'o', 0x01, 0x00, 0x00, 0x00,
477       strlen ("ARTIST=foo bar"), 0x00, 0x00, 0x00, 'A', 'R', 'T', 'I', 'S',
478       'T', '=', 'f', 'o', 'o', ' ', 'b', 'a', 'r'
479     };
480     GstBuffer *buf;
481     gchar *vendor = NULL;
482
483     buf = gst_buffer_new ();
484     GST_BUFFER_DATA (buf) = (guint8 *) vorbis_comments_buf;
485     GST_BUFFER_SIZE (buf) = sizeof (vorbis_comments_buf);
486
487     /* make sure it doesn't memcmp over the end of the buffer */
488     fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf,
489             (const guint8 *) "averylongstringbrownfoxjumpoverthefence", 39,
490             &vendor) == NULL);
491     fail_unless (vendor == NULL);
492
493     /* make sure it bails out if the ID doesn't match */
494     fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf,
495             (guint8 *) "short", 4, &vendor) == NULL);
496     fail_unless (vendor == NULL);
497
498     /* now read properly */
499     list = gst_tag_list_from_vorbiscomment_buffer (buf,
500         (guint8 *) "\003vorbis", 7, &vendor);
501     fail_unless (vendor != NULL);
502     fail_unless_equals_string (vendor, "foo");
503     fail_unless (list != NULL);
504     fail_unless (gst_structure_n_fields ((GstStructure *) list) == 1);
505     ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST, "foo bar");
506     g_free (vendor);
507     gst_tag_list_free (list);
508
509     /* now again without vendor */
510     list = gst_tag_list_from_vorbiscomment_buffer (buf,
511         (guint8 *) "\003vorbis", 7, NULL);
512     fail_unless (list != NULL);
513     fail_unless (gst_structure_n_fields ((GstStructure *) list) == 1);
514     ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST, "foo bar");
515     gst_tag_list_free (list);
516
517     gst_buffer_unref (buf);
518   }
519
520   /* check date with time */
521   {
522     GDate *date = NULL;
523
524     list = gst_tag_list_new ();
525     gst_vorbis_tag_add (list, "DATE", "2006-09-25 22:02:38");
526
527     fail_unless (gst_tag_list_get_date_index (list, GST_TAG_DATE, 0, &date));
528     fail_unless (date != NULL);
529     fail_unless (g_date_get_day (date) == 25);
530     fail_unless (g_date_get_month (date) == G_DATE_SEPTEMBER);
531     fail_unless (g_date_get_year (date) == 2006);
532
533     g_date_free (date);
534     gst_tag_list_free (list);
535   }
536
537   /* check date with month/day of 00-00 */
538   {
539     GDate *date = NULL;
540
541     list = gst_tag_list_new ();
542     gst_vorbis_tag_add (list, "DATE", "1992-00-00");
543
544     fail_unless (gst_tag_list_get_date_index (list, GST_TAG_DATE, 0, &date));
545     fail_unless (date != NULL);
546     fail_unless (g_date_get_year (date) == 1992);
547
548     g_date_free (date);
549     gst_tag_list_free (list);
550   }
551
552   /* check date with valid month, but day of 00 */
553   {
554     GDate *date = NULL;
555
556     list = gst_tag_list_new ();
557     gst_vorbis_tag_add (list, "DATE", "1992-05-00");
558
559     fail_unless (gst_tag_list_get_date_index (list, GST_TAG_DATE, 0, &date));
560     fail_unless (date != NULL);
561     fail_unless (g_date_get_year (date) == 1992);
562     fail_unless (g_date_get_month (date) == G_DATE_MAY);
563
564     g_date_free (date);
565     gst_tag_list_free (list);
566   }
567 }
568
569 GST_END_TEST;
570
571 GST_START_TEST (test_id3_tags)
572 {
573   guint i;
574
575   fail_unless (gst_tag_id3_genre_count () > 0);
576
577   for (i = 0; i < gst_tag_id3_genre_count (); ++i) {
578     const gchar *genre;
579
580     genre = gst_tag_id3_genre_get (i);
581     GST_LOG ("genre: %s", genre);
582     fail_unless (genre != NULL);
583   }
584
585   {
586     /* TODO: GstTagList *gst_tag_list_new_from_id3v1 (const guint8 *data) */
587   }
588
589   /* gst_tag_from_id3_tag */
590   fail_unless (gst_tag_from_id3_tag ("TALB") != NULL);
591   ASSERT_CRITICAL (gst_tag_from_id3_tag (NULL));
592   fail_unless (gst_tag_from_id3_tag ("R2D2") == NULL);
593   fail_unless_equals_string (gst_tag_from_id3_tag ("WCOP"),
594       GST_TAG_COPYRIGHT_URI);
595
596   /* gst_tag_from_id3_user_tag */
597   ASSERT_CRITICAL (gst_tag_from_id3_user_tag (NULL, "foo"));
598   ASSERT_CRITICAL (gst_tag_from_id3_user_tag ("foo", NULL));
599   fail_unless (gst_tag_from_id3_user_tag ("R2D2", "R2D2") == NULL);
600
601   /* gst_tag_to_id3_tag */
602   ASSERT_CRITICAL (gst_tag_to_id3_tag (NULL));
603   fail_unless (gst_tag_to_id3_tag ("R2D2") == NULL);
604   fail_unless (gst_tag_to_id3_tag (GST_TAG_ARTIST) != NULL);
605   fail_unless_equals_string (gst_tag_to_id3_tag (GST_TAG_COPYRIGHT_URI),
606       "WCOP");
607
608   fail_unless (GST_TYPE_TAG_IMAGE_TYPE != 0);
609   fail_unless (g_type_name (GST_TYPE_TAG_IMAGE_TYPE) != NULL);
610 }
611
612 GST_END_TEST;
613
614
615 GST_START_TEST (test_id3v1_utf8_tag)
616 {
617   const guint8 id3v1[128] = {
618     /* marker */
619     'T', 'A', 'G',
620     /* title (30 bytes) */
621     'D', 0xc3, 0xad, 'v', 'k', 'a', ' ', 's',
622     ' ', 'p', 'e', 'r', 'l', 'a', 'm', 'i',
623     ' ', 'v', 'e', ' ', 'v', 'l', 'a', 's',
624     'e', 'c', 'h', 0, 0, 0,
625     /* artist (30 bytes) */
626     'A', 'l', 'e', 0xc5, 0xa1, ' ', 'B', 'r', 'i', 'c', 'h', 't', 'a',
627     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
628     /* album (30 bytes) */
629     'B', 'e', 's', 't', ' ', 'o', 'f', ' ', '(', 'P', 'r', 'o', 's', 't',
630     0xc4, 0x9b, ' ', 0xc3, 0xba, 0xc5, 0xbe, 'a', 's', 'n', 0xc3, 0xbd, ')',
631     0, 0, 0,
632     /* year (4 bytes) */
633     '2', '0', '0', '0',
634     /* comment (28 bytes) */
635     '-', '-', '-', ' ', 0xc4, 0x8d, 'e', 's', 'k', 0xc3, 0xa9, ' ', 'p',
636     0xc3, 0xad, 's', 'n', 'i', 0xc4, 0x8d, 'k', 'y', ' ', '-', '-', '-',
637     0, 0,
638     /* track number */
639     0, 0,
640     /* genre */
641     0x11
642   };
643   GstTagList *tags;
644   GDate *d;
645   gchar *s;
646
647   /* set this, to make sure UTF-8 strings are really interpreted properly
648    * as UTF-8, regardless of the locale set */
649   g_setenv ("GST_ID3V1_TAG_ENCODING", "WINDOWS-1250", TRUE);
650
651   tags = gst_tag_list_new_from_id3v1 (id3v1);
652   fail_unless (tags != NULL);
653
654   GST_LOG ("Got tags: %" GST_PTR_FORMAT, tags);
655
656   s = NULL;
657   fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &s));
658   fail_unless (s != NULL);
659   fail_unless_equals_string (s, "Dívka s perlami ve vlasech");
660   g_free (s);
661
662   s = NULL;
663   fail_unless (gst_tag_list_get_string (tags, GST_TAG_ARTIST, &s));
664   fail_unless (s != NULL);
665   fail_unless_equals_string (s, "Aleš Brichta");
666   g_free (s);
667
668   s = NULL;
669   fail_unless (gst_tag_list_get_string (tags, GST_TAG_ALBUM, &s));
670   fail_unless (s != NULL);
671   fail_unless_equals_string (s, "Best of (Prostě úžasný)");
672   g_free (s);
673
674   d = NULL;
675   fail_unless (gst_tag_list_get_date (tags, GST_TAG_DATE, &d));
676   fail_unless (d != NULL);
677   fail_unless_equals_int (g_date_get_year (d), 2000);
678   g_date_free (d);
679   d = NULL;
680
681   gst_tag_list_free (tags);
682
683   g_unsetenv ("GST_ID3V1_TAG_ENCODING");
684 }
685
686 GST_END_TEST;
687
688 GST_START_TEST (test_language_utils)
689 {
690   gchar **lang_codes, **c;
691
692 #define ASSERT_STRINGS_EQUAL fail_unless_equals_string
693
694   lang_codes = gst_tag_get_language_codes ();
695   fail_unless (lang_codes != NULL);
696   fail_unless (*lang_codes != NULL);
697
698   for (c = lang_codes; c != NULL && *c != NULL; ++c) {
699     const gchar *lang_name, *c1, *c2t, *c2b;
700
701     lang_name = gst_tag_get_language_name (*c);
702     fail_unless (lang_name != NULL);
703     fail_unless (g_utf8_validate (lang_name, -1, NULL));
704
705     c1 = gst_tag_get_language_code_iso_639_1 (*c);
706     fail_unless (c1 != NULL);
707     fail_unless (g_utf8_validate (c1, -1, NULL));
708
709     c2t = gst_tag_get_language_code_iso_639_2T (*c);
710     fail_unless (c2t != NULL);
711     fail_unless (g_utf8_validate (c2t, -1, NULL));
712
713     c2b = gst_tag_get_language_code_iso_639_2B (*c);
714     fail_unless (c2b != NULL);
715     fail_unless (g_utf8_validate (c2b, -1, NULL));
716
717     ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (*c), *c);
718     ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (c2t), *c);
719     ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (c2b), *c);
720
721     GST_DEBUG ("[%s] %s %s %s : %s\n", *c, c1, c2t, c2b, lang_name);
722
723   }
724   g_strfreev (lang_codes);
725
726   fail_unless (gst_tag_get_language_name ("de") != NULL);
727   fail_unless (gst_tag_get_language_name ("deu") != NULL);
728   fail_unless (gst_tag_get_language_name ("ger") != NULL);
729   fail_unless_equals_string (gst_tag_get_language_name ("deu"),
730       gst_tag_get_language_name ("ger"));
731   fail_unless_equals_string (gst_tag_get_language_name ("de"),
732       gst_tag_get_language_name ("ger"));
733   fail_unless (gst_tag_get_language_name ("de") !=
734       gst_tag_get_language_name ("fr"));
735
736   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("deu"), "de");
737   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("de"), "de");
738   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("ger"), "de");
739
740   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("deu"), "de");
741   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("de"), "de");
742   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("ger"), "de");
743
744   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("de"), "deu");
745   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("deu"), "deu");
746   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("ger"), "deu");
747
748   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("de"), "ger");
749   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("deu"), "ger");
750   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("ger"), "ger");
751 }
752
753 GST_END_TEST;
754
755 #define SPECIFIC_L "http://creativecommons.org/licenses/by-nc-sa/2.5/scotland/"
756 #define GENERIC_L "http://creativecommons.org/licenses/by/1.0/"
757 #define DERIVED_L "http://creativecommons.org/licenses/sampling+/1.0/tw/"
758
759 GST_START_TEST (test_license_utils)
760 {
761   GHashTable *ht;
762   GError *err = NULL;
763   gchar **liblicense_refs, **r;
764   gchar **lrefs, **l;
765   gchar *path, *data = NULL;
766   gsize data_len;
767
768   gst_debug_set_threshold_for_name ("tag-licenses", GST_LEVEL_NONE);
769
770   /* test jurisdiction-specific license */
771   fail_unless_equals_int (gst_tag_get_license_flags (SPECIFIC_L), 0x01010703);
772   fail_unless_equals_string (gst_tag_get_license_nick (SPECIFIC_L),
773       "CC BY-NC-SA 2.5 SCOTLAND");
774   fail_unless_equals_string (gst_tag_get_license_version (SPECIFIC_L), "2.5");
775   fail_unless_equals_string (gst_tag_get_license_jurisdiction (SPECIFIC_L),
776       "scotland");
777
778   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "C", TRUE);
779   fail_unless_equals_string (gst_tag_get_license_title (SPECIFIC_L),
780       "Attribution-NonCommercial-ShareAlike");
781   fail_unless (gst_tag_get_license_description (SPECIFIC_L) == NULL);
782
783   /* test generic license */
784   fail_unless_equals_int (gst_tag_get_license_flags (GENERIC_L), 0x01000307);
785   fail_unless_equals_string (gst_tag_get_license_nick (GENERIC_L), "CC BY 1.0");
786   fail_unless_equals_string (gst_tag_get_license_version (GENERIC_L), "1.0");
787   fail_unless (gst_tag_get_license_jurisdiction (GENERIC_L) == NULL);
788
789   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "C", TRUE);
790   fail_unless_equals_string (gst_tag_get_license_title (GENERIC_L),
791       "Attribution");
792   fail_unless_equals_string (gst_tag_get_license_description (GENERIC_L),
793       "You must attribute the work in the manner specified by the author or licensor.");
794
795 #ifdef ENABLE_NLS
796   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "fr", TRUE);
797   fail_unless_equals_string (gst_tag_get_license_title (GENERIC_L),
798       "Paternité");
799   fail_unless_equals_string (gst_tag_get_license_description (GENERIC_L),
800       "L'offrant autorise les autres à reproduire, distribuer et communiquer cette création au public. En échange, les personnes qui acceptent ce contrat doivent citer le nom de l'auteur original.");
801 #endif
802
803   /* test derived (for a certain jurisdiction) license */
804   fail_unless_equals_int (gst_tag_get_license_flags (DERIVED_L), 0x0100030d);
805   fail_unless_equals_string (gst_tag_get_license_nick (DERIVED_L),
806       "CC SAMPLING+ 1.0 TW");
807   fail_unless_equals_string (gst_tag_get_license_version (DERIVED_L), "1.0");
808   fail_unless_equals_string (gst_tag_get_license_jurisdiction (DERIVED_L),
809       "tw");
810
811   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "C", TRUE);
812   fail_unless_equals_string (gst_tag_get_license_title (DERIVED_L),
813       "Sampling Plus");
814   fail_unless_equals_string (gst_tag_get_license_description (GENERIC_L),
815       "You must attribute the work in the manner specified by the author or licensor.");
816
817   /* test all we know about */
818   lrefs = gst_tag_get_licenses ();
819   fail_unless (lrefs != NULL);
820   fail_unless (*lrefs != NULL);
821
822   GST_INFO ("%d licenses", g_strv_length (lrefs));
823   fail_unless (g_strv_length (lrefs) >= 376);
824
825   ht = g_hash_table_new (g_str_hash, g_str_equal);
826
827   for (l = lrefs; l != NULL && *l != NULL; ++l) {
828     const gchar *ref, *nick, *title, *desc G_GNUC_UNUSED;
829
830     ref = (const gchar *) *l;
831     nick = gst_tag_get_license_nick (ref);
832     title = gst_tag_get_license_title (ref);
833     desc = gst_tag_get_license_description (ref);
834     fail_unless (nick != NULL, "no nick for license '%s'", ref);
835     fail_unless (title != NULL, "no title for license '%s'", ref);
836     GST_LOG ("ref: %s [nick %s]", ref, (nick) ? nick : "none");
837     GST_TRACE ("    %s : %s", title, (desc) ? desc : "(no description)");
838
839     /* make sure the list contains no duplicates */
840     fail_if (g_hash_table_lookup (ht, (gpointer) ref) != NULL);
841     g_hash_table_insert (ht, (gpointer) ref, (gpointer) "meep");
842   }
843   g_hash_table_destroy (ht);
844
845   /* trailing slash shouldn't make a difference */
846   fail_unless_equals_int (gst_tag_get_license_flags
847       ("http://creativecommons.org/licenses/by-nd/1.0/"),
848       gst_tag_get_license_flags
849       ("http://creativecommons.org/licenses/by-nd/1.0"));
850   fail_unless_equals_string (gst_tag_get_license_nick
851       ("http://creativecommons.org/licenses/by-nd/1.0/"),
852       gst_tag_get_license_nick
853       ("http://creativecommons.org/licenses/by-nd/1.0"));
854   fail_unless_equals_int (gst_tag_get_license_flags
855       ("http://creativecommons.org/licenses/by-nd/2.5/ca/"),
856       gst_tag_get_license_flags
857       ("http://creativecommons.org/licenses/by-nd/2.5/ca"));
858   fail_unless_equals_string (gst_tag_get_license_nick
859       ("http://creativecommons.org/licenses/by-nd/2.5/ca/"),
860       gst_tag_get_license_nick
861       ("http://creativecommons.org/licenses/by-nd/2.5/ca"));
862
863   /* unknown licenses */
864   fail_unless (gst_tag_get_license_nick
865       ("http://creativecommons.org/licenses/by-nd/25/ca/") == NULL);
866   fail_unless (gst_tag_get_license_flags
867       ("http://creativecommons.org/licenses/by-nd/25/ca") == 0);
868   fail_unless (gst_tag_get_license_jurisdiction
869       ("http://creativecommons.org/licenses/by-nd/25/ca/") == NULL);
870   fail_unless (gst_tag_get_license_jurisdiction
871       ("http://creativecommons.org/licenses/by-nd/25/ca") == NULL);
872   fail_unless (gst_tag_get_license_title
873       ("http://creativecommons.org/licenses/by-nd/25/ca") == NULL);
874   fail_unless (gst_tag_get_license_jurisdiction
875       ("http://creativecommons.org/licenses/by-nd/25/ca") == NULL);
876
877   /* unknown prefixes even */
878   fail_unless (gst_tag_get_license_nick
879       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
880   fail_unless (gst_tag_get_license_flags
881       ("http://copycats.org/licenses/by-nd/2.5/ca") == 0);
882   fail_unless (gst_tag_get_license_jurisdiction
883       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
884   fail_unless (gst_tag_get_license_title
885       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
886   fail_unless (gst_tag_get_license_description
887       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
888
889   /* read list of liblicense refs from file */
890   path = g_build_filename (GST_TEST_FILES_PATH, "license-uris", NULL);
891   GST_LOG ("reading file '%s'", path);
892   if (!g_file_get_contents (path, &data, &data_len, &err)) {
893     g_error ("error loading test file: %s", err->message);
894   }
895
896   while (data_len > 0 && data[data_len - 1] == '\n') {
897     data[--data_len] = '\0';
898   }
899
900   liblicense_refs = g_strsplit (data, "\n", -1);
901   g_free (data);
902   g_free (path);
903
904   fail_unless (g_strv_length (lrefs) >= g_strv_length (liblicense_refs));
905
906   for (r = liblicense_refs; r != NULL && *r != NULL; ++r) {
907     GstTagLicenseFlags flags;
908     const gchar *version, *nick, *jur;
909     const gchar *ref = *r;
910
911     GST_LOG ("liblicense ref: %s", ref);
912
913     version = gst_tag_get_license_version (ref);
914     if (strstr (ref, "publicdomain") != NULL)
915       fail_unless (version == NULL);
916     else
917       fail_unless (version != NULL, "expected version for license %s", ref);
918
919     flags = gst_tag_get_license_flags (ref);
920     fail_unless (flags != 0, "expected non-zero flags for license %s", ref);
921
922     nick = gst_tag_get_license_nick (ref);
923     fail_unless (nick != NULL, "expected nick for license %s", ref);
924
925     jur = gst_tag_get_license_jurisdiction (ref);
926     if (g_str_has_suffix (ref, "de/")) {
927       fail_unless_equals_string (jur, "de");
928     } else if (g_str_has_suffix (ref, "scotland")) {
929       fail_unless_equals_string (jur, "scotland");
930     } else if (g_str_has_suffix (ref, ".0") || g_str_has_suffix (ref, ".1")) {
931       fail_unless (jur == NULL);
932     }
933   }
934
935   g_strfreev (liblicense_refs);
936   g_strfreev (lrefs);
937 }
938
939 GST_END_TEST;
940
941 GST_START_TEST (test_xmp_formatting)
942 {
943   GstTagList *list;
944   GstBuffer *buf;
945   const gchar *text;
946   guint len;
947
948   /* test data */
949   list = gst_tag_list_new_full (GST_TAG_TITLE, "test title",
950       GST_TAG_DESCRIPTION, "test decription",
951       GST_TAG_KEYWORDS, "keyword1", GST_TAG_KEYWORDS, "keyword2", NULL);
952
953   buf = gst_tag_list_to_xmp_buffer (list, FALSE);
954   fail_unless (buf != NULL);
955
956   text = (const gchar *) GST_BUFFER_DATA (buf);
957   len = GST_BUFFER_SIZE (buf);
958
959   /* check the content */
960   fail_unless (g_strrstr_len (text, len, "<?xpacket begin") == text);
961   fail_unless (g_strrstr_len (text, len, ">test title<") != NULL);
962   fail_unless (g_strrstr_len (text, len, ">test decription<") != NULL);
963   fail_unless (g_strrstr_len (text, len, ">keyword1<") != NULL);
964   fail_unless (g_strrstr_len (text, len, ">keyword2<") != NULL);
965   fail_unless (g_strrstr_len (text, len, "<?xpacket end") != NULL);
966
967   gst_buffer_unref (buf);
968   gst_tag_list_free (list);
969 }
970
971 GST_END_TEST;
972
973
974 GST_START_TEST (test_xmp_parsing)
975 {
976   GstTagList *list;
977   GstBuffer *buf;
978   guint i, j, result_size;
979   gchar *text;
980   const gchar *xmp_header =
981       "<?xpacket begin=\"\xEF\xBB\xBF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>"
982       "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"GStreamer\">"
983       "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">";
984
985   /* We used to write an extra trailing \n after the footer, keep compatibility
986    * with our old generated media by checking that it still can be parsed */
987   const gchar *xmp_footers[] = {
988     "</rdf:RDF>" "</x:xmpmeta>" "<?xpacket end=\"r\"?>",
989     "</rdf:RDF>" "</x:xmpmeta>" "<?xpacket end=\"r\"?>\n",
990     NULL
991   };
992
993   struct
994   {
995     const gchar *xmp_data;
996     gint result_size;
997     gint result_test;
998   } test_data[] = {
999     {
1000     "", -1, -1}, {
1001     "<rdf:Description rdf:about=\"\" />", 0, -1}, {
1002     "<rdf:Description rdf:about=\"\"></rdf:Description>", 0, -1}, {
1003     "<rdf:Description    rdf:about=\"\"    ></rdf:Description>", 0, -1}, {
1004     "<rdf:Description rdf:about=\"\"><dc:description>test</dc:description></rdf:Description>",
1005           1, 0}, {
1006     "<rdf:Description rdf:about=\"\" dc:description=\"test\"></rdf:Description>",
1007           1, 0}, {
1008     NULL, -1, -1}
1009   };
1010
1011   /* test data */
1012   buf = gst_buffer_new ();
1013
1014   j = 0;
1015   i = 0;
1016   while (xmp_footers[j]) {
1017     while (test_data[i].xmp_data) {
1018       GST_DEBUG ("trying test-data %u", i);
1019
1020       text =
1021           g_strconcat (xmp_header, test_data[i].xmp_data, xmp_footers[j], NULL);
1022       GST_BUFFER_DATA (buf) = (guint8 *) text;
1023       GST_BUFFER_SIZE (buf) = strlen (text) + 1;
1024
1025       list = gst_tag_list_from_xmp_buffer (buf);
1026       if (test_data[i].result_size >= 0) {
1027         fail_unless (list != NULL);
1028
1029         result_size = gst_structure_n_fields ((GstStructure *) list);
1030         fail_unless (result_size == test_data[i].result_size);
1031
1032         /* check the taglist content */
1033         switch (test_data[i].result_test) {
1034           case 0:
1035             ASSERT_TAG_LIST_HAS_STRING (list, "description", "test");
1036             break;
1037           default:
1038             break;
1039         }
1040       }
1041       if (list)
1042         gst_tag_list_free (list);
1043
1044       g_free (text);
1045       i++;
1046     }
1047     j++;
1048   }
1049
1050   gst_buffer_unref (buf);
1051 }
1052
1053 GST_END_TEST;
1054
1055 static void
1056 tag_list_equals (GstTagList * taglist, GstTagList * taglist2)
1057 {
1058   const gchar *name_sent, *name_recv;
1059   const GValue *value_sent, *value_recv;
1060   gboolean found;
1061   gint comparison;
1062   gint n_recv;
1063   gint n_sent;
1064   gint i, j;
1065
1066   /* verify tags */
1067   fail_unless (taglist2 != NULL);
1068   n_recv = gst_structure_n_fields (taglist2);
1069   n_sent = gst_structure_n_fields (taglist);
1070   fail_unless (n_recv == n_sent);
1071   fail_unless (n_sent > 0);
1072
1073   /* FIXME: compare taglist values */
1074   for (i = 0; i < n_sent; i++) {
1075     name_sent = gst_structure_nth_field_name (taglist, i);
1076     value_sent = gst_structure_get_value (taglist, name_sent);
1077     found = FALSE;
1078     for (j = 0; j < n_recv; j++) {
1079       name_recv = gst_structure_nth_field_name (taglist2, j);
1080       if (!strcmp (name_sent, name_recv)) {
1081         value_recv = gst_structure_get_value (taglist2, name_recv);
1082         comparison = gst_value_compare (value_sent, value_recv);
1083         if (comparison != GST_VALUE_EQUAL) {
1084           gchar *vs = g_strdup_value_contents (value_sent);
1085           gchar *vr = g_strdup_value_contents (value_recv);
1086           GST_DEBUG ("sent = %s:'%s', recv = %s:'%s'",
1087               G_VALUE_TYPE_NAME (value_sent), vs,
1088               G_VALUE_TYPE_NAME (value_recv), vr);
1089           g_free (vs);
1090           g_free (vr);
1091         }
1092         if (comparison != GST_VALUE_EQUAL &&
1093             G_VALUE_HOLDS (value_sent, G_TYPE_DOUBLE)) {
1094           gdouble vs;
1095           gdouble vr;
1096
1097           /* add some tolerance for doubles */
1098           vs = g_value_get_double (value_sent);
1099           vr = g_value_get_double (value_recv);
1100           if (vr >= vs - 0.001 && vr <= vs + 0.001)
1101             comparison = GST_VALUE_EQUAL;
1102         }
1103         fail_unless (comparison == GST_VALUE_EQUAL,
1104             "tag item %s has been received with different type or value",
1105             name_sent);
1106         found = TRUE;
1107         break;
1108       }
1109     }
1110     fail_unless (found, "tag item %s is lost", name_sent);
1111   }
1112 }
1113
1114 static void
1115 do_xmp_tag_serialization_deserialization (GstTagList * taglist,
1116     const gchar ** schemas)
1117 {
1118   GstTagList *taglist2;
1119   GstBuffer *buf;
1120
1121   buf = gst_tag_list_to_xmp_buffer_full (taglist, TRUE, schemas);
1122   taglist2 = gst_tag_list_from_xmp_buffer (buf);
1123
1124   tag_list_equals (taglist, taglist2);
1125
1126   gst_buffer_unref (buf);
1127   gst_tag_list_free (taglist2);
1128 }
1129
1130 static void
1131 do_simple_xmp_tag_serialization_deserialization (const gchar * gsttag,
1132     GValue * value)
1133 {
1134   GstTagList *taglist = gst_tag_list_new ();
1135
1136   gst_tag_list_add_value (taglist, GST_TAG_MERGE_REPLACE, gsttag, value);
1137
1138   do_xmp_tag_serialization_deserialization (taglist, NULL);
1139   gst_tag_list_free (taglist);
1140 }
1141
1142 GST_START_TEST (test_xmp_tags_serialization_deserialization)
1143 {
1144   GValue value = { 0 };
1145   GDate *date;
1146   GstDateTime *datetime;
1147
1148   gst_tag_register_musicbrainz_tags ();
1149
1150   g_value_init (&value, G_TYPE_STRING);
1151   g_value_set_static_string (&value, "my string");
1152   do_simple_xmp_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1153   do_simple_xmp_tag_serialization_deserialization (GST_TAG_COPYRIGHT, &value);
1154   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DESCRIPTION, &value);
1155   do_simple_xmp_tag_serialization_deserialization (GST_TAG_KEYWORDS, &value);
1156   do_simple_xmp_tag_serialization_deserialization (GST_TAG_TITLE, &value);
1157   do_simple_xmp_tag_serialization_deserialization (GST_TAG_VIDEO_CODEC, &value);
1158   do_simple_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_COUNTRY,
1159       &value);
1160   do_simple_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_CITY,
1161       &value);
1162   do_simple_xmp_tag_serialization_deserialization
1163       (GST_TAG_GEO_LOCATION_SUBLOCATION, &value);
1164   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DEVICE_MANUFACTURER,
1165       &value);
1166   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DEVICE_MODEL,
1167       &value);
1168   do_simple_xmp_tag_serialization_deserialization (GST_TAG_APPLICATION_NAME,
1169       &value);
1170
1171   g_value_set_static_string (&value, "rotate-0");
1172   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1173       &value);
1174   g_value_set_static_string (&value, "flip-rotate-0");
1175   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1176       &value);
1177   g_value_set_static_string (&value, "rotate-180");
1178   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1179       &value);
1180   g_value_set_static_string (&value, "flip-rotate-180");
1181   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1182       &value);
1183   g_value_set_static_string (&value, "flip-rotate-270");
1184   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1185       &value);
1186   g_value_set_static_string (&value, "rotate-90");
1187   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1188       &value);
1189   g_value_set_static_string (&value, "flip-rotate-90");
1190   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1191       &value);
1192   g_value_set_static_string (&value, "rotate-270");
1193   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1194       &value);
1195
1196   g_value_unset (&value);
1197   g_value_init (&value, G_TYPE_DOUBLE);
1198
1199   g_value_set_double (&value, 0.0);
1200   do_simple_xmp_tag_serialization_deserialization
1201       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1202   do_simple_xmp_tag_serialization_deserialization
1203       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1204   g_value_set_double (&value, 10.5);
1205   do_simple_xmp_tag_serialization_deserialization
1206       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1207   do_simple_xmp_tag_serialization_deserialization
1208       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1209   g_value_set_double (&value, -32.375);
1210   do_simple_xmp_tag_serialization_deserialization
1211       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1212   do_simple_xmp_tag_serialization_deserialization
1213       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1214
1215   g_value_set_double (&value, 0);
1216   do_simple_xmp_tag_serialization_deserialization
1217       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1218   g_value_set_double (&value, 100);
1219   do_simple_xmp_tag_serialization_deserialization
1220       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1221   g_value_set_double (&value, 500.25);
1222   do_simple_xmp_tag_serialization_deserialization
1223       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1224   g_value_set_double (&value, -12.75);
1225   do_simple_xmp_tag_serialization_deserialization
1226       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1227
1228   g_value_set_double (&value, 0.0);
1229   do_simple_xmp_tag_serialization_deserialization
1230       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1231   g_value_set_double (&value, 10.0);
1232   do_simple_xmp_tag_serialization_deserialization
1233       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1234   g_value_set_double (&value, 786.125);
1235   do_simple_xmp_tag_serialization_deserialization
1236       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1237   g_value_set_double (&value, -2.5);
1238   do_simple_xmp_tag_serialization_deserialization
1239       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1240
1241   g_value_set_double (&value, 0.0);
1242   do_simple_xmp_tag_serialization_deserialization
1243       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1244   g_value_set_double (&value, 180.0);
1245   do_simple_xmp_tag_serialization_deserialization
1246       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1247   g_value_set_double (&value, 359.99);
1248   do_simple_xmp_tag_serialization_deserialization
1249       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1250
1251   g_value_set_double (&value, 0.0);
1252   do_simple_xmp_tag_serialization_deserialization
1253       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1254   g_value_set_double (&value, 90.0);
1255   do_simple_xmp_tag_serialization_deserialization
1256       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1257   g_value_set_double (&value, 359.99);
1258   do_simple_xmp_tag_serialization_deserialization
1259       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1260
1261   g_value_set_double (&value, 0.0);
1262   do_simple_xmp_tag_serialization_deserialization
1263       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1264   g_value_set_double (&value, 1.0);
1265   do_simple_xmp_tag_serialization_deserialization
1266       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1267   g_value_set_double (&value, -2.5);
1268   do_simple_xmp_tag_serialization_deserialization
1269       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1270   g_value_unset (&value);
1271
1272   g_value_init (&value, GST_TYPE_DATE);
1273   date = g_date_new_dmy (22, 3, 2010);
1274   gst_value_set_date (&value, date);
1275   g_date_free (date);
1276   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE, &value);
1277   g_value_unset (&value);
1278
1279   g_value_init (&value, G_TYPE_UINT);
1280   g_value_set_uint (&value, 0);
1281   do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value);
1282   g_value_set_uint (&value, 100);
1283   do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value);
1284   g_value_set_uint (&value, 22);
1285   do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value);
1286   g_value_unset (&value);
1287
1288   g_value_init (&value, GST_TYPE_DATE_TIME);
1289   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10);
1290   g_value_set_boxed (&value, datetime);
1291   gst_date_time_unref (datetime);
1292   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1293   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.000125);
1294   g_value_set_boxed (&value, datetime);
1295   gst_date_time_unref (datetime);
1296   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1297   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.000001);
1298   g_value_set_boxed (&value, datetime);
1299   gst_date_time_unref (datetime);
1300   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1301   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.123456);
1302   g_value_set_boxed (&value, datetime);
1303   gst_date_time_unref (datetime);
1304   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1305   datetime = gst_date_time_new (-3, 2010, 6, 22, 12, 5, 10.123456);
1306   g_value_set_boxed (&value, datetime);
1307   gst_date_time_unref (datetime);
1308   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1309   datetime = gst_date_time_new (5, 2010, 6, 22, 12, 5, 10.123456);
1310   g_value_set_boxed (&value, datetime);
1311   gst_date_time_unref (datetime);
1312   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1313   datetime = gst_date_time_new_local_time (2010, 12, 2, 12, 5, 10.000043);
1314   g_value_set_boxed (&value, datetime);
1315   gst_date_time_unref (datetime);
1316   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1317   g_value_unset (&value);
1318 }
1319
1320 GST_END_TEST;
1321
1322
1323 GST_START_TEST (test_xmp_compound_tags)
1324 {
1325   const gchar *schemas[] = { "Iptc4xmpExt", NULL };
1326   GstTagList *taglist = gst_tag_list_new ();
1327
1328   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_KEYWORDS, "k1",
1329       GST_TAG_KEYWORDS, "k2", GST_TAG_TITLE, "title", GST_TAG_KEYWORDS, "k3",
1330       NULL);
1331   do_xmp_tag_serialization_deserialization (taglist, NULL);
1332   gst_tag_list_free (taglist);
1333
1334   taglist = gst_tag_list_new ();
1335   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_GEO_LOCATION_COUNTRY,
1336       "Brazil", GST_TAG_GEO_LOCATION_CITY, "Campina Grande", NULL);
1337   do_xmp_tag_serialization_deserialization (taglist, schemas);
1338   gst_tag_list_free (taglist);
1339 }
1340
1341 GST_END_TEST;
1342
1343
1344 GST_START_TEST (test_exif_parsing)
1345 {
1346   GstTagList *taglist;
1347   GstBuffer *buf;
1348   GstByteWriter writer;
1349   const gchar *str;
1350
1351   gst_byte_writer_init (&writer);
1352
1353   /* write the IFD */
1354   /* 1 entry */
1355   gst_byte_writer_put_uint16_le (&writer, 1);
1356
1357   /* copyright tag */
1358   /* tag id */
1359   gst_byte_writer_put_uint16_le (&writer, 0x8298);
1360   /* tag type */
1361   gst_byte_writer_put_uint16_le (&writer, 0x2);
1362   /* count */
1363   gst_byte_writer_put_uint32_le (&writer, strlen ("my copyright") + 1);
1364   /* offset */
1365   gst_byte_writer_put_uint32_le (&writer, 8 + 14);
1366
1367   /* data */
1368   gst_byte_writer_put_string (&writer, "my copyright");
1369
1370   buf = gst_byte_writer_reset_and_get_buffer (&writer);
1371
1372   taglist = gst_tag_list_from_exif_buffer (buf, G_LITTLE_ENDIAN, 8);
1373
1374   fail_unless (gst_structure_n_fields (taglist) == 1);
1375   fail_unless (gst_structure_has_field_typed (taglist, GST_TAG_COPYRIGHT,
1376           G_TYPE_STRING));
1377   str = gst_structure_get_string (taglist, GST_TAG_COPYRIGHT);
1378   fail_unless (strcmp (str, "my copyright") == 0);
1379
1380   gst_tag_list_free (taglist);
1381   gst_buffer_unref (buf);
1382 }
1383
1384 GST_END_TEST;
1385
1386
1387 static void
1388 do_exif_tag_serialization_deserialization (GstTagList * taglist)
1389 {
1390   GstTagList *taglist2;
1391   GstBuffer *buf;
1392
1393   /* LE */
1394   buf = gst_tag_list_to_exif_buffer (taglist, G_LITTLE_ENDIAN, 0);
1395   GST_MEMDUMP ("Exif tag", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
1396   taglist2 = gst_tag_list_from_exif_buffer (buf, G_LITTLE_ENDIAN, 0);
1397   gst_buffer_unref (buf);
1398
1399   tag_list_equals (taglist, taglist2);
1400   gst_tag_list_free (taglist2);
1401
1402   /* BE */
1403   buf = gst_tag_list_to_exif_buffer (taglist, G_BIG_ENDIAN, 0);
1404   GST_MEMDUMP ("Exif tag", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
1405   taglist2 = gst_tag_list_from_exif_buffer (buf, G_BIG_ENDIAN, 0);
1406   gst_buffer_unref (buf);
1407
1408   tag_list_equals (taglist, taglist2);
1409   gst_tag_list_free (taglist2);
1410
1411   /* APP1 */
1412   buf = gst_tag_list_to_exif_buffer_with_tiff_header (taglist);
1413   taglist2 = gst_tag_list_from_exif_buffer_with_tiff_header (buf);
1414   gst_buffer_unref (buf);
1415
1416   tag_list_equals (taglist, taglist2);
1417   gst_tag_list_free (taglist2);
1418 }
1419
1420 static void
1421 do_simple_exif_tag_serialization_deserialization (const gchar * gsttag,
1422     GValue * value)
1423 {
1424   GstTagList *taglist = gst_tag_list_new ();
1425
1426   gst_tag_list_add_value (taglist, GST_TAG_MERGE_REPLACE, gsttag, value);
1427   do_exif_tag_serialization_deserialization (taglist);
1428
1429   gst_tag_list_free (taglist);
1430 }
1431
1432 /*
1433  * Adds tags from multiple ifd tables and tries serializing them
1434  */
1435 GST_START_TEST (test_exif_multiple_tags)
1436 {
1437   GstTagList *taglist;
1438   GstDateTime *datetime;
1439   GValue value = { 0 };
1440
1441   gst_tag_register_musicbrainz_tags ();
1442
1443   taglist = gst_tag_list_new_full (GST_TAG_ARTIST, "artist",
1444       GST_TAG_DEVICE_MANUFACTURER, "make",
1445       GST_TAG_DEVICE_MODEL, "model", GST_TAG_GEO_LOCATION_LATITUDE, 45.5,
1446       GST_TAG_GEO_LOCATION_LONGITUDE, -10.25,
1447       GST_TAG_IMAGE_HORIZONTAL_PPI, 300.0,
1448       GST_TAG_IMAGE_VERTICAL_PPI, 300.0, NULL);
1449
1450   g_value_init (&value, GST_TYPE_DATE_TIME);
1451   datetime = gst_date_time_new_local_time (2010, 6, 22, 12, 5, 10);
1452   g_value_set_boxed (&value, datetime);
1453   gst_date_time_unref (datetime);
1454   gst_tag_list_add_value (taglist, GST_TAG_MERGE_APPEND, GST_TAG_DATE_TIME,
1455       &value);
1456   g_value_unset (&value);
1457
1458   do_exif_tag_serialization_deserialization (taglist);
1459
1460   gst_tag_list_free (taglist);
1461 }
1462
1463 GST_END_TEST;
1464
1465
1466 GST_START_TEST (test_exif_tags_serialization_deserialization)
1467 {
1468   GValue value = { 0 };
1469   GstDateTime *datetime = NULL;
1470   GstBuffer *buf = NULL;
1471   gint i;
1472   GstTagList *taglist;
1473
1474   gst_tag_register_musicbrainz_tags ();
1475
1476   g_value_init (&value, G_TYPE_STRING);
1477   g_value_set_static_string (&value, "my string");
1478   do_simple_exif_tag_serialization_deserialization (GST_TAG_COPYRIGHT, &value);
1479   g_value_set_static_string (&value, "ty");
1480   do_simple_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1481   g_value_set_static_string (&value, "Company Software 1.2b (info)");
1482   do_simple_exif_tag_serialization_deserialization (GST_TAG_APPLICATION_NAME,
1483       &value);
1484
1485   /* non ascii chars */
1486   g_value_set_static_string (&value, "AaÄäEeËëIiÏïOoÖöUuÜü");
1487   do_simple_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1488   g_value_set_static_string (&value, "Äë");
1489   do_simple_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1490
1491   /* image orientation tests */
1492   g_value_set_static_string (&value, "rotate-0");
1493   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1494       &value);
1495   g_value_set_static_string (&value, "flip-rotate-0");
1496   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1497       &value);
1498   g_value_set_static_string (&value, "rotate-180");
1499   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1500       &value);
1501   g_value_set_static_string (&value, "flip-rotate-180");
1502   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1503       &value);
1504   g_value_set_static_string (&value, "flip-rotate-270");
1505   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1506       &value);
1507   g_value_set_static_string (&value, "rotate-90");
1508   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1509       &value);
1510   g_value_set_static_string (&value, "flip-rotate-90");
1511   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1512       &value);
1513   g_value_set_static_string (&value, "rotate-270");
1514   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1515       &value);
1516
1517   /* exposure program */
1518   g_value_set_static_string (&value, "undefined");
1519   do_simple_exif_tag_serialization_deserialization
1520       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1521   g_value_set_static_string (&value, "manual");
1522   do_simple_exif_tag_serialization_deserialization
1523       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1524   g_value_set_static_string (&value, "normal");
1525   do_simple_exif_tag_serialization_deserialization
1526       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1527   g_value_set_static_string (&value, "aperture-priority");
1528   do_simple_exif_tag_serialization_deserialization
1529       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1530   g_value_set_static_string (&value, "shutter-priority");
1531   do_simple_exif_tag_serialization_deserialization
1532       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1533   g_value_set_static_string (&value, "creative");
1534   do_simple_exif_tag_serialization_deserialization
1535       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1536   g_value_set_static_string (&value, "action");
1537   do_simple_exif_tag_serialization_deserialization
1538       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1539   g_value_set_static_string (&value, "portrait");
1540   do_simple_exif_tag_serialization_deserialization
1541       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1542   g_value_set_static_string (&value, "landscape");
1543   do_simple_exif_tag_serialization_deserialization
1544       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1545
1546   /* exposure mode */
1547   g_value_set_static_string (&value, "auto-exposure");
1548   do_simple_exif_tag_serialization_deserialization
1549       (GST_TAG_CAPTURING_EXPOSURE_MODE, &value);
1550   g_value_set_static_string (&value, "manual-exposure");
1551   do_simple_exif_tag_serialization_deserialization
1552       (GST_TAG_CAPTURING_EXPOSURE_MODE, &value);
1553   g_value_set_static_string (&value, "auto-bracket");
1554   do_simple_exif_tag_serialization_deserialization
1555       (GST_TAG_CAPTURING_EXPOSURE_MODE, &value);
1556
1557   /* scene capture type */
1558   g_value_set_static_string (&value, "standard");
1559   do_simple_exif_tag_serialization_deserialization
1560       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1561   g_value_set_static_string (&value, "portrait");
1562   do_simple_exif_tag_serialization_deserialization
1563       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1564   g_value_set_static_string (&value, "landscape");
1565   do_simple_exif_tag_serialization_deserialization
1566       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1567   g_value_set_static_string (&value, "night-scene");
1568   do_simple_exif_tag_serialization_deserialization
1569       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1570
1571   g_value_set_static_string (&value, "none");
1572   do_simple_exif_tag_serialization_deserialization
1573       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1574   g_value_set_static_string (&value, "high-gain-up");
1575   do_simple_exif_tag_serialization_deserialization
1576       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1577   g_value_set_static_string (&value, "low-gain-up");
1578   do_simple_exif_tag_serialization_deserialization
1579       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1580   g_value_set_static_string (&value, "high-gain-down");
1581   do_simple_exif_tag_serialization_deserialization
1582       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1583   g_value_set_static_string (&value, "low-gain-down");
1584   do_simple_exif_tag_serialization_deserialization
1585       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1586
1587   g_value_set_static_string (&value, "auto");
1588   do_simple_exif_tag_serialization_deserialization
1589       (GST_TAG_CAPTURING_WHITE_BALANCE, &value);
1590   g_value_set_static_string (&value, "manual");
1591   do_simple_exif_tag_serialization_deserialization
1592       (GST_TAG_CAPTURING_WHITE_BALANCE, &value);
1593
1594   g_value_set_static_string (&value, "normal");
1595   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST,
1596       &value);
1597   g_value_set_static_string (&value, "hard");
1598   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST,
1599       &value);
1600   g_value_set_static_string (&value, "soft");
1601   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST,
1602       &value);
1603
1604   g_value_set_static_string (&value, "normal");
1605   do_simple_exif_tag_serialization_deserialization
1606       (GST_TAG_CAPTURING_SATURATION, &value);
1607   g_value_set_static_string (&value, "low-saturation");
1608   do_simple_exif_tag_serialization_deserialization
1609       (GST_TAG_CAPTURING_SATURATION, &value);
1610   g_value_set_static_string (&value, "high-saturation");
1611   do_simple_exif_tag_serialization_deserialization
1612       (GST_TAG_CAPTURING_SATURATION, &value);
1613
1614   g_value_set_static_string (&value, "normal");
1615   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS,
1616       &value);
1617   g_value_set_static_string (&value, "hard");
1618   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS,
1619       &value);
1620   g_value_set_static_string (&value, "soft");
1621   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS,
1622       &value);
1623
1624   g_value_set_static_string (&value, "unknown");
1625   do_simple_exif_tag_serialization_deserialization
1626       (GST_TAG_CAPTURING_METERING_MODE, &value);
1627   g_value_set_static_string (&value, "average");
1628   do_simple_exif_tag_serialization_deserialization
1629       (GST_TAG_CAPTURING_METERING_MODE, &value);
1630   g_value_set_static_string (&value, "center-weighted-average");
1631   do_simple_exif_tag_serialization_deserialization
1632       (GST_TAG_CAPTURING_METERING_MODE, &value);
1633   g_value_set_static_string (&value, "spot");
1634   do_simple_exif_tag_serialization_deserialization
1635       (GST_TAG_CAPTURING_METERING_MODE, &value);
1636   g_value_set_static_string (&value, "multi-spot");
1637   do_simple_exif_tag_serialization_deserialization
1638       (GST_TAG_CAPTURING_METERING_MODE, &value);
1639   g_value_set_static_string (&value, "pattern");
1640   do_simple_exif_tag_serialization_deserialization
1641       (GST_TAG_CAPTURING_METERING_MODE, &value);
1642   g_value_set_static_string (&value, "partial");
1643   do_simple_exif_tag_serialization_deserialization
1644       (GST_TAG_CAPTURING_METERING_MODE, &value);
1645   g_value_set_static_string (&value, "other");
1646   do_simple_exif_tag_serialization_deserialization
1647       (GST_TAG_CAPTURING_METERING_MODE, &value);
1648
1649   g_value_set_static_string (&value, "dsc");
1650   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1651       &value);
1652   g_value_set_static_string (&value, "other");
1653   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1654       &value);
1655   g_value_set_static_string (&value, "transparent-scanner");
1656   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1657       &value);
1658   g_value_set_static_string (&value, "reflex-scanner");
1659   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1660       &value);
1661   g_value_unset (&value);
1662
1663   g_value_init (&value, G_TYPE_DOUBLE);
1664   g_value_set_double (&value, 30.5);
1665   do_simple_exif_tag_serialization_deserialization
1666       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1667   g_value_set_double (&value, -12.125);
1668   do_simple_exif_tag_serialization_deserialization
1669       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1670   g_value_set_double (&value, 0);
1671   do_simple_exif_tag_serialization_deserialization
1672       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1673   g_value_set_double (&value, 65.0);
1674   do_simple_exif_tag_serialization_deserialization
1675       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1676   g_value_set_double (&value, -0.75);
1677   do_simple_exif_tag_serialization_deserialization
1678       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1679
1680   g_value_set_double (&value, 0.0);
1681   do_simple_exif_tag_serialization_deserialization
1682       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1683   g_value_set_double (&value, 180.5);
1684   do_simple_exif_tag_serialization_deserialization
1685       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1686   g_value_set_double (&value, 0.12345);
1687   do_simple_exif_tag_serialization_deserialization
1688       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1689   g_value_set_double (&value, 359.9);
1690   do_simple_exif_tag_serialization_deserialization
1691       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1692
1693   g_value_set_double (&value, 0.0);
1694   do_simple_exif_tag_serialization_deserialization
1695       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1696   g_value_set_double (&value, 321.456);
1697   do_simple_exif_tag_serialization_deserialization
1698       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1699   g_value_set_double (&value, -12.56);
1700   do_simple_exif_tag_serialization_deserialization
1701       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1702
1703   g_value_set_double (&value, 0);
1704   do_simple_exif_tag_serialization_deserialization
1705       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1706   g_value_set_double (&value, 100 / 3.6);
1707   do_simple_exif_tag_serialization_deserialization
1708       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1709
1710   g_value_set_double (&value, 0);
1711   do_simple_exif_tag_serialization_deserialization
1712       (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, &value);
1713   g_value_set_double (&value, 50.25);
1714   do_simple_exif_tag_serialization_deserialization
1715       (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, &value);
1716
1717   g_value_set_double (&value, 0);
1718   do_simple_exif_tag_serialization_deserialization
1719       (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value);
1720   g_value_set_double (&value, 2.5);
1721   do_simple_exif_tag_serialization_deserialization
1722       (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value);
1723   g_value_set_double (&value, 8.75);
1724   do_simple_exif_tag_serialization_deserialization
1725       (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value);
1726
1727   g_value_set_double (&value, 20.0);
1728   do_simple_exif_tag_serialization_deserialization
1729       (GST_TAG_CAPTURING_FOCAL_LENGTH, &value);
1730   g_value_set_double (&value, 5.5);
1731   do_simple_exif_tag_serialization_deserialization
1732       (GST_TAG_CAPTURING_FOCAL_LENGTH, &value);
1733
1734   g_value_set_double (&value, 16);
1735   do_simple_exif_tag_serialization_deserialization
1736       (GST_TAG_CAPTURING_FOCAL_RATIO, &value);
1737   g_value_set_double (&value, 2.7);
1738   do_simple_exif_tag_serialization_deserialization
1739       (GST_TAG_CAPTURING_FOCAL_LENGTH, &value);
1740
1741   g_value_set_double (&value, 96.0);
1742   do_simple_exif_tag_serialization_deserialization
1743       (GST_TAG_IMAGE_HORIZONTAL_PPI, &value);
1744   g_value_set_double (&value, 300.0);
1745   do_simple_exif_tag_serialization_deserialization
1746       (GST_TAG_IMAGE_HORIZONTAL_PPI, &value);
1747   g_value_set_double (&value, 87.5);
1748   do_simple_exif_tag_serialization_deserialization
1749       (GST_TAG_IMAGE_VERTICAL_PPI, &value);
1750   g_value_set_double (&value, 600.0);
1751   do_simple_exif_tag_serialization_deserialization
1752       (GST_TAG_IMAGE_VERTICAL_PPI, &value);
1753
1754   g_value_set_double (&value, 0.0);
1755   do_simple_exif_tag_serialization_deserialization
1756       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1757   g_value_set_double (&value, 1.0);
1758   do_simple_exif_tag_serialization_deserialization
1759       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1760   g_value_set_double (&value, -2.5);
1761   do_simple_exif_tag_serialization_deserialization
1762       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1763   g_value_unset (&value);
1764
1765   g_value_init (&value, G_TYPE_INT);
1766   g_value_set_int (&value, 400);
1767   do_simple_exif_tag_serialization_deserialization
1768       (GST_TAG_CAPTURING_ISO_SPEED, &value);
1769   g_value_set_int (&value, 1600);
1770   do_simple_exif_tag_serialization_deserialization
1771       (GST_TAG_CAPTURING_ISO_SPEED, &value);
1772   g_value_unset (&value);
1773
1774   g_value_init (&value, GST_TYPE_DATE_TIME);
1775   datetime = gst_date_time_new_local_time (2010, 6, 22, 12, 5, 10);
1776   g_value_set_boxed (&value, datetime);
1777   gst_date_time_unref (datetime);
1778   do_simple_exif_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1779   g_value_unset (&value);
1780
1781   g_value_init (&value, GST_TYPE_BUFFER);
1782   buf = gst_buffer_new_and_alloc (1024);
1783   for (i = 0; i < 1024; i++)
1784     GST_BUFFER_DATA (buf)[i] = i % 255;
1785   gst_value_set_buffer (&value, buf);
1786   gst_buffer_unref (buf);
1787   do_simple_exif_tag_serialization_deserialization (GST_TAG_APPLICATION_DATA,
1788       &value);
1789   g_value_unset (&value);
1790
1791   g_value_init (&value, GST_TYPE_FRACTION);
1792   gst_value_set_fraction (&value, 1, 1);
1793   do_simple_exif_tag_serialization_deserialization
1794       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1795   gst_value_set_fraction (&value, 1, 30);
1796   do_simple_exif_tag_serialization_deserialization
1797       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1798   gst_value_set_fraction (&value, 1, 200);
1799   do_simple_exif_tag_serialization_deserialization
1800       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1801   gst_value_set_fraction (&value, 1, 8000);
1802   do_simple_exif_tag_serialization_deserialization
1803       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1804   g_value_unset (&value);
1805
1806   /* flash is a little bit more tricky, because 2 tags are merged into 1 in
1807    * exif */
1808   taglist = gst_tag_list_new_full (GST_TAG_CAPTURING_FLASH_FIRED, FALSE,
1809       GST_TAG_CAPTURING_FLASH_MODE, "auto", NULL);
1810   do_exif_tag_serialization_deserialization (taglist);
1811   gst_tag_list_free (taglist);
1812
1813   taglist = gst_tag_list_new_full (GST_TAG_CAPTURING_FLASH_FIRED, TRUE,
1814       GST_TAG_CAPTURING_FLASH_MODE, "auto", NULL);
1815   do_exif_tag_serialization_deserialization (taglist);
1816   gst_tag_list_free (taglist);
1817
1818   taglist = gst_tag_list_new_full (GST_TAG_CAPTURING_FLASH_FIRED, FALSE,
1819       GST_TAG_CAPTURING_FLASH_MODE, "never", NULL);
1820   do_exif_tag_serialization_deserialization (taglist);
1821   gst_tag_list_free (taglist);
1822
1823   taglist = gst_tag_list_new_full (GST_TAG_CAPTURING_FLASH_FIRED, TRUE,
1824       GST_TAG_CAPTURING_FLASH_MODE, "always", NULL);
1825   do_exif_tag_serialization_deserialization (taglist);
1826   gst_tag_list_free (taglist);
1827 }
1828
1829 GST_END_TEST;
1830
1831 static Suite *
1832 tag_suite (void)
1833 {
1834   Suite *s = suite_create ("tag support library");
1835   TCase *tc_chain = tcase_create ("general");
1836
1837   suite_add_tcase (s, tc_chain);
1838   tcase_add_test (tc_chain, test_musicbrainz_tag_registration);
1839   tcase_add_test (tc_chain, test_parse_extended_comment);
1840   tcase_add_test (tc_chain, test_vorbis_tags);
1841   tcase_add_test (tc_chain, test_id3_tags);
1842   tcase_add_test (tc_chain, test_id3v1_utf8_tag);
1843   tcase_add_test (tc_chain, test_language_utils);
1844   tcase_add_test (tc_chain, test_license_utils);
1845   tcase_add_test (tc_chain, test_xmp_formatting);
1846   tcase_add_test (tc_chain, test_xmp_parsing);
1847   tcase_add_test (tc_chain, test_xmp_tags_serialization_deserialization);
1848   tcase_add_test (tc_chain, test_xmp_compound_tags);
1849   tcase_add_test (tc_chain, test_exif_parsing);
1850   tcase_add_test (tc_chain, test_exif_tags_serialization_deserialization);
1851   tcase_add_test (tc_chain, test_exif_multiple_tags);
1852   return s;
1853 }
1854
1855 int
1856 main (int argc, char **argv)
1857 {
1858   int nf;
1859
1860   Suite *s = tag_suite ();
1861   SRunner *sr = srunner_create (s);
1862
1863   gst_check_init (&argc, &argv);
1864
1865   srunner_run_all (sr, CK_NORMAL);
1866   nf = srunner_ntests_failed (sr);
1867   srunner_free (sr);
1868
1869   return nf;
1870 }