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