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