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