tests: tags: add unit test for ID3 v2.4 extended headers
[platform/upstream/gstreamer.git] / 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., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, 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_empty ();
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_unref (list);
208 }
209
210 GST_END_TEST;
211
212 GST_START_TEST (test_vorbis_tags)
213 {
214   GstTagList *list;
215
216   list = gst_tag_list_new_empty ();
217
218   /* NULL pointers aren't allowed */
219   ASSERT_CRITICAL (gst_vorbis_tag_add (NULL, "key", "value"));
220   ASSERT_CRITICAL (gst_vorbis_tag_add (list, NULL, "value"));
221   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "key", NULL));
222
223   /* must be UTF-8 */
224   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "key", "v\377lue"));
225   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "k\377y", "value"));
226
227   /* key can't have a '=' in it */
228   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "k=y", "value"));
229   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "key=", "value"));
230
231   /* should be allowed in values though */
232   gst_vorbis_tag_add (list, "keeey", "va=ue");
233
234   /* add some tags */
235   gst_vorbis_tag_add (list, "TITLE", "Too");
236   gst_vorbis_tag_add (list, "ALBUM", "Aoo");
237   gst_vorbis_tag_add (list, "ARTIST", "Alboo");
238   gst_vorbis_tag_add (list, "PERFORMER", "Perfoo");
239   gst_vorbis_tag_add (list, "COPYRIGHT", "Copyfoo");
240   gst_vorbis_tag_add (list, "DESCRIPTION", "Descoo");
241   gst_vorbis_tag_add (list, "LICENSE", "Licoo");
242   gst_vorbis_tag_add (list, "LICENSE",
243       "http://creativecommons.org/licenses/by/3.0/");
244   gst_vorbis_tag_add (list, "LOCATION", "Bristol, UK");
245   gst_vorbis_tag_add (list, "ORGANIZATION", "Orgoo");
246   gst_vorbis_tag_add (list, "GENRE", "Goo");
247   gst_vorbis_tag_add (list, "CONTACT", "Coo");
248   gst_vorbis_tag_add (list, "COMMENT", "Stroodle is good");
249   gst_vorbis_tag_add (list, "COMMENT", "Peroxysulfid stroodles the brain");
250
251   gst_vorbis_tag_add (list, "TRACKNUMBER", "5");
252   gst_vorbis_tag_add (list, "TRACKTOTAL", "77");
253   gst_vorbis_tag_add (list, "DISCNUMBER", "1");
254   gst_vorbis_tag_add (list, "DISCTOTAL", "2");
255   gst_vorbis_tag_add (list, "DATE", "1954-12-31");
256
257   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_TITLE, "Too");
258   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ALBUM, "Aoo");
259   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST, "Alboo");
260   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_PERFORMER, "Perfoo");
261   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_COPYRIGHT, "Copyfoo");
262   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_DESCRIPTION, "Descoo");
263   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LICENSE, "Licoo");
264   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LICENSE_URI,
265       "http://creativecommons.org/licenses/by/3.0/");
266   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_GEO_LOCATION_NAME, "Bristol, UK");
267   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ORGANIZATION, "Orgoo");
268   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_GENRE, "Goo");
269   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_CONTACT, "Coo");
270   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_COMMENT,
271       "Peroxysulfid stroodles the brain");
272   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_COMMENT, "Stroodle is good");
273   ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_TRACK_NUMBER, 5);
274   ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_TRACK_COUNT, 77);
275   ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_ALBUM_VOLUME_NUMBER, 1);
276   ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_ALBUM_VOLUME_COUNT, 2);
277
278   {
279     GstDateTime *dt = NULL;
280
281     fail_unless (gst_tag_list_get_date_time (list, GST_TAG_DATE_TIME, &dt));
282     fail_unless (dt != NULL);
283     fail_unless (gst_date_time_get_day (dt) == 31);
284     fail_unless (gst_date_time_get_month (dt) == 12);
285     fail_unless (gst_date_time_get_year (dt) == 1954);
286     fail_unless (!gst_date_time_has_time (dt));
287
288     gst_date_time_unref (dt);
289   }
290
291   /* unknown vorbis comments should go into a GST_TAG_EXTENDED_COMMENT */
292   gst_vorbis_tag_add (list, "CoEdSub_ID", "98172AF-973-10-B");
293   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_EXTENDED_COMMENT,
294       "CoEdSub_ID=98172AF-973-10-B");
295   gst_vorbis_tag_add (list, "RuBuWuHash", "1337BA42F91");
296   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_EXTENDED_COMMENT,
297       "RuBuWuHash=1337BA42F91");
298
299   gst_vorbis_tag_add (list, "REPLAYGAIN_REFERENCE_LOUDNESS", "89.");
300   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_REFERENCE_LEVEL, 89.);
301   gst_vorbis_tag_add (list, "REPLAYGAIN_TRACK_GAIN", "+12.36");
302   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_TRACK_GAIN, +12.36);
303   gst_vorbis_tag_add (list, "REPLAYGAIN_TRACK_PEAK", "0.96349");
304   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_TRACK_PEAK, 0.96349);
305   gst_vorbis_tag_add (list, "REPLAYGAIN_ALBUM_GAIN", "+10.12");
306   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_ALBUM_GAIN, +10.12);
307   /* now check that we can parse floating point numbers with any separator
308    * (',' or '.') regardless of the current locale */
309   gst_vorbis_tag_add (list, "REPLAYGAIN_ALBUM_PEAK", "0,98107");
310   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_ALBUM_PEAK, 0.98107);
311   gst_vorbis_tag_add (list, "LICENSE", "http://foo.com/license-1.html");
312
313   /* make sure we can convert back and forth without loss */
314   {
315     GstTagList *new_list, *even_newer_list;
316     GstBuffer *buf, *buf2;
317     gchar *vendor_id = NULL;
318
319     buf = gst_tag_list_to_vorbiscomment_buffer (list,
320         (const guint8 *) "\003vorbis", 7, "libgstunittest");
321     fail_unless (buf != NULL);
322     new_list = gst_tag_list_from_vorbiscomment_buffer (buf,
323         (const guint8 *) "\003vorbis", 7, &vendor_id);
324     fail_unless (new_list != NULL);
325     fail_unless (vendor_id != NULL);
326     g_free (vendor_id);
327     vendor_id = NULL;
328
329     GST_LOG ("new_list = %" GST_PTR_FORMAT, new_list);
330     fail_unless (gst_tag_list_is_equal (list, new_list));
331
332     buf2 = gst_tag_list_to_vorbiscomment_buffer (new_list,
333         (const guint8 *) "\003vorbis", 7, "libgstunittest");
334     fail_unless (buf2 != NULL);
335     even_newer_list = gst_tag_list_from_vorbiscomment_buffer (buf2,
336         (const guint8 *) "\003vorbis", 7, &vendor_id);
337     fail_unless (even_newer_list != NULL);
338     fail_unless (vendor_id != NULL);
339     g_free (vendor_id);
340     vendor_id = NULL;
341
342     GST_LOG ("even_newer_list = %" GST_PTR_FORMAT, even_newer_list);
343     fail_unless (gst_tag_list_is_equal (new_list, even_newer_list));
344
345     gst_tag_list_unref (new_list);
346     gst_tag_list_unref (even_newer_list);
347     gst_buffer_unref (buf);
348     gst_buffer_unref (buf2);
349   }
350
351   /* there can only be one language per taglist ... */
352   gst_tag_list_unref (list);
353   list = gst_tag_list_new_empty ();
354   gst_vorbis_tag_add (list, "LANGUAGE", "fr");
355   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "fr");
356
357   gst_tag_list_unref (list);
358   list = gst_tag_list_new_empty ();
359   gst_vorbis_tag_add (list, "LANGUAGE", "[fr]");
360   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "fr");
361
362   gst_tag_list_unref (list);
363   list = gst_tag_list_new_empty ();
364   gst_vorbis_tag_add (list, "LANGUAGE", "French [fr]");
365   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "fr");
366
367   gst_tag_list_unref (list);
368   list = gst_tag_list_new_empty ();
369   gst_vorbis_tag_add (list, "LANGUAGE", "[eng] English");
370   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "eng");
371
372   gst_tag_list_unref (list);
373   list = gst_tag_list_new_empty ();
374   gst_vorbis_tag_add (list, "LANGUAGE", "eng");
375   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "eng");
376
377   gst_tag_list_unref (list);
378   list = gst_tag_list_new_empty ();
379   gst_vorbis_tag_add (list, "LANGUAGE", "[eng]");
380   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "eng");
381
382   /* free-form *sigh* */
383   gst_tag_list_unref (list);
384   list = gst_tag_list_new_empty ();
385   gst_vorbis_tag_add (list, "LANGUAGE", "English");
386   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "English");
387
388   /* now, while we still have a taglist, test _to_vorbiscomment_buffer() */
389   {
390     GstBuffer *buf1, *buf2;
391     GstMapInfo map1, map2;
392
393     ASSERT_CRITICAL (gst_tag_list_to_vorbiscomment_buffer (NULL,
394             (const guint8 *) "x", 1, "x"));
395
396     buf1 = gst_tag_list_to_vorbiscomment_buffer (list, NULL, 0, NULL);
397     fail_unless (buf1 != NULL);
398
399     buf2 = gst_tag_list_to_vorbiscomment_buffer (list,
400         (const guint8 *) "foo", 3, NULL);
401     fail_unless (buf2 != NULL);
402
403     gst_buffer_map (buf1, &map1, GST_MAP_READ);
404     gst_buffer_map (buf2, &map2, GST_MAP_READ);
405
406     fail_unless (memcmp (map1.data, map2.data + 3, map1.size) == 0);
407
408     gst_buffer_unmap (buf2, &map2);
409     gst_buffer_unmap (buf1, &map1);
410
411     gst_buffer_unref (buf1);
412     gst_buffer_unref (buf2);
413   }
414
415   gst_tag_list_unref (list);
416
417   /* make sure gst_tag_list_from_vorbiscomment_buffer() works with an
418    * empty ID (for Speex) */
419   {
420     const guint8 speex_comments_buf1[] = { 0x03, 0x00, 0x00, 0x00, 'f', 'o',
421       'o', 0x00, 0x00, 0x00, 0x00
422     };
423     GstBuffer *buf;
424     gchar *vendor = NULL;
425
426     buf = gst_buffer_new ();
427     gst_buffer_append_memory (buf,
428         gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
429             (gpointer) speex_comments_buf1,
430             sizeof (speex_comments_buf1), 0, sizeof (speex_comments_buf1), NULL,
431             NULL));
432
433     /* make sure it doesn't memcmp over the end of the buffer */
434     fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf,
435             (const guint8 *) "averylongstringbrownfoxjumpoverthefence", 39,
436             &vendor) == NULL);
437     fail_unless (vendor == NULL);
438
439     /* make sure it bails out if the ID doesn't match */
440     fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf,
441             (guint8 *) "short", 4, &vendor) == NULL);
442     fail_unless (vendor == NULL);
443
444     /* now read properly */
445     list = gst_tag_list_from_vorbiscomment_buffer (buf, NULL, 0, &vendor);
446     fail_unless (vendor != NULL);
447     fail_unless_equals_string (vendor, "foo");
448     fail_unless (list != NULL);
449     fail_unless (gst_tag_list_n_tags (list) == 0);
450     g_free (vendor);
451     gst_tag_list_unref (list);
452
453     /* now again without vendor */
454     list = gst_tag_list_from_vorbiscomment_buffer (buf, NULL, 0, NULL);
455     fail_unless (list != NULL);
456     fail_unless (gst_tag_list_n_tags (list) == 0);
457     gst_tag_list_unref (list);
458
459     gst_buffer_unref (buf);
460   }
461
462   /* the same with an ID */
463   {
464     const guint8 vorbis_comments_buf[] = { 0x03, 'v', 'o', 'r', 'b', 'i', 's',
465       0x03, 0x00, 0x00, 0x00, 'f', 'o', 'o', 0x01, 0x00, 0x00, 0x00,
466       strlen ("ARTIST=foo bar"), 0x00, 0x00, 0x00, 'A', 'R', 'T', 'I', 'S',
467       'T', '=', 'f', 'o', 'o', ' ', 'b', 'a', 'r'
468     };
469     GstBuffer *buf;
470     gchar *vendor = NULL;
471
472     buf = gst_buffer_new ();
473     gst_buffer_append_memory (buf,
474         gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
475             (gpointer) vorbis_comments_buf,
476             sizeof (vorbis_comments_buf), 0, sizeof (vorbis_comments_buf), NULL,
477             NULL));
478
479     /* make sure it doesn't memcmp over the end of the buffer */
480     fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf,
481             (const guint8 *) "averylongstringbrownfoxjumpoverthefence", 39,
482             &vendor) == NULL);
483     fail_unless (vendor == NULL);
484
485     /* make sure it bails out if the ID doesn't match */
486     fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf,
487             (guint8 *) "short", 4, &vendor) == NULL);
488     fail_unless (vendor == NULL);
489
490     /* now read properly */
491     list = gst_tag_list_from_vorbiscomment_buffer (buf,
492         (guint8 *) "\003vorbis", 7, &vendor);
493     fail_unless (vendor != NULL);
494     fail_unless_equals_string (vendor, "foo");
495     fail_unless (list != NULL);
496     fail_unless (gst_tag_list_n_tags (list) == 1);
497     ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST, "foo bar");
498     g_free (vendor);
499     gst_tag_list_unref (list);
500
501     /* now again without vendor */
502     list = gst_tag_list_from_vorbiscomment_buffer (buf,
503         (guint8 *) "\003vorbis", 7, NULL);
504     fail_unless (list != NULL);
505     fail_unless (gst_tag_list_n_tags (list) == 1);
506     ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST, "foo bar");
507     gst_tag_list_unref (list);
508
509     gst_buffer_unref (buf);
510   }
511
512   /* check date with time */
513   {
514     GstDateTime *dt = NULL;
515
516     list = gst_tag_list_new_empty ();
517     gst_vorbis_tag_add (list, "DATE", "2006-09-25 22:02:38");
518
519     fail_unless (gst_tag_list_get_date_time (list, GST_TAG_DATE_TIME, &dt));
520     fail_unless (dt != NULL);
521     fail_unless (gst_date_time_get_day (dt) == 25);
522     fail_unless (gst_date_time_get_month (dt) == 9);
523     fail_unless (gst_date_time_get_year (dt) == 2006);
524     fail_unless (gst_date_time_has_time (dt));
525
526     gst_date_time_unref (dt);
527     gst_tag_list_unref (list);
528   }
529
530   /* check date with month/day of 00-00 */
531   {
532     GstDateTime *dt = NULL;
533
534     list = gst_tag_list_new_empty ();
535     gst_vorbis_tag_add (list, "DATE", "1992-00-00");
536
537     fail_unless (gst_tag_list_get_date_time (list, GST_TAG_DATE_TIME, &dt));
538     fail_unless (dt != NULL);
539     fail_unless (gst_date_time_get_year (dt) == 1992);
540     fail_unless (!gst_date_time_has_month (dt));
541     fail_unless (!gst_date_time_has_day (dt));
542     fail_unless (!gst_date_time_has_time (dt));
543
544     gst_date_time_unref (dt);
545     gst_tag_list_unref (list);
546   }
547
548   /* check date with valid month, but day of 00 */
549   {
550     GstDateTime *dt = NULL;
551
552     list = gst_tag_list_new_empty ();
553     gst_vorbis_tag_add (list, "DATE", "1992-05-00");
554
555     fail_unless (gst_tag_list_get_date_time (list, GST_TAG_DATE_TIME, &dt));
556     fail_unless (dt != NULL);
557     fail_unless (gst_date_time_get_year (dt) == 1992);
558     fail_unless (gst_date_time_get_month (dt) == 5);
559     fail_unless (!gst_date_time_has_day (dt));
560     fail_unless (!gst_date_time_has_time (dt));
561
562     gst_date_time_unref (dt);
563     gst_tag_list_unref (list);
564   }
565 }
566
567 GST_END_TEST;
568
569 GST_START_TEST (test_id3_tags)
570 {
571   guint i;
572
573   fail_unless (gst_tag_id3_genre_count () > 0);
574
575   for (i = 0; i < gst_tag_id3_genre_count (); ++i) {
576     const gchar *genre;
577
578     genre = gst_tag_id3_genre_get (i);
579     GST_LOG ("genre: %s", genre);
580     fail_unless (genre != NULL);
581   }
582
583   {
584     /* TODO: GstTagList *gst_tag_list_new_from_id3v1 (const guint8 *data) */
585   }
586
587   /* gst_tag_from_id3_tag */
588   fail_unless (gst_tag_from_id3_tag ("TALB") != NULL);
589   ASSERT_CRITICAL (gst_tag_from_id3_tag (NULL));
590   fail_unless (gst_tag_from_id3_tag ("R2D2") == NULL);
591   fail_unless_equals_string (gst_tag_from_id3_tag ("WCOP"),
592       GST_TAG_COPYRIGHT_URI);
593
594   /* gst_tag_from_id3_user_tag */
595   ASSERT_CRITICAL (gst_tag_from_id3_user_tag (NULL, "foo"));
596   ASSERT_CRITICAL (gst_tag_from_id3_user_tag ("foo", NULL));
597   fail_unless (gst_tag_from_id3_user_tag ("R2D2", "R2D2") == NULL);
598
599   /* gst_tag_to_id3_tag */
600   ASSERT_CRITICAL (gst_tag_to_id3_tag (NULL));
601   fail_unless (gst_tag_to_id3_tag ("R2D2") == NULL);
602   fail_unless (gst_tag_to_id3_tag (GST_TAG_ARTIST) != NULL);
603   fail_unless_equals_string (gst_tag_to_id3_tag (GST_TAG_COPYRIGHT_URI),
604       "WCOP");
605
606   fail_unless (GST_TYPE_TAG_IMAGE_TYPE != 0);
607   fail_unless (g_type_name (GST_TYPE_TAG_IMAGE_TYPE) != NULL);
608 }
609
610 GST_END_TEST;
611
612
613 GST_START_TEST (test_id3v1_utf8_tag)
614 {
615   const guint8 id3v1[128] = {
616     /* marker */
617     'T', 'A', 'G',
618     /* title (30 bytes) */
619     'D', 0xc3, 0xad, 'v', 'k', 'a', ' ', 's',
620     ' ', 'p', 'e', 'r', 'l', 'a', 'm', 'i',
621     ' ', 'v', 'e', ' ', 'v', 'l', 'a', 's',
622     'e', 'c', 'h', 0, 0, 0,
623     /* artist (30 bytes) */
624     'A', 'l', 'e', 0xc5, 0xa1, ' ', 'B', 'r', 'i', 'c', 'h', 't', 'a',
625     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
626     /* album (30 bytes) */
627     'B', 'e', 's', 't', ' ', 'o', 'f', ' ', '(', 'P', 'r', 'o', 's', 't',
628     0xc4, 0x9b, ' ', 0xc3, 0xba, 0xc5, 0xbe, 'a', 's', 'n', 0xc3, 0xbd, ')',
629     0, 0, 0,
630     /* year (4 bytes) */
631     '2', '0', '0', '0',
632     /* comment (28 bytes) */
633     '-', '-', '-', ' ', 0xc4, 0x8d, 'e', 's', 'k', 0xc3, 0xa9, ' ', 'p',
634     0xc3, 0xad, 's', 'n', 'i', 0xc4, 0x8d, 'k', 'y', ' ', '-', '-', '-',
635     0, 0,
636     /* track number */
637     0, 0,
638     /* genre */
639     0x11
640   };
641   GstDateTime *dt;
642   GstTagList *tags;
643   gchar *s;
644
645   /* set this, to make sure UTF-8 strings are really interpreted properly
646    * as UTF-8, regardless of the locale set */
647   g_setenv ("GST_ID3V1_TAG_ENCODING", "WINDOWS-1250", TRUE);
648
649   tags = gst_tag_list_new_from_id3v1 (id3v1);
650   fail_unless (tags != NULL);
651
652   GST_LOG ("Got tags: %" GST_PTR_FORMAT, tags);
653
654   s = NULL;
655   fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &s));
656   fail_unless (s != NULL);
657   fail_unless_equals_string (s, "Dívka s perlami ve vlasech");
658   g_free (s);
659
660   s = NULL;
661   fail_unless (gst_tag_list_get_string (tags, GST_TAG_ARTIST, &s));
662   fail_unless (s != NULL);
663   fail_unless_equals_string (s, "Aleš Brichta");
664   g_free (s);
665
666   s = NULL;
667   fail_unless (gst_tag_list_get_string (tags, GST_TAG_ALBUM, &s));
668   fail_unless (s != NULL);
669   fail_unless_equals_string (s, "Best of (Prostě úžasný)");
670   g_free (s);
671
672   dt = NULL;
673   fail_unless (gst_tag_list_get_date_time (tags, GST_TAG_DATE_TIME, &dt));
674   fail_unless (dt != NULL);
675   fail_unless_equals_int (gst_date_time_get_year (dt), 2000);
676   fail_if (gst_date_time_has_month (dt));
677   fail_if (gst_date_time_has_day (dt));
678   fail_if (gst_date_time_has_time (dt));
679   gst_date_time_unref (dt);
680   dt = NULL;
681
682   gst_tag_list_unref (tags);
683
684   g_unsetenv ("GST_ID3V1_TAG_ENCODING");
685 }
686
687 GST_END_TEST;
688
689 GST_START_TEST (test_id3v2_priv_tag)
690 {
691   const guint8 id3v2[] = {
692     0x49, 0x44, 0x33, 0x04, 0x00, 0x00, 0x00, 0x00,
693     0x00, 0x3f, 0x50, 0x52, 0x49, 0x56, 0x00, 0x00,
694     0x00, 0x35, 0x00, 0x00, 0x63, 0x6f, 0x6d, 0x2e,
695     0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x73, 0x74,
696     0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x2e,
697     0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
698     0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54,
699     0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
700     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xbb,
701     0xa0
702   };
703   const GstStructure *s;
704   GstTagList *tags;
705   GstSample *sample = NULL;
706   GstBuffer *buf;
707   GstMapInfo map;
708   gchar *owner = NULL;
709
710   buf = gst_buffer_new_allocate (NULL, sizeof (id3v2), NULL);
711   gst_buffer_fill (buf, 0, id3v2, sizeof (id3v2));
712
713   tags = gst_tag_list_from_id3v2_tag (buf);
714   gst_buffer_unref (buf);
715
716   fail_if (tags == NULL, "Failed to parse ID3 tag");
717
718   GST_LOG ("tags: %" GST_PTR_FORMAT, tags);
719
720   if (!gst_tag_list_get_sample (tags, GST_TAG_PRIVATE_DATA, &sample))
721     g_error ("Failed to get PRIVATE_DATA tag");
722
723   s = gst_sample_get_info (sample);
724   buf = gst_sample_get_buffer (sample);
725
726   if (!gst_structure_has_name (s, "ID3PrivateFrame"))
727     g_error ("wrong info name");
728
729   gst_structure_get (s, "owner", G_TYPE_STRING, &owner, NULL);
730   fail_unless (owner != NULL);
731
732   fail_unless_equals_string (owner,
733       "com.apple.streaming.transportStreamTimestamp");
734
735   fail_unless_equals_int (gst_buffer_get_size (buf), 8);
736
737   gst_buffer_map (buf, &map, GST_MAP_READ);
738   GST_MEMDUMP ("private data", map.data, map.size);
739   fail_unless_equals_uint64 (GST_READ_UINT64_BE (map.data), 0x0dbba0);
740   gst_buffer_unmap (buf, &map);
741   g_free (owner);
742
743   gst_sample_unref (sample);
744   gst_tag_list_unref (tags);
745 }
746
747 GST_END_TEST;
748
749 static GstTagList *
750 parse_id3v2_tag_from_data (const guint8 * id3v2, gsize id3v2_size)
751 {
752   GstTagList *tags;
753   GstBuffer *buf;
754
755   GST_MEMDUMP ("id3v2 tag", id3v2, id3v2_size);
756
757   buf = gst_buffer_new_allocate (NULL, id3v2_size, NULL);
758   gst_buffer_fill (buf, 0, id3v2, id3v2_size);
759   tags = gst_tag_list_from_id3v2_tag (buf);
760   gst_buffer_unref (buf);
761
762   return tags;
763 }
764
765 GST_START_TEST (test_id3v2_extended_header)
766 {
767   const guint8 id3v24_exthdr[1024] = {
768     0x49, 0x44, 0x33, 0x04, 0x00, 0x40, 0x00, 0x00, 0x07, 0x76,
769     0x00, 0x00, 0x00, 0x0c, 0x01, 0x20, 0x05, 0x0b, 0x7f, 0x06,
770     0x43, 0x22, 0x54, 0x53, 0x53, 0x45, 0x00, 0x00, 0x00, 0x0e,
771     0x00, 0x00, 0x03, 0x4c, 0x61, 0x76, 0x66, 0x35, 0x37, 0x2e,
772     0x37, 0x31, 0x2e, 0x31, 0x30, 0x30, 0x54, 0x49, 0x54, 0x32,
773     0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x53, 0x69, 0x6c,
774     0x65, 0x6e, 0x63, 0x65, 0x54, 0x50, 0x45, 0x31, 0x00, 0x00,
775     0x00, 0x07, 0x00, 0x00, 0x03, 0x4e, 0x6f, 0x20, 0x6f, 0x6e,
776     0x65, 0x54, 0x50, 0x45, 0x32, 0x00, 0x00, 0x00, 0x05, 0x00,
777     0x00, 0x03, 0x4e, 0x6f, 0x6e, 0x65, 0x54, 0x41, 0x4c, 0x42,
778     0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x4e, 0x65, 0x69,
779     0x74, 0x68, 0x65, 0x72, 0x54, 0x44, 0x52, 0x43, 0x00, 0x00,
780     0x00, 0x05, 0x00, 0x00, 0x03, 0x32, 0x30, 0x31, 0x38, 0x54,
781     0x52, 0x43, 0x4b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03,
782     0x30, 0x31, 0x2f, 0x30, 0x31, 0x54, 0x43, 0x4f, 0x4e, 0x00,
783     0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x28, 0x31, 0x34, 0x38,
784     0x29,
785   };
786   const guint8 id3v2_exthdr[] = {
787     0x49, 0x44, 0x33, 0x03, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1b,
788     0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
789     0x54, 0x50, 0x45, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
790     0x00, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x65
791   };
792   const guint8 id3v2_no_exthdr[] = {
793     0x49, 0x44, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
794     0x54, 0x50, 0x45, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
795     0x00, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x65
796   };
797   GstTagList *tags;
798
799   tags = parse_id3v2_tag_from_data (id3v2_exthdr, sizeof (id3v2_exthdr));
800   fail_if (tags == NULL, "Failed to parse ID3 v2.3 tag with extension header");
801   GST_LOG ("tags: %" GST_PTR_FORMAT, tags);
802   fail_unless_equals_int (gst_tag_list_n_tags (tags), 1);
803   gst_tag_list_unref (tags);
804
805   tags = parse_id3v2_tag_from_data (id3v24_exthdr, sizeof (id3v24_exthdr));
806   fail_if (tags == NULL, "Failed to parse ID3 v2.4 tag with extension header");
807   GST_LOG ("tags: %" GST_PTR_FORMAT, tags);
808   fail_unless_equals_int (gst_tag_list_n_tags (tags), 9);
809   gst_tag_list_unref (tags);
810
811   tags = parse_id3v2_tag_from_data (id3v2_no_exthdr, sizeof (id3v2_no_exthdr));
812   fail_if (tags == NULL, "Failed to parse ID3 tag without extension header");
813   GST_LOG ("tags: %" GST_PTR_FORMAT, tags);
814   fail_unless_equals_int (gst_tag_list_n_tags (tags), 1);
815   gst_tag_list_unref (tags);
816 }
817
818 GST_END_TEST;
819
820 GST_START_TEST (test_id3v2_string_list_utf16)
821 {
822   const guint8 id3v2[] = {
823     0x49, 0x44, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
824     0x43, 0x4f, 0x4d, 0x4d, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00,
825     0x01, 0x65, 0x6e, 0x67, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xfe,
826     0x4e, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x20, 0x00,
827     0x4d, 0x00, 0x50, 0x00, 0x33, 0x00, 0x20, 0x00, 0x4d, 0x00,
828     0x75, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00,
829     0x4c, 0x00, 0x69, 0x00, 0x62, 0x00, 0x72, 0x00, 0x61, 0x00,
830     0x72, 0x00, 0x79, 0x00
831   };
832   GstTagList *tags;
833   gchar *comment = NULL;
834
835   tags = parse_id3v2_tag_from_data (id3v2, sizeof (id3v2));
836   fail_if (tags == NULL,
837       "Failed to parse ID3 tag with UTF-16 strings and BOMs");
838
839   GST_LOG ("tags: %" GST_PTR_FORMAT, tags);
840
841   gst_tag_list_get_string (tags, GST_TAG_COMMENT, &comment);
842   fail_unless (comment != NULL, "Expected comment tag");
843   GST_MEMDUMP ("comment string UTF-8", (guint8 *) comment, strlen (comment));
844   fail_unless_equals_string (comment, "Naim MP3 Music Library");
845   g_free (comment);
846   gst_tag_list_unref (tags);
847 }
848
849 GST_END_TEST;
850
851 GST_START_TEST (test_language_utils)
852 {
853   gchar **lang_codes, **c;
854
855 #define ASSERT_STRINGS_EQUAL fail_unless_equals_string
856
857   lang_codes = gst_tag_get_language_codes ();
858   fail_unless (lang_codes != NULL);
859   fail_unless (*lang_codes != NULL);
860
861   for (c = lang_codes; c != NULL && *c != NULL; ++c) {
862     const gchar *lang_name, *c1, *c2t, *c2b;
863
864     lang_name = gst_tag_get_language_name (*c);
865     fail_unless (lang_name != NULL);
866     fail_unless (g_utf8_validate (lang_name, -1, NULL));
867
868     c1 = gst_tag_get_language_code_iso_639_1 (*c);
869     fail_unless (c1 != NULL);
870     fail_unless (g_utf8_validate (c1, -1, NULL));
871
872     c2t = gst_tag_get_language_code_iso_639_2T (*c);
873     fail_unless (c2t != NULL);
874     fail_unless (g_utf8_validate (c2t, -1, NULL));
875
876     c2b = gst_tag_get_language_code_iso_639_2B (*c);
877     fail_unless (c2b != NULL);
878     fail_unless (g_utf8_validate (c2b, -1, NULL));
879
880     ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (*c), *c);
881     ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (c2t), *c);
882     ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (c2b), *c);
883
884     GST_DEBUG ("[%s] %s %s %s : %s", *c, c1, c2t, c2b, lang_name);
885
886   }
887   g_strfreev (lang_codes);
888
889   fail_unless (gst_tag_get_language_name ("de") != NULL);
890   fail_unless (gst_tag_get_language_name ("deu") != NULL);
891   fail_unless (gst_tag_get_language_name ("ger") != NULL);
892   fail_unless_equals_string (gst_tag_get_language_name ("deu"),
893       gst_tag_get_language_name ("ger"));
894   fail_unless_equals_string (gst_tag_get_language_name ("de"),
895       gst_tag_get_language_name ("ger"));
896   fail_unless (gst_tag_get_language_name ("de") !=
897       gst_tag_get_language_name ("fr"));
898
899   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("deu"), "de");
900   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("de"), "de");
901   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("ger"), "de");
902
903   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("deu"), "de");
904   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("de"), "de");
905   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("ger"), "de");
906
907   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("de"), "deu");
908   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("deu"), "deu");
909   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("ger"), "deu");
910
911   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("de"), "ger");
912   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("deu"), "ger");
913   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("ger"), "ger");
914
915   fail_unless (gst_tag_check_language_code ("de"));
916   fail_unless (gst_tag_check_language_code ("deu"));
917   fail_unless (gst_tag_check_language_code ("ger"));
918   fail_if (gst_tag_check_language_code ("xxx"));
919   fail_if (gst_tag_check_language_code ("und"));
920   fail_if (gst_tag_check_language_code ("un"));
921   fail_if (gst_tag_check_language_code (""));
922   fail_if (gst_tag_check_language_code ("\377"));
923   fail_if (gst_tag_check_language_code ("deutsch"));
924 }
925
926 GST_END_TEST;
927
928 #define SPECIFIC_L "http://creativecommons.org/licenses/by-nc-sa/2.5/scotland/"
929 #define GENERIC_L "http://creativecommons.org/licenses/by/1.0/"
930 #define DERIVED_L "http://creativecommons.org/licenses/sampling+/1.0/tw/"
931
932 GST_START_TEST (test_license_utils)
933 {
934   GHashTable *ht;
935   GError *err = NULL;
936   gchar **liblicense_refs, **r;
937   gchar **lrefs, **l;
938   gchar *path, *data = NULL;
939   gsize data_len;
940
941   gst_debug_set_threshold_for_name ("tag-licenses", GST_LEVEL_NONE);
942
943   /* test jurisdiction-specific license */
944   fail_unless_equals_int (gst_tag_get_license_flags (SPECIFIC_L), 0x01010703);
945   fail_unless_equals_string (gst_tag_get_license_nick (SPECIFIC_L),
946       "CC BY-NC-SA 2.5 SCOTLAND");
947   fail_unless_equals_string (gst_tag_get_license_version (SPECIFIC_L), "2.5");
948   fail_unless_equals_string (gst_tag_get_license_jurisdiction (SPECIFIC_L),
949       "scotland");
950
951   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "C", TRUE);
952   fail_unless_equals_string (gst_tag_get_license_title (SPECIFIC_L),
953       "Attribution-NonCommercial-ShareAlike");
954   fail_unless (gst_tag_get_license_description (SPECIFIC_L) == NULL);
955
956   /* test generic license */
957   fail_unless_equals_int (gst_tag_get_license_flags (GENERIC_L), 0x01000307);
958   fail_unless_equals_string (gst_tag_get_license_nick (GENERIC_L), "CC BY 1.0");
959   fail_unless_equals_string (gst_tag_get_license_version (GENERIC_L), "1.0");
960   fail_unless (gst_tag_get_license_jurisdiction (GENERIC_L) == NULL);
961
962   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "C", TRUE);
963   fail_unless_equals_string (gst_tag_get_license_title (GENERIC_L),
964       "Attribution");
965   fail_unless_equals_string (gst_tag_get_license_description (GENERIC_L),
966       "You must attribute the work in the manner specified by the author or licensor.");
967
968 #ifdef ENABLE_NLS
969   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "fr", TRUE);
970   fail_unless_equals_string (gst_tag_get_license_title (GENERIC_L),
971       "Paternité");
972   fail_unless_equals_string (gst_tag_get_license_description (GENERIC_L),
973       "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.");
974 #endif
975
976   /* test derived (for a certain jurisdiction) license */
977   fail_unless_equals_int (gst_tag_get_license_flags (DERIVED_L), 0x0100030d);
978   fail_unless_equals_string (gst_tag_get_license_nick (DERIVED_L),
979       "CC SAMPLING+ 1.0 TW");
980   fail_unless_equals_string (gst_tag_get_license_version (DERIVED_L), "1.0");
981   fail_unless_equals_string (gst_tag_get_license_jurisdiction (DERIVED_L),
982       "tw");
983
984   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "C", TRUE);
985   fail_unless_equals_string (gst_tag_get_license_title (DERIVED_L),
986       "Sampling Plus");
987   fail_unless_equals_string (gst_tag_get_license_description (GENERIC_L),
988       "You must attribute the work in the manner specified by the author or licensor.");
989
990   /* test all we know about */
991   lrefs = gst_tag_get_licenses ();
992   fail_unless (lrefs != NULL);
993   fail_unless (*lrefs != NULL);
994
995   GST_INFO ("%d licenses", g_strv_length (lrefs));
996   fail_unless (g_strv_length (lrefs) >= 376);
997
998   ht = g_hash_table_new (g_str_hash, g_str_equal);
999
1000   for (l = lrefs; l != NULL && *l != NULL; ++l) {
1001     const gchar *ref, *nick, *title, *desc G_GNUC_UNUSED;
1002
1003     ref = (const gchar *) *l;
1004     nick = gst_tag_get_license_nick (ref);
1005     title = gst_tag_get_license_title (ref);
1006     desc = gst_tag_get_license_description (ref);
1007     fail_unless (nick != NULL, "no nick for license '%s'", ref);
1008     fail_unless (title != NULL, "no title for license '%s'", ref);
1009     GST_LOG ("ref: %s [nick %s]", ref, (nick) ? nick : "none");
1010     GST_TRACE ("    %s : %s", title, (desc) ? desc : "(no description)");
1011
1012     /* make sure the list contains no duplicates */
1013     fail_if (g_hash_table_lookup (ht, (gpointer) ref) != NULL);
1014     g_hash_table_insert (ht, (gpointer) ref, (gpointer) "meep");
1015   }
1016   g_hash_table_destroy (ht);
1017
1018   /* trailing slash shouldn't make a difference */
1019   fail_unless_equals_int (gst_tag_get_license_flags
1020       ("http://creativecommons.org/licenses/by-nd/1.0/"),
1021       gst_tag_get_license_flags
1022       ("http://creativecommons.org/licenses/by-nd/1.0"));
1023   fail_unless_equals_string (gst_tag_get_license_nick
1024       ("http://creativecommons.org/licenses/by-nd/1.0/"),
1025       gst_tag_get_license_nick
1026       ("http://creativecommons.org/licenses/by-nd/1.0"));
1027   fail_unless_equals_int (gst_tag_get_license_flags
1028       ("http://creativecommons.org/licenses/by-nd/2.5/ca/"),
1029       gst_tag_get_license_flags
1030       ("http://creativecommons.org/licenses/by-nd/2.5/ca"));
1031   fail_unless_equals_string (gst_tag_get_license_nick
1032       ("http://creativecommons.org/licenses/by-nd/2.5/ca/"),
1033       gst_tag_get_license_nick
1034       ("http://creativecommons.org/licenses/by-nd/2.5/ca"));
1035
1036   /* unknown licenses */
1037   fail_unless (gst_tag_get_license_nick
1038       ("http://creativecommons.org/licenses/by-nd/25/ca/") == NULL);
1039   fail_unless (gst_tag_get_license_flags
1040       ("http://creativecommons.org/licenses/by-nd/25/ca") == 0);
1041   fail_unless (gst_tag_get_license_jurisdiction
1042       ("http://creativecommons.org/licenses/by-nd/25/ca/") == NULL);
1043   fail_unless (gst_tag_get_license_jurisdiction
1044       ("http://creativecommons.org/licenses/by-nd/25/ca") == NULL);
1045   fail_unless (gst_tag_get_license_title
1046       ("http://creativecommons.org/licenses/by-nd/25/ca") == NULL);
1047   fail_unless (gst_tag_get_license_jurisdiction
1048       ("http://creativecommons.org/licenses/by-nd/25/ca") == NULL);
1049
1050   /* unknown prefixes even */
1051   fail_unless (gst_tag_get_license_nick
1052       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
1053   fail_unless (gst_tag_get_license_flags
1054       ("http://copycats.org/licenses/by-nd/2.5/ca") == 0);
1055   fail_unless (gst_tag_get_license_jurisdiction
1056       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
1057   fail_unless (gst_tag_get_license_title
1058       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
1059   fail_unless (gst_tag_get_license_description
1060       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
1061
1062   /* read list of liblicense refs from file */
1063   path = g_build_filename (GST_TEST_FILES_PATH, "license-uris", NULL);
1064   GST_LOG ("reading file '%s'", path);
1065   if (!g_file_get_contents (path, &data, &data_len, &err)) {
1066     g_error ("error loading test file: %s", err->message);
1067   }
1068
1069   while (data_len > 0 && data[data_len - 1] == '\n') {
1070     data[--data_len] = '\0';
1071   }
1072
1073   liblicense_refs = g_strsplit (data, "\n", -1);
1074   g_free (data);
1075   g_free (path);
1076
1077   fail_unless (g_strv_length (lrefs) >= g_strv_length (liblicense_refs));
1078
1079   for (r = liblicense_refs; r != NULL && *r != NULL; ++r) {
1080     GstTagLicenseFlags flags;
1081     const gchar *version, *nick, *jur;
1082     const gchar *ref = *r;
1083
1084     GST_LOG ("liblicense ref: %s", ref);
1085
1086     version = gst_tag_get_license_version (ref);
1087     if (strstr (ref, "publicdomain") != NULL)
1088       fail_unless (version == NULL);
1089     else
1090       fail_unless (version != NULL, "expected version for license %s", ref);
1091
1092     flags = gst_tag_get_license_flags (ref);
1093     fail_unless (flags != 0, "expected non-zero flags for license %s", ref);
1094
1095     nick = gst_tag_get_license_nick (ref);
1096     fail_unless (nick != NULL, "expected nick for license %s", ref);
1097
1098     jur = gst_tag_get_license_jurisdiction (ref);
1099     if (g_str_has_suffix (ref, "de/")) {
1100       fail_unless_equals_string (jur, "de");
1101     } else if (g_str_has_suffix (ref, "scotland")) {
1102       fail_unless_equals_string (jur, "scotland");
1103     } else if (g_str_has_suffix (ref, ".0") || g_str_has_suffix (ref, ".1")) {
1104       fail_unless (jur == NULL);
1105     }
1106   }
1107
1108   g_strfreev (liblicense_refs);
1109   g_strfreev (lrefs);
1110 }
1111
1112 GST_END_TEST;
1113
1114 GST_START_TEST (test_xmp_formatting)
1115 {
1116   GstTagList *list;
1117   GstBuffer *buf;
1118   GstMapInfo map;
1119   const gchar *text;
1120   gsize len;
1121
1122   /* test data */
1123   list = gst_tag_list_new (GST_TAG_TITLE, "test title",
1124       GST_TAG_DESCRIPTION, "test decription",
1125       GST_TAG_KEYWORDS, "keyword1", GST_TAG_KEYWORDS, "keyword2", NULL);
1126
1127   buf = gst_tag_list_to_xmp_buffer (list, FALSE, NULL);
1128   fail_unless (buf != NULL);
1129
1130   gst_buffer_map (buf, &map, GST_MAP_READ);
1131   text = (gchar *) map.data;
1132   len = map.size;
1133
1134   /* check the content */
1135   fail_unless (g_strrstr_len (text, len, "<?xpacket begin") == text);
1136   fail_unless (g_strrstr_len (text, len, ">test title<") != NULL);
1137   fail_unless (g_strrstr_len (text, len, ">test decription<") != NULL);
1138   fail_unless (g_strrstr_len (text, len, ">keyword1<") != NULL);
1139   fail_unless (g_strrstr_len (text, len, ">keyword2<") != NULL);
1140   fail_unless (g_strrstr_len (text, len, "<?xpacket end") != NULL);
1141   gst_buffer_unmap (buf, &map);
1142
1143   gst_buffer_unref (buf);
1144   gst_tag_list_unref (list);
1145 }
1146
1147 GST_END_TEST;
1148
1149
1150 GST_START_TEST (test_xmp_parsing)
1151 {
1152   GstTagList *list;
1153   GstBuffer *buf;
1154   guint i, j, result_size;
1155   gchar *text;
1156   const gchar *xmp_header =
1157       "<?xpacket begin=\"\xEF\xBB\xBF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>"
1158       "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"GStreamer\">"
1159       "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">";
1160
1161   /* We used to write an extra trailing \n after the footer, keep compatibility
1162    * with our old generated media by checking that it still can be parsed */
1163   const gchar *xmp_footers[] = {
1164     "</rdf:RDF>" "</x:xmpmeta>" "<?xpacket end=\"r\"?>",
1165     "</rdf:RDF>" "</x:xmpmeta>" "<?xpacket end=\"r\"?>\n",
1166     NULL
1167   };
1168
1169   struct
1170   {
1171     const gchar *xmp_data;
1172     gint result_size;
1173     gint result_test;
1174   } test_data[] = {
1175     {
1176     "", -1, -1}, {
1177     "<rdf:Description rdf:about=\"\" />", 0, -1}, {
1178     "<rdf:Description rdf:about=\"\"></rdf:Description>", 0, -1}, {
1179     "<rdf:Description    rdf:about=\"\"    ></rdf:Description>", 0, -1}, {
1180     "<rdf:Description rdf:about=\"\"><dc:description>test</dc:description></rdf:Description>",
1181           1, 0}, {
1182     "<rdf:Description rdf:about=\"\" dc:description=\"test\"></rdf:Description>",
1183           1, 0}, {
1184     NULL, -1, -1}
1185   };
1186
1187   /* test data */
1188   j = 0;
1189   i = 0;
1190   while (xmp_footers[j]) {
1191     while (test_data[i].xmp_data) {
1192       gsize len;
1193
1194       GST_DEBUG ("trying test-data %u", i);
1195
1196       text =
1197           g_strconcat (xmp_header, test_data[i].xmp_data, xmp_footers[j], NULL);
1198
1199       buf = gst_buffer_new ();
1200       len = strlen (text) + 1;
1201       gst_buffer_append_memory (buf,
1202           gst_memory_new_wrapped (0, text, len, 0, len, NULL, NULL));
1203
1204       list = gst_tag_list_from_xmp_buffer (buf);
1205       if (test_data[i].result_size >= 0) {
1206         fail_unless (list != NULL);
1207
1208         result_size = gst_tag_list_n_tags (list);
1209         fail_unless (result_size == test_data[i].result_size);
1210
1211         /* check the taglist content */
1212         switch (test_data[i].result_test) {
1213           case 0:
1214             ASSERT_TAG_LIST_HAS_STRING (list, "description", "test");
1215             break;
1216           default:
1217             break;
1218         }
1219       }
1220       if (list)
1221         gst_tag_list_unref (list);
1222
1223       gst_buffer_unref (buf);
1224       g_free (text);
1225       i++;
1226     }
1227     j++;
1228   }
1229 }
1230
1231 GST_END_TEST;
1232
1233 static void
1234 do_xmp_tag_serialization_deserialization (GstTagList * taglist,
1235     const gchar ** schemas)
1236 {
1237   GstTagList *taglist2;
1238   GstBuffer *buf;
1239
1240   buf = gst_tag_list_to_xmp_buffer (taglist, TRUE, schemas);
1241   taglist2 = gst_tag_list_from_xmp_buffer (buf);
1242
1243   fail_unless (gst_tag_list_is_equal (taglist, taglist2));
1244
1245   gst_buffer_unref (buf);
1246   gst_tag_list_unref (taglist2);
1247 }
1248
1249 static void
1250 do_simple_xmp_tag_serialization_deserialization (const gchar * gsttag,
1251     GValue * value)
1252 {
1253   GstTagList *taglist = gst_tag_list_new_empty ();
1254
1255   gst_tag_list_add_value (taglist, GST_TAG_MERGE_REPLACE, gsttag, value);
1256
1257   do_xmp_tag_serialization_deserialization (taglist, NULL);
1258   gst_tag_list_unref (taglist);
1259 }
1260
1261 GST_START_TEST (test_xmp_tags_serialization_deserialization)
1262 {
1263   GValue value = { 0 };
1264   GstDateTime *datetime;
1265
1266   gst_tag_register_musicbrainz_tags ();
1267
1268   g_value_init (&value, G_TYPE_STRING);
1269   g_value_set_static_string (&value, "my string");
1270   do_simple_xmp_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1271   do_simple_xmp_tag_serialization_deserialization (GST_TAG_COPYRIGHT, &value);
1272   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DESCRIPTION, &value);
1273   do_simple_xmp_tag_serialization_deserialization (GST_TAG_KEYWORDS, &value);
1274   do_simple_xmp_tag_serialization_deserialization (GST_TAG_TITLE, &value);
1275   do_simple_xmp_tag_serialization_deserialization (GST_TAG_VIDEO_CODEC, &value);
1276   do_simple_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_COUNTRY,
1277       &value);
1278   do_simple_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_CITY,
1279       &value);
1280   do_simple_xmp_tag_serialization_deserialization
1281       (GST_TAG_GEO_LOCATION_SUBLOCATION, &value);
1282   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DEVICE_MANUFACTURER,
1283       &value);
1284   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DEVICE_MODEL,
1285       &value);
1286   do_simple_xmp_tag_serialization_deserialization (GST_TAG_APPLICATION_NAME,
1287       &value);
1288
1289   g_value_set_static_string (&value, "rotate-0");
1290   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1291       &value);
1292   g_value_set_static_string (&value, "flip-rotate-0");
1293   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1294       &value);
1295   g_value_set_static_string (&value, "rotate-180");
1296   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1297       &value);
1298   g_value_set_static_string (&value, "flip-rotate-180");
1299   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1300       &value);
1301   g_value_set_static_string (&value, "flip-rotate-270");
1302   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1303       &value);
1304   g_value_set_static_string (&value, "rotate-90");
1305   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1306       &value);
1307   g_value_set_static_string (&value, "flip-rotate-90");
1308   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1309       &value);
1310   g_value_set_static_string (&value, "rotate-270");
1311   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1312       &value);
1313
1314   g_value_unset (&value);
1315   g_value_init (&value, G_TYPE_DOUBLE);
1316
1317   g_value_set_double (&value, 0.0);
1318   do_simple_xmp_tag_serialization_deserialization
1319       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1320   do_simple_xmp_tag_serialization_deserialization
1321       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1322   g_value_set_double (&value, 10.5);
1323   do_simple_xmp_tag_serialization_deserialization
1324       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1325   do_simple_xmp_tag_serialization_deserialization
1326       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1327   g_value_set_double (&value, -32.375);
1328   do_simple_xmp_tag_serialization_deserialization
1329       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1330   do_simple_xmp_tag_serialization_deserialization
1331       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1332
1333   g_value_set_double (&value, 0);
1334   do_simple_xmp_tag_serialization_deserialization
1335       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1336   g_value_set_double (&value, 100);
1337   do_simple_xmp_tag_serialization_deserialization
1338       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1339   g_value_set_double (&value, 500.25);
1340   do_simple_xmp_tag_serialization_deserialization
1341       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1342   g_value_set_double (&value, -12.75);
1343   do_simple_xmp_tag_serialization_deserialization
1344       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1345
1346   g_value_set_double (&value, 0.0);
1347   do_simple_xmp_tag_serialization_deserialization
1348       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1349   g_value_set_double (&value, 10.0);
1350   do_simple_xmp_tag_serialization_deserialization
1351       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1352   g_value_set_double (&value, 786.125);
1353   do_simple_xmp_tag_serialization_deserialization
1354       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1355   g_value_set_double (&value, -2.5);
1356   do_simple_xmp_tag_serialization_deserialization
1357       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1358
1359   g_value_set_double (&value, 0.0);
1360   do_simple_xmp_tag_serialization_deserialization
1361       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1362   g_value_set_double (&value, 180.0);
1363   do_simple_xmp_tag_serialization_deserialization
1364       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1365   g_value_set_double (&value, 359.99);
1366   do_simple_xmp_tag_serialization_deserialization
1367       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1368
1369   g_value_set_double (&value, 0.0);
1370   do_simple_xmp_tag_serialization_deserialization
1371       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1372   g_value_set_double (&value, 90.0);
1373   do_simple_xmp_tag_serialization_deserialization
1374       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1375   g_value_set_double (&value, 359.99);
1376   do_simple_xmp_tag_serialization_deserialization
1377       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1378
1379   g_value_set_double (&value, 0.0);
1380   do_simple_xmp_tag_serialization_deserialization
1381       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1382   g_value_set_double (&value, 1.0);
1383   do_simple_xmp_tag_serialization_deserialization
1384       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1385   g_value_set_double (&value, -2.5);
1386   do_simple_xmp_tag_serialization_deserialization
1387       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1388   g_value_unset (&value);
1389
1390   g_value_init (&value, GST_TYPE_DATE_TIME);
1391   datetime = gst_date_time_new_ymd (2010, 3, 22);
1392   g_value_take_boxed (&value, datetime);
1393   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1394   g_value_unset (&value);
1395
1396   g_value_init (&value, G_TYPE_UINT);
1397   g_value_set_uint (&value, 0);
1398   do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value);
1399   g_value_set_uint (&value, 100);
1400   do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value);
1401   g_value_set_uint (&value, 22);
1402   do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value);
1403   g_value_unset (&value);
1404
1405   g_value_init (&value, GST_TYPE_DATE_TIME);
1406   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10);
1407   g_value_set_boxed (&value, datetime);
1408   gst_date_time_unref (datetime);
1409   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1410   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.000125);
1411   g_value_set_boxed (&value, datetime);
1412   gst_date_time_unref (datetime);
1413   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1414   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.000001);
1415   g_value_set_boxed (&value, datetime);
1416   gst_date_time_unref (datetime);
1417   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1418   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.123456);
1419   g_value_set_boxed (&value, datetime);
1420   gst_date_time_unref (datetime);
1421   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1422   datetime = gst_date_time_new (-3, 2010, 6, 22, 12, 5, 10.123456);
1423   g_value_set_boxed (&value, datetime);
1424   gst_date_time_unref (datetime);
1425   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1426   datetime = gst_date_time_new (5, 2010, 6, 22, 12, 5, 10.123456);
1427   g_value_set_boxed (&value, datetime);
1428   gst_date_time_unref (datetime);
1429   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1430   datetime = gst_date_time_new_local_time (2010, 12, 2, 12, 5, 10.000043);
1431   g_value_set_boxed (&value, datetime);
1432   gst_date_time_unref (datetime);
1433   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1434   g_value_unset (&value);
1435 }
1436
1437 GST_END_TEST;
1438
1439
1440 GST_START_TEST (test_xmp_compound_tags)
1441 {
1442   const gchar *schemas[] = { "Iptc4xmpExt", NULL };
1443   GstTagList *taglist = gst_tag_list_new_empty ();
1444
1445   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_KEYWORDS, "k1",
1446       GST_TAG_KEYWORDS, "k2", GST_TAG_TITLE, "title", GST_TAG_KEYWORDS, "k3",
1447       NULL);
1448   do_xmp_tag_serialization_deserialization (taglist, NULL);
1449   gst_tag_list_unref (taglist);
1450
1451   taglist = gst_tag_list_new_empty ();
1452   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_GEO_LOCATION_COUNTRY,
1453       "Brazil", GST_TAG_GEO_LOCATION_CITY, "Campina Grande", NULL);
1454   do_xmp_tag_serialization_deserialization (taglist, schemas);
1455   gst_tag_list_unref (taglist);
1456 }
1457
1458 GST_END_TEST;
1459
1460
1461 GST_START_TEST (test_exif_parsing)
1462 {
1463   GstTagList *taglist;
1464   GstBuffer *buf;
1465   GstByteWriter writer;
1466   gboolean res = TRUE;
1467   const gchar *str = NULL;
1468
1469   gst_byte_writer_init (&writer);
1470
1471   /* write the IFD */
1472   /* 1 entry */
1473   res &= gst_byte_writer_put_uint16_le (&writer, 1);
1474
1475   /* copyright tag */
1476   /* tag id */
1477   res &= gst_byte_writer_put_uint16_le (&writer, 0x8298);
1478   /* tag type */
1479   res &= gst_byte_writer_put_uint16_le (&writer, 0x2);
1480   /* count */
1481   res &= gst_byte_writer_put_uint32_le (&writer, strlen ("my copyright") + 1);
1482   /* offset */
1483   res &= gst_byte_writer_put_uint32_le (&writer, 8 + 14);
1484
1485   /* data */
1486   res &= gst_byte_writer_put_string (&writer, "my copyright");
1487
1488   fail_unless (res, "Failed to write tag");
1489
1490   buf = gst_byte_writer_reset_and_get_buffer (&writer);
1491
1492   taglist = gst_tag_list_from_exif_buffer (buf, G_LITTLE_ENDIAN, 8);
1493
1494   fail_unless (gst_tag_list_get_tag_size (taglist, GST_TAG_COPYRIGHT) == 1);
1495   gst_tag_list_peek_string_index (taglist, GST_TAG_COPYRIGHT, 0, &str);
1496   fail_unless_equals_string (str, "my copyright");
1497
1498   gst_tag_list_unref (taglist);
1499   gst_buffer_unref (buf);
1500 }
1501
1502 GST_END_TEST;
1503
1504
1505 static void
1506 do_exif_tag_serialization_deserialization (GstTagList * taglist)
1507 {
1508   GstTagList *taglist2;
1509   GstBuffer *buf;
1510
1511   /* LE */
1512   buf = gst_tag_list_to_exif_buffer (taglist, G_LITTLE_ENDIAN, 0);
1513   taglist2 = gst_tag_list_from_exif_buffer (buf, G_LITTLE_ENDIAN, 0);
1514   gst_buffer_unref (buf);
1515
1516   fail_unless (gst_tag_list_is_equal (taglist, taglist2));
1517   gst_tag_list_unref (taglist2);
1518
1519   /* BE */
1520   buf = gst_tag_list_to_exif_buffer (taglist, G_BIG_ENDIAN, 0);
1521   taglist2 = gst_tag_list_from_exif_buffer (buf, G_BIG_ENDIAN, 0);
1522   gst_buffer_unref (buf);
1523
1524   fail_unless (gst_tag_list_is_equal (taglist, taglist2));
1525   gst_tag_list_unref (taglist2);
1526
1527   /* APP1 */
1528   buf = gst_tag_list_to_exif_buffer_with_tiff_header (taglist);
1529   taglist2 = gst_tag_list_from_exif_buffer_with_tiff_header (buf);
1530   gst_buffer_unref (buf);
1531
1532   fail_unless (gst_tag_list_is_equal (taglist, taglist2));
1533   gst_tag_list_unref (taglist2);
1534 }
1535
1536 static void
1537 do_simple_exif_tag_serialization_deserialization (const gchar * gsttag,
1538     GValue * value)
1539 {
1540   GstTagList *taglist = gst_tag_list_new_empty ();
1541
1542   gst_tag_list_add_value (taglist, GST_TAG_MERGE_REPLACE, gsttag, value);
1543   do_exif_tag_serialization_deserialization (taglist);
1544
1545   gst_tag_list_unref (taglist);
1546 }
1547
1548 /*
1549  * Adds tags from multiple ifd tables and tries serializing them
1550  */
1551 GST_START_TEST (test_exif_multiple_tags)
1552 {
1553   GstTagList *taglist;
1554   GstDateTime *datetime;
1555   GValue value = { 0 };
1556
1557   gst_tag_register_musicbrainz_tags ();
1558
1559   taglist = gst_tag_list_new (GST_TAG_ARTIST, "artist",
1560       GST_TAG_DEVICE_MANUFACTURER, "make",
1561       GST_TAG_DEVICE_MODEL, "model", GST_TAG_GEO_LOCATION_LATITUDE, 45.5,
1562       GST_TAG_GEO_LOCATION_LONGITUDE, -10.25,
1563       GST_TAG_IMAGE_HORIZONTAL_PPI, 300.0,
1564       GST_TAG_IMAGE_VERTICAL_PPI, 300.0, NULL);
1565
1566   g_value_init (&value, GST_TYPE_DATE_TIME);
1567   datetime = gst_date_time_new_local_time (2010, 6, 22, 12, 5, 10);
1568   g_value_set_boxed (&value, datetime);
1569   gst_date_time_unref (datetime);
1570   gst_tag_list_add_value (taglist, GST_TAG_MERGE_APPEND, GST_TAG_DATE_TIME,
1571       &value);
1572   g_value_unset (&value);
1573
1574   do_exif_tag_serialization_deserialization (taglist);
1575
1576   gst_tag_list_unref (taglist);
1577 }
1578
1579 GST_END_TEST;
1580
1581
1582 GST_START_TEST (test_exif_tags_serialization_deserialization)
1583 {
1584   GValue value = { 0 };
1585   GstDateTime *datetime = NULL;
1586   GstBuffer *buf = NULL;
1587   gint i;
1588   GstTagList *taglist;
1589   GstMapInfo map;
1590   guint8 *data;
1591
1592   gst_tag_register_musicbrainz_tags ();
1593
1594   g_value_init (&value, G_TYPE_STRING);
1595   g_value_set_static_string (&value, "my string");
1596   do_simple_exif_tag_serialization_deserialization (GST_TAG_COPYRIGHT, &value);
1597   g_value_set_static_string (&value, "ty");
1598   do_simple_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1599   g_value_set_static_string (&value, "Company Software 1.2b (info)");
1600   do_simple_exif_tag_serialization_deserialization (GST_TAG_APPLICATION_NAME,
1601       &value);
1602
1603   /* non ascii chars */
1604   g_value_set_static_string (&value, "AaÄäEeËëIiÏïOoÖöUuÜü");
1605   do_simple_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1606   g_value_set_static_string (&value, "Äë");
1607   do_simple_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1608
1609   /* image orientation tests */
1610   g_value_set_static_string (&value, "rotate-0");
1611   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1612       &value);
1613   g_value_set_static_string (&value, "flip-rotate-0");
1614   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1615       &value);
1616   g_value_set_static_string (&value, "rotate-180");
1617   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1618       &value);
1619   g_value_set_static_string (&value, "flip-rotate-180");
1620   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1621       &value);
1622   g_value_set_static_string (&value, "flip-rotate-270");
1623   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1624       &value);
1625   g_value_set_static_string (&value, "rotate-90");
1626   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1627       &value);
1628   g_value_set_static_string (&value, "flip-rotate-90");
1629   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1630       &value);
1631   g_value_set_static_string (&value, "rotate-270");
1632   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1633       &value);
1634
1635   /* exposure program */
1636   g_value_set_static_string (&value, "undefined");
1637   do_simple_exif_tag_serialization_deserialization
1638       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1639   g_value_set_static_string (&value, "manual");
1640   do_simple_exif_tag_serialization_deserialization
1641       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1642   g_value_set_static_string (&value, "normal");
1643   do_simple_exif_tag_serialization_deserialization
1644       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1645   g_value_set_static_string (&value, "aperture-priority");
1646   do_simple_exif_tag_serialization_deserialization
1647       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1648   g_value_set_static_string (&value, "shutter-priority");
1649   do_simple_exif_tag_serialization_deserialization
1650       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1651   g_value_set_static_string (&value, "creative");
1652   do_simple_exif_tag_serialization_deserialization
1653       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1654   g_value_set_static_string (&value, "action");
1655   do_simple_exif_tag_serialization_deserialization
1656       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1657   g_value_set_static_string (&value, "portrait");
1658   do_simple_exif_tag_serialization_deserialization
1659       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1660   g_value_set_static_string (&value, "landscape");
1661   do_simple_exif_tag_serialization_deserialization
1662       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1663
1664   /* exposure mode */
1665   g_value_set_static_string (&value, "auto-exposure");
1666   do_simple_exif_tag_serialization_deserialization
1667       (GST_TAG_CAPTURING_EXPOSURE_MODE, &value);
1668   g_value_set_static_string (&value, "manual-exposure");
1669   do_simple_exif_tag_serialization_deserialization
1670       (GST_TAG_CAPTURING_EXPOSURE_MODE, &value);
1671   g_value_set_static_string (&value, "auto-bracket");
1672   do_simple_exif_tag_serialization_deserialization
1673       (GST_TAG_CAPTURING_EXPOSURE_MODE, &value);
1674
1675   /* scene capture type */
1676   g_value_set_static_string (&value, "standard");
1677   do_simple_exif_tag_serialization_deserialization
1678       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1679   g_value_set_static_string (&value, "portrait");
1680   do_simple_exif_tag_serialization_deserialization
1681       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1682   g_value_set_static_string (&value, "landscape");
1683   do_simple_exif_tag_serialization_deserialization
1684       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1685   g_value_set_static_string (&value, "night-scene");
1686   do_simple_exif_tag_serialization_deserialization
1687       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1688
1689   g_value_set_static_string (&value, "none");
1690   do_simple_exif_tag_serialization_deserialization
1691       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1692   g_value_set_static_string (&value, "high-gain-up");
1693   do_simple_exif_tag_serialization_deserialization
1694       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1695   g_value_set_static_string (&value, "low-gain-up");
1696   do_simple_exif_tag_serialization_deserialization
1697       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1698   g_value_set_static_string (&value, "high-gain-down");
1699   do_simple_exif_tag_serialization_deserialization
1700       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1701   g_value_set_static_string (&value, "low-gain-down");
1702   do_simple_exif_tag_serialization_deserialization
1703       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1704
1705   g_value_set_static_string (&value, "auto");
1706   do_simple_exif_tag_serialization_deserialization
1707       (GST_TAG_CAPTURING_WHITE_BALANCE, &value);
1708   g_value_set_static_string (&value, "manual");
1709   do_simple_exif_tag_serialization_deserialization
1710       (GST_TAG_CAPTURING_WHITE_BALANCE, &value);
1711
1712   g_value_set_static_string (&value, "normal");
1713   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST,
1714       &value);
1715   g_value_set_static_string (&value, "hard");
1716   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST,
1717       &value);
1718   g_value_set_static_string (&value, "soft");
1719   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST,
1720       &value);
1721
1722   g_value_set_static_string (&value, "normal");
1723   do_simple_exif_tag_serialization_deserialization
1724       (GST_TAG_CAPTURING_SATURATION, &value);
1725   g_value_set_static_string (&value, "low-saturation");
1726   do_simple_exif_tag_serialization_deserialization
1727       (GST_TAG_CAPTURING_SATURATION, &value);
1728   g_value_set_static_string (&value, "high-saturation");
1729   do_simple_exif_tag_serialization_deserialization
1730       (GST_TAG_CAPTURING_SATURATION, &value);
1731
1732   g_value_set_static_string (&value, "normal");
1733   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS,
1734       &value);
1735   g_value_set_static_string (&value, "hard");
1736   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS,
1737       &value);
1738   g_value_set_static_string (&value, "soft");
1739   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS,
1740       &value);
1741
1742   g_value_set_static_string (&value, "unknown");
1743   do_simple_exif_tag_serialization_deserialization
1744       (GST_TAG_CAPTURING_METERING_MODE, &value);
1745   g_value_set_static_string (&value, "average");
1746   do_simple_exif_tag_serialization_deserialization
1747       (GST_TAG_CAPTURING_METERING_MODE, &value);
1748   g_value_set_static_string (&value, "center-weighted-average");
1749   do_simple_exif_tag_serialization_deserialization
1750       (GST_TAG_CAPTURING_METERING_MODE, &value);
1751   g_value_set_static_string (&value, "spot");
1752   do_simple_exif_tag_serialization_deserialization
1753       (GST_TAG_CAPTURING_METERING_MODE, &value);
1754   g_value_set_static_string (&value, "multi-spot");
1755   do_simple_exif_tag_serialization_deserialization
1756       (GST_TAG_CAPTURING_METERING_MODE, &value);
1757   g_value_set_static_string (&value, "pattern");
1758   do_simple_exif_tag_serialization_deserialization
1759       (GST_TAG_CAPTURING_METERING_MODE, &value);
1760   g_value_set_static_string (&value, "partial");
1761   do_simple_exif_tag_serialization_deserialization
1762       (GST_TAG_CAPTURING_METERING_MODE, &value);
1763   g_value_set_static_string (&value, "other");
1764   do_simple_exif_tag_serialization_deserialization
1765       (GST_TAG_CAPTURING_METERING_MODE, &value);
1766
1767   g_value_set_static_string (&value, "dsc");
1768   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1769       &value);
1770   g_value_set_static_string (&value, "other");
1771   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1772       &value);
1773   g_value_set_static_string (&value, "transparent-scanner");
1774   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1775       &value);
1776   g_value_set_static_string (&value, "reflex-scanner");
1777   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1778       &value);
1779   g_value_unset (&value);
1780
1781   g_value_init (&value, G_TYPE_DOUBLE);
1782   g_value_set_double (&value, 40.3456784);
1783   do_simple_exif_tag_serialization_deserialization
1784       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1785   g_value_set_double (&value, -12.1250865);
1786
1787   do_simple_exif_tag_serialization_deserialization
1788       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1789   g_value_set_double (&value, 0);
1790   do_simple_exif_tag_serialization_deserialization
1791       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1792   g_value_set_double (&value, 65.0);
1793   do_simple_exif_tag_serialization_deserialization
1794       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1795   g_value_set_double (&value, -0.75);
1796   do_simple_exif_tag_serialization_deserialization
1797       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1798
1799   g_value_set_double (&value, 0.0);
1800   do_simple_exif_tag_serialization_deserialization
1801       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1802   g_value_set_double (&value, 180.5);
1803   do_simple_exif_tag_serialization_deserialization
1804       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1805   g_value_set_double (&value, 0.12345);
1806   do_simple_exif_tag_serialization_deserialization
1807       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1808   g_value_set_double (&value, 359.9);
1809   do_simple_exif_tag_serialization_deserialization
1810       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1811
1812   g_value_set_double (&value, 0.0);
1813   do_simple_exif_tag_serialization_deserialization
1814       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1815   g_value_set_double (&value, 321.456);
1816   do_simple_exif_tag_serialization_deserialization
1817       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1818   g_value_set_double (&value, -12.56);
1819   do_simple_exif_tag_serialization_deserialization
1820       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1821
1822   g_value_set_double (&value, 0);
1823   do_simple_exif_tag_serialization_deserialization
1824       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1825   g_value_set_double (&value, 100 / 3.6);
1826   do_simple_exif_tag_serialization_deserialization
1827       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1828
1829   g_value_set_double (&value, 0);
1830   do_simple_exif_tag_serialization_deserialization
1831       (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, &value);
1832   g_value_set_double (&value, 50.25);
1833   do_simple_exif_tag_serialization_deserialization
1834       (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, &value);
1835
1836   g_value_set_double (&value, 0);
1837   do_simple_exif_tag_serialization_deserialization
1838       (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value);
1839   g_value_set_double (&value, 2.5);
1840   do_simple_exif_tag_serialization_deserialization
1841       (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value);
1842   g_value_set_double (&value, 8.75);
1843   do_simple_exif_tag_serialization_deserialization
1844       (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value);
1845
1846   g_value_set_double (&value, 20.0);
1847   do_simple_exif_tag_serialization_deserialization
1848       (GST_TAG_CAPTURING_FOCAL_LENGTH, &value);
1849   g_value_set_double (&value, 5.5);
1850   do_simple_exif_tag_serialization_deserialization
1851       (GST_TAG_CAPTURING_FOCAL_LENGTH, &value);
1852
1853   g_value_set_double (&value, 16);
1854   do_simple_exif_tag_serialization_deserialization
1855       (GST_TAG_CAPTURING_FOCAL_RATIO, &value);
1856   g_value_set_double (&value, 2.7);
1857   do_simple_exif_tag_serialization_deserialization
1858       (GST_TAG_CAPTURING_FOCAL_LENGTH, &value);
1859
1860   g_value_set_double (&value, 96.0);
1861   do_simple_exif_tag_serialization_deserialization
1862       (GST_TAG_IMAGE_HORIZONTAL_PPI, &value);
1863   g_value_set_double (&value, 300.0);
1864   do_simple_exif_tag_serialization_deserialization
1865       (GST_TAG_IMAGE_HORIZONTAL_PPI, &value);
1866   g_value_set_double (&value, 87.5);
1867   do_simple_exif_tag_serialization_deserialization
1868       (GST_TAG_IMAGE_VERTICAL_PPI, &value);
1869   g_value_set_double (&value, 600.0);
1870   do_simple_exif_tag_serialization_deserialization
1871       (GST_TAG_IMAGE_VERTICAL_PPI, &value);
1872
1873   g_value_set_double (&value, 0.0);
1874   do_simple_exif_tag_serialization_deserialization
1875       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1876   g_value_set_double (&value, 1.0);
1877   do_simple_exif_tag_serialization_deserialization
1878       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1879   g_value_set_double (&value, -2.5);
1880   do_simple_exif_tag_serialization_deserialization
1881       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1882
1883   g_value_set_double (&value, 50.0);
1884   do_simple_exif_tag_serialization_deserialization
1885       (GST_TAG_CAPTURING_FOCAL_LENGTH_35_MM, &value);
1886   g_value_unset (&value);
1887
1888   g_value_init (&value, G_TYPE_INT);
1889   g_value_set_int (&value, 400);
1890   do_simple_exif_tag_serialization_deserialization
1891       (GST_TAG_CAPTURING_ISO_SPEED, &value);
1892   g_value_set_int (&value, 1600);
1893   do_simple_exif_tag_serialization_deserialization
1894       (GST_TAG_CAPTURING_ISO_SPEED, &value);
1895   g_value_unset (&value);
1896
1897   g_value_init (&value, GST_TYPE_DATE_TIME);
1898   datetime = gst_date_time_new_local_time (2010, 6, 22, 12, 5, 10);
1899   g_value_set_boxed (&value, datetime);
1900   gst_date_time_unref (datetime);
1901   do_simple_exif_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1902   g_value_unset (&value);
1903
1904   g_value_init (&value, GST_TYPE_SAMPLE);
1905   buf = gst_buffer_new_and_alloc (1024);
1906   gst_buffer_map (buf, &map, GST_MAP_WRITE);
1907   data = map.data;
1908   for (i = 0; i < 1024; i++)
1909     data[i] = i % 255;
1910   gst_buffer_unmap (buf, &map);
1911   gst_value_take_sample (&value, gst_sample_new (buf, NULL, NULL, NULL));
1912   gst_buffer_unref (buf);
1913   do_simple_exif_tag_serialization_deserialization (GST_TAG_APPLICATION_DATA,
1914       &value);
1915   g_value_unset (&value);
1916
1917   g_value_init (&value, GST_TYPE_FRACTION);
1918   gst_value_set_fraction (&value, 1, 1);
1919   do_simple_exif_tag_serialization_deserialization
1920       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1921   gst_value_set_fraction (&value, 1, 30);
1922   do_simple_exif_tag_serialization_deserialization
1923       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1924   gst_value_set_fraction (&value, 1, 200);
1925   do_simple_exif_tag_serialization_deserialization
1926       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1927   gst_value_set_fraction (&value, 1, 8000);
1928   do_simple_exif_tag_serialization_deserialization
1929       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1930   g_value_unset (&value);
1931
1932   /* flash is a little bit more tricky, because 2 tags are merged into 1 in
1933    * exif */
1934   taglist = gst_tag_list_new (GST_TAG_CAPTURING_FLASH_FIRED, FALSE,
1935       GST_TAG_CAPTURING_FLASH_MODE, "auto", NULL);
1936   do_exif_tag_serialization_deserialization (taglist);
1937   gst_tag_list_unref (taglist);
1938
1939   taglist = gst_tag_list_new (GST_TAG_CAPTURING_FLASH_FIRED, TRUE,
1940       GST_TAG_CAPTURING_FLASH_MODE, "auto", NULL);
1941   do_exif_tag_serialization_deserialization (taglist);
1942   gst_tag_list_unref (taglist);
1943
1944   taglist = gst_tag_list_new (GST_TAG_CAPTURING_FLASH_FIRED, FALSE,
1945       GST_TAG_CAPTURING_FLASH_MODE, "never", NULL);
1946   do_exif_tag_serialization_deserialization (taglist);
1947   gst_tag_list_unref (taglist);
1948
1949   taglist = gst_tag_list_new (GST_TAG_CAPTURING_FLASH_FIRED, TRUE,
1950       GST_TAG_CAPTURING_FLASH_MODE, "always", NULL);
1951   do_exif_tag_serialization_deserialization (taglist);
1952   gst_tag_list_unref (taglist);
1953 }
1954
1955 GST_END_TEST;
1956
1957 static Suite *
1958 tag_suite (void)
1959 {
1960   Suite *s = suite_create ("tag support library");
1961   TCase *tc_chain = tcase_create ("general");
1962
1963   suite_add_tcase (s, tc_chain);
1964   tcase_add_test (tc_chain, test_musicbrainz_tag_registration);
1965   tcase_add_test (tc_chain, test_parse_extended_comment);
1966   tcase_add_test (tc_chain, test_vorbis_tags);
1967   tcase_add_test (tc_chain, test_id3_tags);
1968   tcase_add_test (tc_chain, test_id3v1_utf8_tag);
1969   tcase_add_test (tc_chain, test_id3v2_priv_tag);
1970   tcase_add_test (tc_chain, test_id3v2_extended_header);
1971   tcase_add_test (tc_chain, test_id3v2_string_list_utf16);
1972   tcase_add_test (tc_chain, test_language_utils);
1973   tcase_add_test (tc_chain, test_license_utils);
1974   tcase_add_test (tc_chain, test_xmp_formatting);
1975   tcase_add_test (tc_chain, test_xmp_parsing);
1976   tcase_add_test (tc_chain, test_xmp_tags_serialization_deserialization);
1977   tcase_add_test (tc_chain, test_xmp_compound_tags);
1978   tcase_add_test (tc_chain, test_exif_parsing);
1979   tcase_add_test (tc_chain, test_exif_tags_serialization_deserialization);
1980   tcase_add_test (tc_chain, test_exif_multiple_tags);
1981   return s;
1982 }
1983
1984 GST_CHECK_MAIN (tag);