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