c97395be8ca2e40327686389c1e1aa15d2dbca9d
[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 id3v2_exthdr[] = {
768     0x49, 0x44, 0x33, 0x03, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1b,
769     0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770     0x54, 0x50, 0x45, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
771     0x00, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x65
772   };
773   const guint8 id3v2_no_exthdr[] = {
774     0x49, 0x44, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
775     0x54, 0x50, 0x45, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
776     0x00, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x65
777   };
778   GstTagList *tags;
779
780   tags = parse_id3v2_tag_from_data (id3v2_exthdr, sizeof (id3v2_exthdr));
781   fail_if (tags == NULL, "Failed to parse ID3 tag with extension header");
782   GST_LOG ("tags: %" GST_PTR_FORMAT, tags);
783   fail_unless_equals_int (gst_tag_list_n_tags (tags), 1);
784   gst_tag_list_unref (tags);
785
786   tags = parse_id3v2_tag_from_data (id3v2_no_exthdr, sizeof (id3v2_no_exthdr));
787   fail_if (tags == NULL, "Failed to parse ID3 tag without extension header");
788   GST_LOG ("tags: %" GST_PTR_FORMAT, tags);
789   fail_unless_equals_int (gst_tag_list_n_tags (tags), 1);
790   gst_tag_list_unref (tags);
791 }
792
793 GST_END_TEST;
794
795 GST_START_TEST (test_id3v2_string_list_utf16)
796 {
797   const guint8 id3v2[] = {
798     0x49, 0x44, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
799     0x43, 0x4f, 0x4d, 0x4d, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00,
800     0x01, 0x65, 0x6e, 0x67, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xfe,
801     0x4e, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x20, 0x00,
802     0x4d, 0x00, 0x50, 0x00, 0x33, 0x00, 0x20, 0x00, 0x4d, 0x00,
803     0x75, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00,
804     0x4c, 0x00, 0x69, 0x00, 0x62, 0x00, 0x72, 0x00, 0x61, 0x00,
805     0x72, 0x00, 0x79, 0x00
806   };
807   GstTagList *tags;
808   gchar *comment = NULL;
809
810   tags = parse_id3v2_tag_from_data (id3v2, sizeof (id3v2));
811   fail_if (tags == NULL,
812       "Failed to parse ID3 tag with UTF-16 strings and BOMs");
813
814   GST_LOG ("tags: %" GST_PTR_FORMAT, tags);
815
816   gst_tag_list_get_string (tags, GST_TAG_COMMENT, &comment);
817   fail_unless (comment != NULL, "Expected comment tag");
818   GST_MEMDUMP ("comment string UTF-8", (guint8 *) comment, strlen (comment));
819   fail_unless_equals_string (comment, "Naim MP3 Music Library");
820   g_free (comment);
821   gst_tag_list_unref (tags);
822 }
823
824 GST_END_TEST;
825
826 GST_START_TEST (test_language_utils)
827 {
828   gchar **lang_codes, **c;
829
830 #define ASSERT_STRINGS_EQUAL fail_unless_equals_string
831
832   lang_codes = gst_tag_get_language_codes ();
833   fail_unless (lang_codes != NULL);
834   fail_unless (*lang_codes != NULL);
835
836   for (c = lang_codes; c != NULL && *c != NULL; ++c) {
837     const gchar *lang_name, *c1, *c2t, *c2b;
838
839     lang_name = gst_tag_get_language_name (*c);
840     fail_unless (lang_name != NULL);
841     fail_unless (g_utf8_validate (lang_name, -1, NULL));
842
843     c1 = gst_tag_get_language_code_iso_639_1 (*c);
844     fail_unless (c1 != NULL);
845     fail_unless (g_utf8_validate (c1, -1, NULL));
846
847     c2t = gst_tag_get_language_code_iso_639_2T (*c);
848     fail_unless (c2t != NULL);
849     fail_unless (g_utf8_validate (c2t, -1, NULL));
850
851     c2b = gst_tag_get_language_code_iso_639_2B (*c);
852     fail_unless (c2b != NULL);
853     fail_unless (g_utf8_validate (c2b, -1, NULL));
854
855     ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (*c), *c);
856     ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (c2t), *c);
857     ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (c2b), *c);
858
859     GST_DEBUG ("[%s] %s %s %s : %s", *c, c1, c2t, c2b, lang_name);
860
861   }
862   g_strfreev (lang_codes);
863
864   fail_unless (gst_tag_get_language_name ("de") != NULL);
865   fail_unless (gst_tag_get_language_name ("deu") != NULL);
866   fail_unless (gst_tag_get_language_name ("ger") != NULL);
867   fail_unless_equals_string (gst_tag_get_language_name ("deu"),
868       gst_tag_get_language_name ("ger"));
869   fail_unless_equals_string (gst_tag_get_language_name ("de"),
870       gst_tag_get_language_name ("ger"));
871   fail_unless (gst_tag_get_language_name ("de") !=
872       gst_tag_get_language_name ("fr"));
873
874   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("deu"), "de");
875   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("de"), "de");
876   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("ger"), "de");
877
878   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("deu"), "de");
879   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("de"), "de");
880   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("ger"), "de");
881
882   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("de"), "deu");
883   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("deu"), "deu");
884   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("ger"), "deu");
885
886   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("de"), "ger");
887   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("deu"), "ger");
888   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("ger"), "ger");
889
890   fail_unless (gst_tag_check_language_code ("de"));
891   fail_unless (gst_tag_check_language_code ("deu"));
892   fail_unless (gst_tag_check_language_code ("ger"));
893   fail_if (gst_tag_check_language_code ("xxx"));
894   fail_if (gst_tag_check_language_code ("und"));
895   fail_if (gst_tag_check_language_code ("un"));
896   fail_if (gst_tag_check_language_code (""));
897   fail_if (gst_tag_check_language_code ("\377"));
898   fail_if (gst_tag_check_language_code ("deutsch"));
899 }
900
901 GST_END_TEST;
902
903 #define SPECIFIC_L "http://creativecommons.org/licenses/by-nc-sa/2.5/scotland/"
904 #define GENERIC_L "http://creativecommons.org/licenses/by/1.0/"
905 #define DERIVED_L "http://creativecommons.org/licenses/sampling+/1.0/tw/"
906
907 GST_START_TEST (test_license_utils)
908 {
909   GHashTable *ht;
910   GError *err = NULL;
911   gchar **liblicense_refs, **r;
912   gchar **lrefs, **l;
913   gchar *path, *data = NULL;
914   gsize data_len;
915
916   gst_debug_set_threshold_for_name ("tag-licenses", GST_LEVEL_NONE);
917
918   /* test jurisdiction-specific license */
919   fail_unless_equals_int (gst_tag_get_license_flags (SPECIFIC_L), 0x01010703);
920   fail_unless_equals_string (gst_tag_get_license_nick (SPECIFIC_L),
921       "CC BY-NC-SA 2.5 SCOTLAND");
922   fail_unless_equals_string (gst_tag_get_license_version (SPECIFIC_L), "2.5");
923   fail_unless_equals_string (gst_tag_get_license_jurisdiction (SPECIFIC_L),
924       "scotland");
925
926   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "C", TRUE);
927   fail_unless_equals_string (gst_tag_get_license_title (SPECIFIC_L),
928       "Attribution-NonCommercial-ShareAlike");
929   fail_unless (gst_tag_get_license_description (SPECIFIC_L) == NULL);
930
931   /* test generic license */
932   fail_unless_equals_int (gst_tag_get_license_flags (GENERIC_L), 0x01000307);
933   fail_unless_equals_string (gst_tag_get_license_nick (GENERIC_L), "CC BY 1.0");
934   fail_unless_equals_string (gst_tag_get_license_version (GENERIC_L), "1.0");
935   fail_unless (gst_tag_get_license_jurisdiction (GENERIC_L) == NULL);
936
937   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "C", TRUE);
938   fail_unless_equals_string (gst_tag_get_license_title (GENERIC_L),
939       "Attribution");
940   fail_unless_equals_string (gst_tag_get_license_description (GENERIC_L),
941       "You must attribute the work in the manner specified by the author or licensor.");
942
943 #ifdef ENABLE_NLS
944   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "fr", TRUE);
945   fail_unless_equals_string (gst_tag_get_license_title (GENERIC_L),
946       "Paternité");
947   fail_unless_equals_string (gst_tag_get_license_description (GENERIC_L),
948       "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.");
949 #endif
950
951   /* test derived (for a certain jurisdiction) license */
952   fail_unless_equals_int (gst_tag_get_license_flags (DERIVED_L), 0x0100030d);
953   fail_unless_equals_string (gst_tag_get_license_nick (DERIVED_L),
954       "CC SAMPLING+ 1.0 TW");
955   fail_unless_equals_string (gst_tag_get_license_version (DERIVED_L), "1.0");
956   fail_unless_equals_string (gst_tag_get_license_jurisdiction (DERIVED_L),
957       "tw");
958
959   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "C", TRUE);
960   fail_unless_equals_string (gst_tag_get_license_title (DERIVED_L),
961       "Sampling Plus");
962   fail_unless_equals_string (gst_tag_get_license_description (GENERIC_L),
963       "You must attribute the work in the manner specified by the author or licensor.");
964
965   /* test all we know about */
966   lrefs = gst_tag_get_licenses ();
967   fail_unless (lrefs != NULL);
968   fail_unless (*lrefs != NULL);
969
970   GST_INFO ("%d licenses", g_strv_length (lrefs));
971   fail_unless (g_strv_length (lrefs) >= 376);
972
973   ht = g_hash_table_new (g_str_hash, g_str_equal);
974
975   for (l = lrefs; l != NULL && *l != NULL; ++l) {
976     const gchar *ref, *nick, *title, *desc G_GNUC_UNUSED;
977
978     ref = (const gchar *) *l;
979     nick = gst_tag_get_license_nick (ref);
980     title = gst_tag_get_license_title (ref);
981     desc = gst_tag_get_license_description (ref);
982     fail_unless (nick != NULL, "no nick for license '%s'", ref);
983     fail_unless (title != NULL, "no title for license '%s'", ref);
984     GST_LOG ("ref: %s [nick %s]", ref, (nick) ? nick : "none");
985     GST_TRACE ("    %s : %s", title, (desc) ? desc : "(no description)");
986
987     /* make sure the list contains no duplicates */
988     fail_if (g_hash_table_lookup (ht, (gpointer) ref) != NULL);
989     g_hash_table_insert (ht, (gpointer) ref, (gpointer) "meep");
990   }
991   g_hash_table_destroy (ht);
992
993   /* trailing slash shouldn't make a difference */
994   fail_unless_equals_int (gst_tag_get_license_flags
995       ("http://creativecommons.org/licenses/by-nd/1.0/"),
996       gst_tag_get_license_flags
997       ("http://creativecommons.org/licenses/by-nd/1.0"));
998   fail_unless_equals_string (gst_tag_get_license_nick
999       ("http://creativecommons.org/licenses/by-nd/1.0/"),
1000       gst_tag_get_license_nick
1001       ("http://creativecommons.org/licenses/by-nd/1.0"));
1002   fail_unless_equals_int (gst_tag_get_license_flags
1003       ("http://creativecommons.org/licenses/by-nd/2.5/ca/"),
1004       gst_tag_get_license_flags
1005       ("http://creativecommons.org/licenses/by-nd/2.5/ca"));
1006   fail_unless_equals_string (gst_tag_get_license_nick
1007       ("http://creativecommons.org/licenses/by-nd/2.5/ca/"),
1008       gst_tag_get_license_nick
1009       ("http://creativecommons.org/licenses/by-nd/2.5/ca"));
1010
1011   /* unknown licenses */
1012   fail_unless (gst_tag_get_license_nick
1013       ("http://creativecommons.org/licenses/by-nd/25/ca/") == NULL);
1014   fail_unless (gst_tag_get_license_flags
1015       ("http://creativecommons.org/licenses/by-nd/25/ca") == 0);
1016   fail_unless (gst_tag_get_license_jurisdiction
1017       ("http://creativecommons.org/licenses/by-nd/25/ca/") == NULL);
1018   fail_unless (gst_tag_get_license_jurisdiction
1019       ("http://creativecommons.org/licenses/by-nd/25/ca") == NULL);
1020   fail_unless (gst_tag_get_license_title
1021       ("http://creativecommons.org/licenses/by-nd/25/ca") == NULL);
1022   fail_unless (gst_tag_get_license_jurisdiction
1023       ("http://creativecommons.org/licenses/by-nd/25/ca") == NULL);
1024
1025   /* unknown prefixes even */
1026   fail_unless (gst_tag_get_license_nick
1027       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
1028   fail_unless (gst_tag_get_license_flags
1029       ("http://copycats.org/licenses/by-nd/2.5/ca") == 0);
1030   fail_unless (gst_tag_get_license_jurisdiction
1031       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
1032   fail_unless (gst_tag_get_license_title
1033       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
1034   fail_unless (gst_tag_get_license_description
1035       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
1036
1037   /* read list of liblicense refs from file */
1038   path = g_build_filename (GST_TEST_FILES_PATH, "license-uris", NULL);
1039   GST_LOG ("reading file '%s'", path);
1040   if (!g_file_get_contents (path, &data, &data_len, &err)) {
1041     g_error ("error loading test file: %s", err->message);
1042   }
1043
1044   while (data_len > 0 && data[data_len - 1] == '\n') {
1045     data[--data_len] = '\0';
1046   }
1047
1048   liblicense_refs = g_strsplit (data, "\n", -1);
1049   g_free (data);
1050   g_free (path);
1051
1052   fail_unless (g_strv_length (lrefs) >= g_strv_length (liblicense_refs));
1053
1054   for (r = liblicense_refs; r != NULL && *r != NULL; ++r) {
1055     GstTagLicenseFlags flags;
1056     const gchar *version, *nick, *jur;
1057     const gchar *ref = *r;
1058
1059     GST_LOG ("liblicense ref: %s", ref);
1060
1061     version = gst_tag_get_license_version (ref);
1062     if (strstr (ref, "publicdomain") != NULL)
1063       fail_unless (version == NULL);
1064     else
1065       fail_unless (version != NULL, "expected version for license %s", ref);
1066
1067     flags = gst_tag_get_license_flags (ref);
1068     fail_unless (flags != 0, "expected non-zero flags for license %s", ref);
1069
1070     nick = gst_tag_get_license_nick (ref);
1071     fail_unless (nick != NULL, "expected nick for license %s", ref);
1072
1073     jur = gst_tag_get_license_jurisdiction (ref);
1074     if (g_str_has_suffix (ref, "de/")) {
1075       fail_unless_equals_string (jur, "de");
1076     } else if (g_str_has_suffix (ref, "scotland")) {
1077       fail_unless_equals_string (jur, "scotland");
1078     } else if (g_str_has_suffix (ref, ".0") || g_str_has_suffix (ref, ".1")) {
1079       fail_unless (jur == NULL);
1080     }
1081   }
1082
1083   g_strfreev (liblicense_refs);
1084   g_strfreev (lrefs);
1085 }
1086
1087 GST_END_TEST;
1088
1089 GST_START_TEST (test_xmp_formatting)
1090 {
1091   GstTagList *list;
1092   GstBuffer *buf;
1093   GstMapInfo map;
1094   const gchar *text;
1095   gsize len;
1096
1097   /* test data */
1098   list = gst_tag_list_new (GST_TAG_TITLE, "test title",
1099       GST_TAG_DESCRIPTION, "test decription",
1100       GST_TAG_KEYWORDS, "keyword1", GST_TAG_KEYWORDS, "keyword2", NULL);
1101
1102   buf = gst_tag_list_to_xmp_buffer (list, FALSE, NULL);
1103   fail_unless (buf != NULL);
1104
1105   gst_buffer_map (buf, &map, GST_MAP_READ);
1106   text = (gchar *) map.data;
1107   len = map.size;
1108
1109   /* check the content */
1110   fail_unless (g_strrstr_len (text, len, "<?xpacket begin") == text);
1111   fail_unless (g_strrstr_len (text, len, ">test title<") != NULL);
1112   fail_unless (g_strrstr_len (text, len, ">test decription<") != NULL);
1113   fail_unless (g_strrstr_len (text, len, ">keyword1<") != NULL);
1114   fail_unless (g_strrstr_len (text, len, ">keyword2<") != NULL);
1115   fail_unless (g_strrstr_len (text, len, "<?xpacket end") != NULL);
1116   gst_buffer_unmap (buf, &map);
1117
1118   gst_buffer_unref (buf);
1119   gst_tag_list_unref (list);
1120 }
1121
1122 GST_END_TEST;
1123
1124
1125 GST_START_TEST (test_xmp_parsing)
1126 {
1127   GstTagList *list;
1128   GstBuffer *buf;
1129   guint i, j, result_size;
1130   gchar *text;
1131   const gchar *xmp_header =
1132       "<?xpacket begin=\"\xEF\xBB\xBF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>"
1133       "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"GStreamer\">"
1134       "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">";
1135
1136   /* We used to write an extra trailing \n after the footer, keep compatibility
1137    * with our old generated media by checking that it still can be parsed */
1138   const gchar *xmp_footers[] = {
1139     "</rdf:RDF>" "</x:xmpmeta>" "<?xpacket end=\"r\"?>",
1140     "</rdf:RDF>" "</x:xmpmeta>" "<?xpacket end=\"r\"?>\n",
1141     NULL
1142   };
1143
1144   struct
1145   {
1146     const gchar *xmp_data;
1147     gint result_size;
1148     gint result_test;
1149   } test_data[] = {
1150     {
1151     "", -1, -1}, {
1152     "<rdf:Description rdf:about=\"\" />", 0, -1}, {
1153     "<rdf:Description rdf:about=\"\"></rdf:Description>", 0, -1}, {
1154     "<rdf:Description    rdf:about=\"\"    ></rdf:Description>", 0, -1}, {
1155     "<rdf:Description rdf:about=\"\"><dc:description>test</dc:description></rdf:Description>",
1156           1, 0}, {
1157     "<rdf:Description rdf:about=\"\" dc:description=\"test\"></rdf:Description>",
1158           1, 0}, {
1159     NULL, -1, -1}
1160   };
1161
1162   /* test data */
1163   j = 0;
1164   i = 0;
1165   while (xmp_footers[j]) {
1166     while (test_data[i].xmp_data) {
1167       gsize len;
1168
1169       GST_DEBUG ("trying test-data %u", i);
1170
1171       text =
1172           g_strconcat (xmp_header, test_data[i].xmp_data, xmp_footers[j], NULL);
1173
1174       buf = gst_buffer_new ();
1175       len = strlen (text) + 1;
1176       gst_buffer_append_memory (buf,
1177           gst_memory_new_wrapped (0, text, len, 0, len, NULL, NULL));
1178
1179       list = gst_tag_list_from_xmp_buffer (buf);
1180       if (test_data[i].result_size >= 0) {
1181         fail_unless (list != NULL);
1182
1183         result_size = gst_tag_list_n_tags (list);
1184         fail_unless (result_size == test_data[i].result_size);
1185
1186         /* check the taglist content */
1187         switch (test_data[i].result_test) {
1188           case 0:
1189             ASSERT_TAG_LIST_HAS_STRING (list, "description", "test");
1190             break;
1191           default:
1192             break;
1193         }
1194       }
1195       if (list)
1196         gst_tag_list_unref (list);
1197
1198       gst_buffer_unref (buf);
1199       g_free (text);
1200       i++;
1201     }
1202     j++;
1203   }
1204 }
1205
1206 GST_END_TEST;
1207
1208 static void
1209 do_xmp_tag_serialization_deserialization (GstTagList * taglist,
1210     const gchar ** schemas)
1211 {
1212   GstTagList *taglist2;
1213   GstBuffer *buf;
1214
1215   buf = gst_tag_list_to_xmp_buffer (taglist, TRUE, schemas);
1216   taglist2 = gst_tag_list_from_xmp_buffer (buf);
1217
1218   fail_unless (gst_tag_list_is_equal (taglist, taglist2));
1219
1220   gst_buffer_unref (buf);
1221   gst_tag_list_unref (taglist2);
1222 }
1223
1224 static void
1225 do_simple_xmp_tag_serialization_deserialization (const gchar * gsttag,
1226     GValue * value)
1227 {
1228   GstTagList *taglist = gst_tag_list_new_empty ();
1229
1230   gst_tag_list_add_value (taglist, GST_TAG_MERGE_REPLACE, gsttag, value);
1231
1232   do_xmp_tag_serialization_deserialization (taglist, NULL);
1233   gst_tag_list_unref (taglist);
1234 }
1235
1236 GST_START_TEST (test_xmp_tags_serialization_deserialization)
1237 {
1238   GValue value = { 0 };
1239   GstDateTime *datetime;
1240
1241   gst_tag_register_musicbrainz_tags ();
1242
1243   g_value_init (&value, G_TYPE_STRING);
1244   g_value_set_static_string (&value, "my string");
1245   do_simple_xmp_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1246   do_simple_xmp_tag_serialization_deserialization (GST_TAG_COPYRIGHT, &value);
1247   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DESCRIPTION, &value);
1248   do_simple_xmp_tag_serialization_deserialization (GST_TAG_KEYWORDS, &value);
1249   do_simple_xmp_tag_serialization_deserialization (GST_TAG_TITLE, &value);
1250   do_simple_xmp_tag_serialization_deserialization (GST_TAG_VIDEO_CODEC, &value);
1251   do_simple_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_COUNTRY,
1252       &value);
1253   do_simple_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_CITY,
1254       &value);
1255   do_simple_xmp_tag_serialization_deserialization
1256       (GST_TAG_GEO_LOCATION_SUBLOCATION, &value);
1257   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DEVICE_MANUFACTURER,
1258       &value);
1259   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DEVICE_MODEL,
1260       &value);
1261   do_simple_xmp_tag_serialization_deserialization (GST_TAG_APPLICATION_NAME,
1262       &value);
1263
1264   g_value_set_static_string (&value, "rotate-0");
1265   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1266       &value);
1267   g_value_set_static_string (&value, "flip-rotate-0");
1268   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1269       &value);
1270   g_value_set_static_string (&value, "rotate-180");
1271   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1272       &value);
1273   g_value_set_static_string (&value, "flip-rotate-180");
1274   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1275       &value);
1276   g_value_set_static_string (&value, "flip-rotate-270");
1277   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1278       &value);
1279   g_value_set_static_string (&value, "rotate-90");
1280   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1281       &value);
1282   g_value_set_static_string (&value, "flip-rotate-90");
1283   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1284       &value);
1285   g_value_set_static_string (&value, "rotate-270");
1286   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1287       &value);
1288
1289   g_value_unset (&value);
1290   g_value_init (&value, G_TYPE_DOUBLE);
1291
1292   g_value_set_double (&value, 0.0);
1293   do_simple_xmp_tag_serialization_deserialization
1294       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1295   do_simple_xmp_tag_serialization_deserialization
1296       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1297   g_value_set_double (&value, 10.5);
1298   do_simple_xmp_tag_serialization_deserialization
1299       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1300   do_simple_xmp_tag_serialization_deserialization
1301       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1302   g_value_set_double (&value, -32.375);
1303   do_simple_xmp_tag_serialization_deserialization
1304       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1305   do_simple_xmp_tag_serialization_deserialization
1306       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1307
1308   g_value_set_double (&value, 0);
1309   do_simple_xmp_tag_serialization_deserialization
1310       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1311   g_value_set_double (&value, 100);
1312   do_simple_xmp_tag_serialization_deserialization
1313       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1314   g_value_set_double (&value, 500.25);
1315   do_simple_xmp_tag_serialization_deserialization
1316       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1317   g_value_set_double (&value, -12.75);
1318   do_simple_xmp_tag_serialization_deserialization
1319       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1320
1321   g_value_set_double (&value, 0.0);
1322   do_simple_xmp_tag_serialization_deserialization
1323       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1324   g_value_set_double (&value, 10.0);
1325   do_simple_xmp_tag_serialization_deserialization
1326       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1327   g_value_set_double (&value, 786.125);
1328   do_simple_xmp_tag_serialization_deserialization
1329       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1330   g_value_set_double (&value, -2.5);
1331   do_simple_xmp_tag_serialization_deserialization
1332       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1333
1334   g_value_set_double (&value, 0.0);
1335   do_simple_xmp_tag_serialization_deserialization
1336       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1337   g_value_set_double (&value, 180.0);
1338   do_simple_xmp_tag_serialization_deserialization
1339       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1340   g_value_set_double (&value, 359.99);
1341   do_simple_xmp_tag_serialization_deserialization
1342       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1343
1344   g_value_set_double (&value, 0.0);
1345   do_simple_xmp_tag_serialization_deserialization
1346       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1347   g_value_set_double (&value, 90.0);
1348   do_simple_xmp_tag_serialization_deserialization
1349       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1350   g_value_set_double (&value, 359.99);
1351   do_simple_xmp_tag_serialization_deserialization
1352       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1353
1354   g_value_set_double (&value, 0.0);
1355   do_simple_xmp_tag_serialization_deserialization
1356       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1357   g_value_set_double (&value, 1.0);
1358   do_simple_xmp_tag_serialization_deserialization
1359       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1360   g_value_set_double (&value, -2.5);
1361   do_simple_xmp_tag_serialization_deserialization
1362       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1363   g_value_unset (&value);
1364
1365   g_value_init (&value, GST_TYPE_DATE_TIME);
1366   datetime = gst_date_time_new_ymd (2010, 3, 22);
1367   g_value_take_boxed (&value, datetime);
1368   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1369   g_value_unset (&value);
1370
1371   g_value_init (&value, G_TYPE_UINT);
1372   g_value_set_uint (&value, 0);
1373   do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value);
1374   g_value_set_uint (&value, 100);
1375   do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value);
1376   g_value_set_uint (&value, 22);
1377   do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value);
1378   g_value_unset (&value);
1379
1380   g_value_init (&value, GST_TYPE_DATE_TIME);
1381   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10);
1382   g_value_set_boxed (&value, datetime);
1383   gst_date_time_unref (datetime);
1384   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1385   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.000125);
1386   g_value_set_boxed (&value, datetime);
1387   gst_date_time_unref (datetime);
1388   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1389   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.000001);
1390   g_value_set_boxed (&value, datetime);
1391   gst_date_time_unref (datetime);
1392   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1393   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.123456);
1394   g_value_set_boxed (&value, datetime);
1395   gst_date_time_unref (datetime);
1396   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1397   datetime = gst_date_time_new (-3, 2010, 6, 22, 12, 5, 10.123456);
1398   g_value_set_boxed (&value, datetime);
1399   gst_date_time_unref (datetime);
1400   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1401   datetime = gst_date_time_new (5, 2010, 6, 22, 12, 5, 10.123456);
1402   g_value_set_boxed (&value, datetime);
1403   gst_date_time_unref (datetime);
1404   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1405   datetime = gst_date_time_new_local_time (2010, 12, 2, 12, 5, 10.000043);
1406   g_value_set_boxed (&value, datetime);
1407   gst_date_time_unref (datetime);
1408   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1409   g_value_unset (&value);
1410 }
1411
1412 GST_END_TEST;
1413
1414
1415 GST_START_TEST (test_xmp_compound_tags)
1416 {
1417   const gchar *schemas[] = { "Iptc4xmpExt", NULL };
1418   GstTagList *taglist = gst_tag_list_new_empty ();
1419
1420   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_KEYWORDS, "k1",
1421       GST_TAG_KEYWORDS, "k2", GST_TAG_TITLE, "title", GST_TAG_KEYWORDS, "k3",
1422       NULL);
1423   do_xmp_tag_serialization_deserialization (taglist, NULL);
1424   gst_tag_list_unref (taglist);
1425
1426   taglist = gst_tag_list_new_empty ();
1427   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_GEO_LOCATION_COUNTRY,
1428       "Brazil", GST_TAG_GEO_LOCATION_CITY, "Campina Grande", NULL);
1429   do_xmp_tag_serialization_deserialization (taglist, schemas);
1430   gst_tag_list_unref (taglist);
1431 }
1432
1433 GST_END_TEST;
1434
1435
1436 GST_START_TEST (test_exif_parsing)
1437 {
1438   GstTagList *taglist;
1439   GstBuffer *buf;
1440   GstByteWriter writer;
1441   gboolean res = TRUE;
1442   const gchar *str = NULL;
1443
1444   gst_byte_writer_init (&writer);
1445
1446   /* write the IFD */
1447   /* 1 entry */
1448   res &= gst_byte_writer_put_uint16_le (&writer, 1);
1449
1450   /* copyright tag */
1451   /* tag id */
1452   res &= gst_byte_writer_put_uint16_le (&writer, 0x8298);
1453   /* tag type */
1454   res &= gst_byte_writer_put_uint16_le (&writer, 0x2);
1455   /* count */
1456   res &= gst_byte_writer_put_uint32_le (&writer, strlen ("my copyright") + 1);
1457   /* offset */
1458   res &= gst_byte_writer_put_uint32_le (&writer, 8 + 14);
1459
1460   /* data */
1461   res &= gst_byte_writer_put_string (&writer, "my copyright");
1462
1463   fail_unless (res, "Failed to write tag");
1464
1465   buf = gst_byte_writer_reset_and_get_buffer (&writer);
1466
1467   taglist = gst_tag_list_from_exif_buffer (buf, G_LITTLE_ENDIAN, 8);
1468
1469   fail_unless (gst_tag_list_get_tag_size (taglist, GST_TAG_COPYRIGHT) == 1);
1470   gst_tag_list_peek_string_index (taglist, GST_TAG_COPYRIGHT, 0, &str);
1471   fail_unless_equals_string (str, "my copyright");
1472
1473   gst_tag_list_unref (taglist);
1474   gst_buffer_unref (buf);
1475 }
1476
1477 GST_END_TEST;
1478
1479
1480 static void
1481 do_exif_tag_serialization_deserialization (GstTagList * taglist)
1482 {
1483   GstTagList *taglist2;
1484   GstBuffer *buf;
1485
1486   /* LE */
1487   buf = gst_tag_list_to_exif_buffer (taglist, G_LITTLE_ENDIAN, 0);
1488   taglist2 = gst_tag_list_from_exif_buffer (buf, G_LITTLE_ENDIAN, 0);
1489   gst_buffer_unref (buf);
1490
1491   fail_unless (gst_tag_list_is_equal (taglist, taglist2));
1492   gst_tag_list_unref (taglist2);
1493
1494   /* BE */
1495   buf = gst_tag_list_to_exif_buffer (taglist, G_BIG_ENDIAN, 0);
1496   taglist2 = gst_tag_list_from_exif_buffer (buf, G_BIG_ENDIAN, 0);
1497   gst_buffer_unref (buf);
1498
1499   fail_unless (gst_tag_list_is_equal (taglist, taglist2));
1500   gst_tag_list_unref (taglist2);
1501
1502   /* APP1 */
1503   buf = gst_tag_list_to_exif_buffer_with_tiff_header (taglist);
1504   taglist2 = gst_tag_list_from_exif_buffer_with_tiff_header (buf);
1505   gst_buffer_unref (buf);
1506
1507   fail_unless (gst_tag_list_is_equal (taglist, taglist2));
1508   gst_tag_list_unref (taglist2);
1509 }
1510
1511 static void
1512 do_simple_exif_tag_serialization_deserialization (const gchar * gsttag,
1513     GValue * value)
1514 {
1515   GstTagList *taglist = gst_tag_list_new_empty ();
1516
1517   gst_tag_list_add_value (taglist, GST_TAG_MERGE_REPLACE, gsttag, value);
1518   do_exif_tag_serialization_deserialization (taglist);
1519
1520   gst_tag_list_unref (taglist);
1521 }
1522
1523 /*
1524  * Adds tags from multiple ifd tables and tries serializing them
1525  */
1526 GST_START_TEST (test_exif_multiple_tags)
1527 {
1528   GstTagList *taglist;
1529   GstDateTime *datetime;
1530   GValue value = { 0 };
1531
1532   gst_tag_register_musicbrainz_tags ();
1533
1534   taglist = gst_tag_list_new (GST_TAG_ARTIST, "artist",
1535       GST_TAG_DEVICE_MANUFACTURER, "make",
1536       GST_TAG_DEVICE_MODEL, "model", GST_TAG_GEO_LOCATION_LATITUDE, 45.5,
1537       GST_TAG_GEO_LOCATION_LONGITUDE, -10.25,
1538       GST_TAG_IMAGE_HORIZONTAL_PPI, 300.0,
1539       GST_TAG_IMAGE_VERTICAL_PPI, 300.0, NULL);
1540
1541   g_value_init (&value, GST_TYPE_DATE_TIME);
1542   datetime = gst_date_time_new_local_time (2010, 6, 22, 12, 5, 10);
1543   g_value_set_boxed (&value, datetime);
1544   gst_date_time_unref (datetime);
1545   gst_tag_list_add_value (taglist, GST_TAG_MERGE_APPEND, GST_TAG_DATE_TIME,
1546       &value);
1547   g_value_unset (&value);
1548
1549   do_exif_tag_serialization_deserialization (taglist);
1550
1551   gst_tag_list_unref (taglist);
1552 }
1553
1554 GST_END_TEST;
1555
1556
1557 GST_START_TEST (test_exif_tags_serialization_deserialization)
1558 {
1559   GValue value = { 0 };
1560   GstDateTime *datetime = NULL;
1561   GstBuffer *buf = NULL;
1562   gint i;
1563   GstTagList *taglist;
1564   GstMapInfo map;
1565   guint8 *data;
1566
1567   gst_tag_register_musicbrainz_tags ();
1568
1569   g_value_init (&value, G_TYPE_STRING);
1570   g_value_set_static_string (&value, "my string");
1571   do_simple_exif_tag_serialization_deserialization (GST_TAG_COPYRIGHT, &value);
1572   g_value_set_static_string (&value, "ty");
1573   do_simple_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1574   g_value_set_static_string (&value, "Company Software 1.2b (info)");
1575   do_simple_exif_tag_serialization_deserialization (GST_TAG_APPLICATION_NAME,
1576       &value);
1577
1578   /* non ascii chars */
1579   g_value_set_static_string (&value, "AaÄäEeËëIiÏïOoÖöUuÜü");
1580   do_simple_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1581   g_value_set_static_string (&value, "Äë");
1582   do_simple_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1583
1584   /* image orientation tests */
1585   g_value_set_static_string (&value, "rotate-0");
1586   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1587       &value);
1588   g_value_set_static_string (&value, "flip-rotate-0");
1589   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1590       &value);
1591   g_value_set_static_string (&value, "rotate-180");
1592   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1593       &value);
1594   g_value_set_static_string (&value, "flip-rotate-180");
1595   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1596       &value);
1597   g_value_set_static_string (&value, "flip-rotate-270");
1598   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1599       &value);
1600   g_value_set_static_string (&value, "rotate-90");
1601   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1602       &value);
1603   g_value_set_static_string (&value, "flip-rotate-90");
1604   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1605       &value);
1606   g_value_set_static_string (&value, "rotate-270");
1607   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1608       &value);
1609
1610   /* exposure program */
1611   g_value_set_static_string (&value, "undefined");
1612   do_simple_exif_tag_serialization_deserialization
1613       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1614   g_value_set_static_string (&value, "manual");
1615   do_simple_exif_tag_serialization_deserialization
1616       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1617   g_value_set_static_string (&value, "normal");
1618   do_simple_exif_tag_serialization_deserialization
1619       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1620   g_value_set_static_string (&value, "aperture-priority");
1621   do_simple_exif_tag_serialization_deserialization
1622       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1623   g_value_set_static_string (&value, "shutter-priority");
1624   do_simple_exif_tag_serialization_deserialization
1625       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1626   g_value_set_static_string (&value, "creative");
1627   do_simple_exif_tag_serialization_deserialization
1628       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1629   g_value_set_static_string (&value, "action");
1630   do_simple_exif_tag_serialization_deserialization
1631       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1632   g_value_set_static_string (&value, "portrait");
1633   do_simple_exif_tag_serialization_deserialization
1634       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1635   g_value_set_static_string (&value, "landscape");
1636   do_simple_exif_tag_serialization_deserialization
1637       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1638
1639   /* exposure mode */
1640   g_value_set_static_string (&value, "auto-exposure");
1641   do_simple_exif_tag_serialization_deserialization
1642       (GST_TAG_CAPTURING_EXPOSURE_MODE, &value);
1643   g_value_set_static_string (&value, "manual-exposure");
1644   do_simple_exif_tag_serialization_deserialization
1645       (GST_TAG_CAPTURING_EXPOSURE_MODE, &value);
1646   g_value_set_static_string (&value, "auto-bracket");
1647   do_simple_exif_tag_serialization_deserialization
1648       (GST_TAG_CAPTURING_EXPOSURE_MODE, &value);
1649
1650   /* scene capture type */
1651   g_value_set_static_string (&value, "standard");
1652   do_simple_exif_tag_serialization_deserialization
1653       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1654   g_value_set_static_string (&value, "portrait");
1655   do_simple_exif_tag_serialization_deserialization
1656       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1657   g_value_set_static_string (&value, "landscape");
1658   do_simple_exif_tag_serialization_deserialization
1659       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1660   g_value_set_static_string (&value, "night-scene");
1661   do_simple_exif_tag_serialization_deserialization
1662       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1663
1664   g_value_set_static_string (&value, "none");
1665   do_simple_exif_tag_serialization_deserialization
1666       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1667   g_value_set_static_string (&value, "high-gain-up");
1668   do_simple_exif_tag_serialization_deserialization
1669       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1670   g_value_set_static_string (&value, "low-gain-up");
1671   do_simple_exif_tag_serialization_deserialization
1672       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1673   g_value_set_static_string (&value, "high-gain-down");
1674   do_simple_exif_tag_serialization_deserialization
1675       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1676   g_value_set_static_string (&value, "low-gain-down");
1677   do_simple_exif_tag_serialization_deserialization
1678       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1679
1680   g_value_set_static_string (&value, "auto");
1681   do_simple_exif_tag_serialization_deserialization
1682       (GST_TAG_CAPTURING_WHITE_BALANCE, &value);
1683   g_value_set_static_string (&value, "manual");
1684   do_simple_exif_tag_serialization_deserialization
1685       (GST_TAG_CAPTURING_WHITE_BALANCE, &value);
1686
1687   g_value_set_static_string (&value, "normal");
1688   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST,
1689       &value);
1690   g_value_set_static_string (&value, "hard");
1691   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST,
1692       &value);
1693   g_value_set_static_string (&value, "soft");
1694   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST,
1695       &value);
1696
1697   g_value_set_static_string (&value, "normal");
1698   do_simple_exif_tag_serialization_deserialization
1699       (GST_TAG_CAPTURING_SATURATION, &value);
1700   g_value_set_static_string (&value, "low-saturation");
1701   do_simple_exif_tag_serialization_deserialization
1702       (GST_TAG_CAPTURING_SATURATION, &value);
1703   g_value_set_static_string (&value, "high-saturation");
1704   do_simple_exif_tag_serialization_deserialization
1705       (GST_TAG_CAPTURING_SATURATION, &value);
1706
1707   g_value_set_static_string (&value, "normal");
1708   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS,
1709       &value);
1710   g_value_set_static_string (&value, "hard");
1711   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS,
1712       &value);
1713   g_value_set_static_string (&value, "soft");
1714   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS,
1715       &value);
1716
1717   g_value_set_static_string (&value, "unknown");
1718   do_simple_exif_tag_serialization_deserialization
1719       (GST_TAG_CAPTURING_METERING_MODE, &value);
1720   g_value_set_static_string (&value, "average");
1721   do_simple_exif_tag_serialization_deserialization
1722       (GST_TAG_CAPTURING_METERING_MODE, &value);
1723   g_value_set_static_string (&value, "center-weighted-average");
1724   do_simple_exif_tag_serialization_deserialization
1725       (GST_TAG_CAPTURING_METERING_MODE, &value);
1726   g_value_set_static_string (&value, "spot");
1727   do_simple_exif_tag_serialization_deserialization
1728       (GST_TAG_CAPTURING_METERING_MODE, &value);
1729   g_value_set_static_string (&value, "multi-spot");
1730   do_simple_exif_tag_serialization_deserialization
1731       (GST_TAG_CAPTURING_METERING_MODE, &value);
1732   g_value_set_static_string (&value, "pattern");
1733   do_simple_exif_tag_serialization_deserialization
1734       (GST_TAG_CAPTURING_METERING_MODE, &value);
1735   g_value_set_static_string (&value, "partial");
1736   do_simple_exif_tag_serialization_deserialization
1737       (GST_TAG_CAPTURING_METERING_MODE, &value);
1738   g_value_set_static_string (&value, "other");
1739   do_simple_exif_tag_serialization_deserialization
1740       (GST_TAG_CAPTURING_METERING_MODE, &value);
1741
1742   g_value_set_static_string (&value, "dsc");
1743   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1744       &value);
1745   g_value_set_static_string (&value, "other");
1746   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1747       &value);
1748   g_value_set_static_string (&value, "transparent-scanner");
1749   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1750       &value);
1751   g_value_set_static_string (&value, "reflex-scanner");
1752   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1753       &value);
1754   g_value_unset (&value);
1755
1756   g_value_init (&value, G_TYPE_DOUBLE);
1757   g_value_set_double (&value, 40.3456784);
1758   do_simple_exif_tag_serialization_deserialization
1759       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1760   g_value_set_double (&value, -12.1250865);
1761
1762   do_simple_exif_tag_serialization_deserialization
1763       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1764   g_value_set_double (&value, 0);
1765   do_simple_exif_tag_serialization_deserialization
1766       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1767   g_value_set_double (&value, 65.0);
1768   do_simple_exif_tag_serialization_deserialization
1769       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1770   g_value_set_double (&value, -0.75);
1771   do_simple_exif_tag_serialization_deserialization
1772       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1773
1774   g_value_set_double (&value, 0.0);
1775   do_simple_exif_tag_serialization_deserialization
1776       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1777   g_value_set_double (&value, 180.5);
1778   do_simple_exif_tag_serialization_deserialization
1779       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1780   g_value_set_double (&value, 0.12345);
1781   do_simple_exif_tag_serialization_deserialization
1782       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1783   g_value_set_double (&value, 359.9);
1784   do_simple_exif_tag_serialization_deserialization
1785       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1786
1787   g_value_set_double (&value, 0.0);
1788   do_simple_exif_tag_serialization_deserialization
1789       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1790   g_value_set_double (&value, 321.456);
1791   do_simple_exif_tag_serialization_deserialization
1792       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1793   g_value_set_double (&value, -12.56);
1794   do_simple_exif_tag_serialization_deserialization
1795       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1796
1797   g_value_set_double (&value, 0);
1798   do_simple_exif_tag_serialization_deserialization
1799       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1800   g_value_set_double (&value, 100 / 3.6);
1801   do_simple_exif_tag_serialization_deserialization
1802       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1803
1804   g_value_set_double (&value, 0);
1805   do_simple_exif_tag_serialization_deserialization
1806       (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, &value);
1807   g_value_set_double (&value, 50.25);
1808   do_simple_exif_tag_serialization_deserialization
1809       (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, &value);
1810
1811   g_value_set_double (&value, 0);
1812   do_simple_exif_tag_serialization_deserialization
1813       (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value);
1814   g_value_set_double (&value, 2.5);
1815   do_simple_exif_tag_serialization_deserialization
1816       (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value);
1817   g_value_set_double (&value, 8.75);
1818   do_simple_exif_tag_serialization_deserialization
1819       (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value);
1820
1821   g_value_set_double (&value, 20.0);
1822   do_simple_exif_tag_serialization_deserialization
1823       (GST_TAG_CAPTURING_FOCAL_LENGTH, &value);
1824   g_value_set_double (&value, 5.5);
1825   do_simple_exif_tag_serialization_deserialization
1826       (GST_TAG_CAPTURING_FOCAL_LENGTH, &value);
1827
1828   g_value_set_double (&value, 16);
1829   do_simple_exif_tag_serialization_deserialization
1830       (GST_TAG_CAPTURING_FOCAL_RATIO, &value);
1831   g_value_set_double (&value, 2.7);
1832   do_simple_exif_tag_serialization_deserialization
1833       (GST_TAG_CAPTURING_FOCAL_LENGTH, &value);
1834
1835   g_value_set_double (&value, 96.0);
1836   do_simple_exif_tag_serialization_deserialization
1837       (GST_TAG_IMAGE_HORIZONTAL_PPI, &value);
1838   g_value_set_double (&value, 300.0);
1839   do_simple_exif_tag_serialization_deserialization
1840       (GST_TAG_IMAGE_HORIZONTAL_PPI, &value);
1841   g_value_set_double (&value, 87.5);
1842   do_simple_exif_tag_serialization_deserialization
1843       (GST_TAG_IMAGE_VERTICAL_PPI, &value);
1844   g_value_set_double (&value, 600.0);
1845   do_simple_exif_tag_serialization_deserialization
1846       (GST_TAG_IMAGE_VERTICAL_PPI, &value);
1847
1848   g_value_set_double (&value, 0.0);
1849   do_simple_exif_tag_serialization_deserialization
1850       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1851   g_value_set_double (&value, 1.0);
1852   do_simple_exif_tag_serialization_deserialization
1853       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1854   g_value_set_double (&value, -2.5);
1855   do_simple_exif_tag_serialization_deserialization
1856       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1857
1858   g_value_set_double (&value, 50.0);
1859   do_simple_exif_tag_serialization_deserialization
1860       (GST_TAG_CAPTURING_FOCAL_LENGTH_35_MM, &value);
1861   g_value_unset (&value);
1862
1863   g_value_init (&value, G_TYPE_INT);
1864   g_value_set_int (&value, 400);
1865   do_simple_exif_tag_serialization_deserialization
1866       (GST_TAG_CAPTURING_ISO_SPEED, &value);
1867   g_value_set_int (&value, 1600);
1868   do_simple_exif_tag_serialization_deserialization
1869       (GST_TAG_CAPTURING_ISO_SPEED, &value);
1870   g_value_unset (&value);
1871
1872   g_value_init (&value, GST_TYPE_DATE_TIME);
1873   datetime = gst_date_time_new_local_time (2010, 6, 22, 12, 5, 10);
1874   g_value_set_boxed (&value, datetime);
1875   gst_date_time_unref (datetime);
1876   do_simple_exif_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1877   g_value_unset (&value);
1878
1879   g_value_init (&value, GST_TYPE_SAMPLE);
1880   buf = gst_buffer_new_and_alloc (1024);
1881   gst_buffer_map (buf, &map, GST_MAP_WRITE);
1882   data = map.data;
1883   for (i = 0; i < 1024; i++)
1884     data[i] = i % 255;
1885   gst_buffer_unmap (buf, &map);
1886   gst_value_take_sample (&value, gst_sample_new (buf, NULL, NULL, NULL));
1887   gst_buffer_unref (buf);
1888   do_simple_exif_tag_serialization_deserialization (GST_TAG_APPLICATION_DATA,
1889       &value);
1890   g_value_unset (&value);
1891
1892   g_value_init (&value, GST_TYPE_FRACTION);
1893   gst_value_set_fraction (&value, 1, 1);
1894   do_simple_exif_tag_serialization_deserialization
1895       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1896   gst_value_set_fraction (&value, 1, 30);
1897   do_simple_exif_tag_serialization_deserialization
1898       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1899   gst_value_set_fraction (&value, 1, 200);
1900   do_simple_exif_tag_serialization_deserialization
1901       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1902   gst_value_set_fraction (&value, 1, 8000);
1903   do_simple_exif_tag_serialization_deserialization
1904       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1905   g_value_unset (&value);
1906
1907   /* flash is a little bit more tricky, because 2 tags are merged into 1 in
1908    * exif */
1909   taglist = gst_tag_list_new (GST_TAG_CAPTURING_FLASH_FIRED, FALSE,
1910       GST_TAG_CAPTURING_FLASH_MODE, "auto", NULL);
1911   do_exif_tag_serialization_deserialization (taglist);
1912   gst_tag_list_unref (taglist);
1913
1914   taglist = gst_tag_list_new (GST_TAG_CAPTURING_FLASH_FIRED, TRUE,
1915       GST_TAG_CAPTURING_FLASH_MODE, "auto", NULL);
1916   do_exif_tag_serialization_deserialization (taglist);
1917   gst_tag_list_unref (taglist);
1918
1919   taglist = gst_tag_list_new (GST_TAG_CAPTURING_FLASH_FIRED, FALSE,
1920       GST_TAG_CAPTURING_FLASH_MODE, "never", NULL);
1921   do_exif_tag_serialization_deserialization (taglist);
1922   gst_tag_list_unref (taglist);
1923
1924   taglist = gst_tag_list_new (GST_TAG_CAPTURING_FLASH_FIRED, TRUE,
1925       GST_TAG_CAPTURING_FLASH_MODE, "always", NULL);
1926   do_exif_tag_serialization_deserialization (taglist);
1927   gst_tag_list_unref (taglist);
1928 }
1929
1930 GST_END_TEST;
1931
1932 static Suite *
1933 tag_suite (void)
1934 {
1935   Suite *s = suite_create ("tag support library");
1936   TCase *tc_chain = tcase_create ("general");
1937
1938   suite_add_tcase (s, tc_chain);
1939   tcase_add_test (tc_chain, test_musicbrainz_tag_registration);
1940   tcase_add_test (tc_chain, test_parse_extended_comment);
1941   tcase_add_test (tc_chain, test_vorbis_tags);
1942   tcase_add_test (tc_chain, test_id3_tags);
1943   tcase_add_test (tc_chain, test_id3v1_utf8_tag);
1944   tcase_add_test (tc_chain, test_id3v2_priv_tag);
1945   tcase_add_test (tc_chain, test_id3v2_extended_header);
1946   tcase_add_test (tc_chain, test_id3v2_string_list_utf16);
1947   tcase_add_test (tc_chain, test_language_utils);
1948   tcase_add_test (tc_chain, test_license_utils);
1949   tcase_add_test (tc_chain, test_xmp_formatting);
1950   tcase_add_test (tc_chain, test_xmp_parsing);
1951   tcase_add_test (tc_chain, test_xmp_tags_serialization_deserialization);
1952   tcase_add_test (tc_chain, test_xmp_compound_tags);
1953   tcase_add_test (tc_chain, test_exif_parsing);
1954   tcase_add_test (tc_chain, test_exif_tags_serialization_deserialization);
1955   tcase_add_test (tc_chain, test_exif_multiple_tags);
1956   return s;
1957 }
1958
1959 GST_CHECK_MAIN (tag);