Added gst-plugins-base-subtitles0.10-0.10.34 for Meego Harmattan 1.2
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / debian / patches / 0024-tag-xmp-Add-struct-xmp-tag-type-support.patch
1 From 2c10edefb47f82a72a27fb54fb181c4e3ea440cf Mon Sep 17 00:00:00 2001
2 From: Thiago Santos <thiago.sousa.santos@collabora.co.uk>
3 Date: Mon, 18 Apr 2011 16:54:54 -0300
4 Subject: [PATCH] tag: xmp: Add struct xmp tag type support
5
6 Adds support for writing the xmp struct tag type, it is a compound tag
7 that has inner tags.
8 ---
9  gst-libs/gst/tag/gstxmptag.c |  357 +++++++++++++++++++++++-------------------
10  1 files changed, 195 insertions(+), 162 deletions(-)
11
12 diff --git a/gst-libs/gst/tag/gstxmptag.c b/gst-libs/gst/tag/gstxmptag.c
13 index b9fee8f..1a6e3c1 100644
14 --- a/gst-libs/gst/tag/gstxmptag.c
15 +++ b/gst-libs/gst/tag/gstxmptag.c
16 @@ -112,14 +112,31 @@ xmp_serialization_data_use_schema (XmpSerializationData * serdata,
17    return FALSE;
18  }
19  
20 +typedef enum
21 +{
22 +  GstXmpTagTypeSimple = 0,
23 +  GstXmpTagTypeBag,
24 +  GstXmpTagTypeSeq,
25 +  GstXmpTagTypeStruct,
26 +
27 +  /* Not really a xmp type, this is a tag that in gst is represented with
28 +   * a single value and on xmp it needs 2 (or more) simple values
29 +   *
30 +   * e.g. GST_TAG_GEO_LOCATION_ELEVATION needs to be mapped into 2 complementary
31 +   * tags in the exif's schema. One of them stores the absolute elevation,
32 +   * and the other one stores if it is above of below sea level.
33 +   */
34 +  GstXmpTagTypeCompound
35 +} GstXmpTagType;
36  
37 -#define GST_XMP_TAG_TYPE_SIMPLE 0
38 -#define GST_XMP_TAG_TYPE_BAG    1
39 -#define GST_XMP_TAG_TYPE_SEQ    2
40  struct _XmpTag
41  {
42 +  const gchar *gst_tag;
43    const gchar *tag_name;
44 -  gint type;
45 +  GstXmpTagType type;
46 +
47 +  /* Used for struct and compound types */
48 +  GSList *children;
49  
50    XmpSerializationFunc serialize;
51    XmpDeserializationFunc deserialize;
52 @@ -129,10 +146,10 @@ static GstTagMergeMode
53  xmp_tag_get_merge_mode (XmpTag * xmptag)
54  {
55    switch (xmptag->type) {
56 -    case GST_XMP_TAG_TYPE_BAG:
57 -    case GST_XMP_TAG_TYPE_SEQ:
58 +    case GstXmpTagTypeBag:
59 +    case GstXmpTagTypeSeq:
60        return GST_TAG_MERGE_APPEND;
61 -    case GST_XMP_TAG_TYPE_SIMPLE:
62 +    case GstXmpTagTypeSimple:
63      default:
64        return GST_TAG_MERGE_KEEP;
65    }
66 @@ -142,11 +159,11 @@ static const gchar *
67  xmp_tag_get_type_name (XmpTag * xmptag)
68  {
69    switch (xmptag->type) {
70 -    case GST_XMP_TAG_TYPE_SEQ:
71 +    case GstXmpTagTypeSeq:
72        return "rdf:Seq";
73      default:
74        g_assert_not_reached ();
75 -    case GST_XMP_TAG_TYPE_BAG:
76 +    case GstXmpTagTypeBag:
77        return "rdf:Bag";
78    }
79  }
80 @@ -159,14 +176,9 @@ struct _PendingXmpTag
81  };
82  typedef struct _PendingXmpTag PendingXmpTag;
83  
84 -
85  /*
86   * A schema is a mapping of strings (the tag name in gstreamer) to a list of
87 - * tags in xmp (XmpTag). We need a list because some tags are split into 2
88 - * when serialized into xmp.
89 - * e.g. GST_TAG_GEO_LOCATION_ELEVATION needs to be mapped into 2 complementary
90 - * tags in the exif's schema. One of them stores the absolute elevation,
91 - * and the other one stores if it is above of below sea level.
92 + * tags in xmp (XmpTag).
93   */
94  typedef GHashTable GstXmpSchema;
95  #define gst_xmp_schema_lookup g_hash_table_lookup
96 @@ -214,40 +226,70 @@ _gst_xmp_add_schema (const gchar * name, GstXmpSchema * schema)
97  }
98  
99  static void
100 -_gst_xmp_schema_add_mapping (GstXmpSchema * schema, const gchar * gst_tag,
101 -    GPtrArray * array)
102 +_gst_xmp_schema_add_mapping (GstXmpSchema * schema, XmpTag * tag)
103  {
104    GQuark key;
105  
106 -  key = g_quark_from_string (gst_tag);
107 +  key = g_quark_from_string (tag->gst_tag);
108  
109    if (gst_xmp_schema_lookup (schema, GUINT_TO_POINTER (key))) {
110 -    GST_WARNING ("Tag %s already present for the schema", gst_tag);
111 +    GST_WARNING ("Tag %s already present for the schema", tag->gst_tag);
112      g_assert_not_reached ();
113      return;
114    }
115 -  gst_xmp_schema_insert (schema, GUINT_TO_POINTER (key), array);
116 +  gst_xmp_schema_insert (schema, GUINT_TO_POINTER (key), tag);
117  }
118  
119 -static void
120 -_gst_xmp_schema_add_simple_mapping (GstXmpSchema * schema,
121 -    const gchar * gst_tag, const gchar * xmp_tag, gint xmp_type,
122 -    XmpSerializationFunc serialization_func,
123 +static XmpTag *
124 +gst_xmp_tag_create (const gchar * gst_tag, const gchar * xmp_tag,
125 +    gint xmp_type, XmpSerializationFunc serialization_func,
126      XmpDeserializationFunc deserialization_func)
127  {
128    XmpTag *xmpinfo;
129 -  GPtrArray *array;
130  
131    xmpinfo = g_slice_new (XmpTag);
132 +  xmpinfo->gst_tag = gst_tag;
133    xmpinfo->tag_name = xmp_tag;
134    xmpinfo->type = xmp_type;
135    xmpinfo->serialize = serialization_func;
136    xmpinfo->deserialize = deserialization_func;
137 +  xmpinfo->children = NULL;
138  
139 -  array = g_ptr_array_sized_new (1);
140 -  g_ptr_array_add (array, xmpinfo);
141 +  return xmpinfo;
142 +}
143  
144 -  _gst_xmp_schema_add_mapping (schema, gst_tag, array);
145 +static XmpTag *
146 +gst_xmp_tag_create_compound (const gchar * gst_tag, const gchar * xmp_tag_a,
147 +    const gchar * xmp_tag_b, XmpSerializationFunc serialization_func_a,
148 +    XmpSerializationFunc serialization_func_b,
149 +    XmpDeserializationFunc deserialization_func)
150 +{
151 +  XmpTag *xmptag;
152 +  XmpTag *xmptag_a =
153 +      gst_xmp_tag_create (gst_tag, xmp_tag_a, GstXmpTagTypeSimple,
154 +      serialization_func_a, deserialization_func);
155 +  XmpTag *xmptag_b =
156 +      gst_xmp_tag_create (gst_tag, xmp_tag_b, GstXmpTagTypeSimple,
157 +      serialization_func_b, deserialization_func);
158 +
159 +  xmptag =
160 +      gst_xmp_tag_create (gst_tag, NULL, GstXmpTagTypeCompound, NULL, NULL);
161 +
162 +  xmptag->children = g_slist_prepend (xmptag->children, xmptag_b);
163 +  xmptag->children = g_slist_prepend (xmptag->children, xmptag_a);
164 +
165 +  return xmptag;
166 +}
167 +
168 +static void
169 +_gst_xmp_schema_add_simple_mapping (GstXmpSchema * schema,
170 +    const gchar * gst_tag, const gchar * xmp_tag, gint xmp_type,
171 +    XmpSerializationFunc serialization_func,
172 +    XmpDeserializationFunc deserialization_func)
173 +{
174 +  _gst_xmp_schema_add_mapping (schema,
175 +      gst_xmp_tag_create (gst_tag, xmp_tag, xmp_type, serialization_func,
176 +          deserialization_func));
177  }
178  
179  /*
180 @@ -286,22 +328,30 @@ _gst_xmp_schema_get_mapping_reverse (GstXmpSchema * schema,
181    GHashTableIter iter;
182    gpointer key, value;
183    const gchar *ret = NULL;
184 -  gint index;
185  
186    /* Iterate over the hashtable */
187    g_hash_table_iter_init (&iter, schema);
188    while (!ret && g_hash_table_iter_next (&iter, &key, &value)) {
189 -    GPtrArray *array = (GPtrArray *) value;
190 -
191 -    /* each mapping might contain complementary tags */
192 -    for (index = 0; index < array->len; index++) {
193 -      XmpTag *xmpinfo = (XmpTag *) g_ptr_array_index (array, index);
194 +    XmpTag *xmpinfo = (XmpTag *) value;
195  
196 +    if (xmpinfo->tag_name) {
197        if (strcmp (xmpinfo->tag_name, xmp_tag) == 0) {
198          *_xmp_tag = xmpinfo;
199          ret = g_quark_to_string (GPOINTER_TO_UINT (key));
200          goto out;
201        }
202 +    } else if (xmpinfo->children) {
203 +      GSList *iter;
204 +      for (iter = xmpinfo->children; iter; iter = g_slist_next (iter)) {
205 +        XmpTag *child = iter->data;
206 +        if (strcmp (child->tag_name, xmp_tag) == 0) {
207 +          *_xmp_tag = child;
208 +          ret = g_quark_to_string (GPOINTER_TO_UINT (key));
209 +          goto out;
210 +        }
211 +      }
212 +    } else {
213 +      g_assert_not_reached ();
214      }
215    }
216  
217 @@ -856,7 +906,6 @@ deserialize_tiff_orientation (XmpTag * xmptag, GstTagList * taglist,
218  static gpointer
219  _init_xmp_tag_map (gpointer user_data)
220  {
221 -  GPtrArray *array;
222    XmpTag *xmpinfo;
223    GstXmpSchema *schema;
224  
225 @@ -868,136 +917,95 @@ _init_xmp_tag_map (gpointer user_data)
226     */
227    schema = gst_xmp_schema_new ();
228    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_ARTIST,
229 -      "dc:creator", GST_XMP_TAG_TYPE_SEQ, NULL, NULL);
230 +      "dc:creator", GstXmpTagTypeSeq, NULL, NULL);
231    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_COPYRIGHT,
232 -      "dc:rights", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
233 +      "dc:rights", GstXmpTagTypeSimple, NULL, NULL);
234    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DATE, "dc:date",
235 -      GST_XMP_TAG_TYPE_SEQ, NULL, NULL);
236 +      GstXmpTagTypeSeq, NULL, NULL);
237    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DESCRIPTION,
238 -      "dc:description", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
239 +      "dc:description", GstXmpTagTypeSimple, NULL, NULL);
240    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_KEYWORDS,
241 -      "dc:subject", GST_XMP_TAG_TYPE_BAG, NULL, NULL);
242 +      "dc:subject", GstXmpTagTypeBag, NULL, NULL);
243    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_TITLE, "dc:title",
244 -      GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
245 +      GstXmpTagTypeSimple, NULL, NULL);
246    /* FIXME: we probably want GST_TAG_{,AUDIO_,VIDEO_}MIME_TYPE */
247    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_VIDEO_CODEC,
248 -      "dc:format", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
249 +      "dc:format", GstXmpTagTypeSimple, NULL, NULL);
250    _gst_xmp_add_schema ("dc", schema);
251  
252    /* xap (xmp) schema */
253    schema = gst_xmp_schema_new ();
254    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_USER_RATING,
255 -      "xmp:Rating", GST_XMP_TAG_TYPE_SIMPLE, NULL, deserialize_xmp_rating);
256 +      "xmp:Rating", GstXmpTagTypeSimple, NULL, deserialize_xmp_rating);
257    _gst_xmp_add_schema ("xap", schema);
258  
259    /* tiff */
260    schema = gst_xmp_schema_new ();
261    _gst_xmp_schema_add_simple_mapping (schema,
262 -      GST_TAG_DEVICE_MANUFACTURER, "tiff:Make", GST_XMP_TAG_TYPE_SIMPLE, NULL,
263 +      GST_TAG_DEVICE_MANUFACTURER, "tiff:Make", GstXmpTagTypeSimple, NULL,
264        NULL);
265    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DEVICE_MODEL,
266 -      "tiff:Model", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
267 +      "tiff:Model", GstXmpTagTypeSimple, NULL, NULL);
268    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_APPLICATION_NAME,
269 -      "tiff:Software", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
270 +      "tiff:Software", GstXmpTagTypeSimple, NULL, NULL);
271    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_IMAGE_ORIENTATION,
272 -      "tiff:Orientation", GST_XMP_TAG_TYPE_SIMPLE, serialize_tiff_orientation,
273 +      "tiff:Orientation", GstXmpTagTypeSimple, serialize_tiff_orientation,
274        deserialize_tiff_orientation);
275    _gst_xmp_add_schema ("tiff", schema);
276  
277    /* exif schema */
278    schema = gst_xmp_schema_new ();
279    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DATE_TIME,
280 -      "exif:DateTimeOriginal", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
281 +      "exif:DateTimeOriginal", GstXmpTagTypeSimple, NULL, NULL);
282    _gst_xmp_schema_add_simple_mapping (schema,
283        GST_TAG_GEO_LOCATION_LATITUDE, "exif:GPSLatitude",
284 -      GST_XMP_TAG_TYPE_SIMPLE, serialize_exif_latitude,
285 -      deserialize_exif_latitude);
286 +      GstXmpTagTypeSimple, serialize_exif_latitude, deserialize_exif_latitude);
287    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_GEO_LOCATION_LONGITUDE,
288 -      "exif:GPSLongitude", GST_XMP_TAG_TYPE_SIMPLE, serialize_exif_longitude,
289 +      "exif:GPSLongitude", GstXmpTagTypeSimple, serialize_exif_longitude,
290        deserialize_exif_longitude);
291    _gst_xmp_schema_add_simple_mapping (schema,
292        GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, "exif:ExposureBiasValue",
293 -      GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
294 +      GstXmpTagTypeSimple, NULL, NULL);
295  
296    /* compound exif tags */
297 -  array = g_ptr_array_sized_new (2);
298 -  xmpinfo = g_slice_new (XmpTag);
299 -  xmpinfo->tag_name = "exif:GPSAltitude";
300 -  xmpinfo->serialize = serialize_exif_altitude;
301 -  xmpinfo->deserialize = deserialize_exif_altitude;
302 -  xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
303 -  g_ptr_array_add (array, xmpinfo);
304 -  xmpinfo = g_slice_new (XmpTag);
305 -  xmpinfo->tag_name = "exif:GPSAltitudeRef";
306 -  xmpinfo->serialize = serialize_exif_altituderef;
307 -  xmpinfo->deserialize = deserialize_exif_altitude;
308 -  xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
309 -  g_ptr_array_add (array, xmpinfo);
310 -  _gst_xmp_schema_add_mapping (schema, GST_TAG_GEO_LOCATION_ELEVATION, array);
311 -
312 -  array = g_ptr_array_sized_new (2);
313 -  xmpinfo = g_slice_new (XmpTag);
314 -  xmpinfo->tag_name = "exif:GPSSpeed";
315 -  xmpinfo->serialize = serialize_exif_gps_speed;
316 -  xmpinfo->deserialize = deserialize_exif_gps_speed;
317 -  xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
318 -  g_ptr_array_add (array, xmpinfo);
319 -  xmpinfo = g_slice_new (XmpTag);
320 -  xmpinfo->tag_name = "exif:GPSSpeedRef";
321 -  xmpinfo->serialize = serialize_exif_gps_speedref;
322 -  xmpinfo->deserialize = deserialize_exif_gps_speed;
323 -  xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
324 -  g_ptr_array_add (array, xmpinfo);
325 -  _gst_xmp_schema_add_mapping (schema,
326 -      GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, array);
327 -
328 -  array = g_ptr_array_sized_new (2);
329 -  xmpinfo = g_slice_new (XmpTag);
330 -  xmpinfo->tag_name = "exif:GPSTrack";
331 -  xmpinfo->serialize = serialize_exif_gps_direction;
332 -  xmpinfo->deserialize = deserialize_exif_gps_track;
333 -  xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
334 -  g_ptr_array_add (array, xmpinfo);
335 -  xmpinfo = g_slice_new (XmpTag);
336 -  xmpinfo->tag_name = "exif:GPSTrackRef";
337 -  xmpinfo->serialize = serialize_exif_gps_directionref;
338 -  xmpinfo->deserialize = deserialize_exif_gps_track;
339 -  xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
340 -  g_ptr_array_add (array, xmpinfo);
341 -  _gst_xmp_schema_add_mapping (schema,
342 -      GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, array);
343 +  xmpinfo = gst_xmp_tag_create_compound (GST_TAG_GEO_LOCATION_ELEVATION,
344 +      "exif:GPSAltitude", "exif:GPSAltitudeRef", serialize_exif_altitude,
345 +      serialize_exif_altituderef, deserialize_exif_altitude);
346 +  _gst_xmp_schema_add_mapping (schema, xmpinfo);
347 +
348 +  xmpinfo = gst_xmp_tag_create_compound (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED,
349 +      "exif:GPSSpeed", "exif:GPSSpeedRef", serialize_exif_gps_speed,
350 +      serialize_exif_gps_speedref, deserialize_exif_gps_speed);
351 +  _gst_xmp_schema_add_mapping (schema, xmpinfo);
352 +
353 +  xmpinfo =
354 +      gst_xmp_tag_create_compound (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION,
355 +      "exif:GPSTrack", "exif:GPSTrackRef", serialize_exif_gps_direction,
356 +      serialize_exif_gps_directionref, deserialize_exif_gps_track);
357 +  _gst_xmp_schema_add_mapping (schema, xmpinfo);
358 +
359 +  xmpinfo = gst_xmp_tag_create_compound (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION,
360 +      "exif:GPSImgDirection", "exif:GPSImgDirectionRef",
361 +      serialize_exif_gps_direction, serialize_exif_gps_directionref,
362 +      deserialize_exif_gps_img_direction);
363 +  _gst_xmp_schema_add_mapping (schema, xmpinfo);
364  
365 -  array = g_ptr_array_sized_new (2);
366 -  xmpinfo = g_slice_new (XmpTag);
367 -  xmpinfo->tag_name = "exif:GPSImgDirection";
368 -  xmpinfo->serialize = serialize_exif_gps_direction;
369 -  xmpinfo->deserialize = deserialize_exif_gps_img_direction;
370 -  xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
371 -  g_ptr_array_add (array, xmpinfo);
372 -  xmpinfo = g_slice_new (XmpTag);
373 -  xmpinfo->tag_name = "exif:GPSImgDirectionRef";
374 -  xmpinfo->serialize = serialize_exif_gps_directionref;
375 -  xmpinfo->deserialize = deserialize_exif_gps_img_direction;
376 -  xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
377 -  g_ptr_array_add (array, xmpinfo);
378 -  _gst_xmp_schema_add_mapping (schema,
379 -      GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, array);
380    _gst_xmp_add_schema ("exif", schema);
381  
382    /* photoshop schema */
383    schema = gst_xmp_schema_new ();
384    _gst_xmp_schema_add_simple_mapping (schema,
385        GST_TAG_GEO_LOCATION_COUNTRY, "photoshop:Country",
386 -      GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
387 +      GstXmpTagTypeSimple, NULL, NULL);
388    _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_GEO_LOCATION_CITY,
389 -      "photoshop:City", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
390 +      "photoshop:City", GstXmpTagTypeSimple, NULL, NULL);
391    _gst_xmp_add_schema ("photoshop", schema);
392  
393    /* iptc4xmpcore schema */
394    schema = gst_xmp_schema_new ();
395    _gst_xmp_schema_add_simple_mapping (schema,
396        GST_TAG_GEO_LOCATION_SUBLOCATION, "Iptc4xmpCore:Location",
397 -      GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
398 +      GstXmpTagTypeSimple, NULL, NULL);
399    _gst_xmp_add_schema ("Iptc4xmpCore", schema);
400  
401    return NULL;
402 @@ -1540,62 +1548,93 @@ gst_value_serialize_xmp (const GValue * value)
403  }
404  
405  static void
406 -write_one_tag (const GstTagList * list, const gchar * tag,
407 -    GPtrArray * xmp_tag_array, gpointer user_data)
408 +write_one_tag (const GstTagList * list, XmpTag * xmp_tag, gpointer user_data)
409  {
410 -  guint i = 0, ct = gst_tag_list_get_tag_size (list, tag), tag_index;
411 +  guint i = 0, ct;
412    XmpSerializationData *serialization_data = user_data;
413    GString *data = serialization_data->data;
414    char *s;
415  
416 -  for (tag_index = 0; tag_index < xmp_tag_array->len; tag_index++) {
417 -    XmpTag *xmp_tag;
418 +  /* struct type handled differently */
419 +  if (xmp_tag->type == GstXmpTagTypeStruct ||
420 +      xmp_tag->type == GstXmpTagTypeCompound) {
421 +    GSList *iter;
422 +    gboolean use_it = FALSE;
423 +
424 +    /* check if any of the inner tags are present on the taglist */
425 +    for (iter = xmp_tag->children; iter && !use_it; iter = g_slist_next (iter)) {
426 +      XmpTag *child_tag = iter->data;
427  
428 -    xmp_tag = g_ptr_array_index (xmp_tag_array, tag_index);
429 -    string_open_tag (data, xmp_tag->tag_name);
430 +      if (gst_tag_list_get_value_index (list, child_tag->gst_tag, 0) != NULL) {
431 +        use_it = TRUE;
432 +        break;
433 +      }
434 +    }
435  
436 -    /* fast path for single valued tag */
437 -    if (ct == 1 || xmp_tag->type == GST_XMP_TAG_TYPE_SIMPLE) {
438 +    if (use_it) {
439 +      if (xmp_tag->tag_name)
440 +        string_open_tag (data, xmp_tag->tag_name);
441 +      /* now write it */
442 +      for (iter = xmp_tag->children; iter; iter = g_slist_next (iter)) {
443 +        write_one_tag (list, iter->data, user_data);
444 +      }
445 +      if (xmp_tag->tag_name)
446 +        string_close_tag (data, xmp_tag->tag_name);
447 +    }
448 +    return;
449 +  }
450 +
451 +  /* at this point we must have a gst_tag */
452 +  g_assert (xmp_tag->gst_tag);
453 +  if (gst_tag_list_get_value_index (list, xmp_tag->gst_tag, 0) == NULL)
454 +    return;
455 +
456 +  ct = gst_tag_list_get_tag_size (list, xmp_tag->gst_tag);
457 +  string_open_tag (data, xmp_tag->tag_name);
458 +
459 +  /* fast path for single valued tag */
460 +  if (ct == 1 || xmp_tag->type == GstXmpTagTypeSimple) {
461 +    if (xmp_tag->serialize) {
462 +      s = xmp_tag->serialize (gst_tag_list_get_value_index (list,
463 +              xmp_tag->gst_tag, 0));
464 +    } else {
465 +      s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list,
466 +              xmp_tag->gst_tag, 0));
467 +    }
468 +    if (s) {
469 +      g_string_append (data, s);
470 +      g_free (s);
471 +    } else {
472 +      GST_WARNING ("unhandled type for %s to xmp", xmp_tag->gst_tag);
473 +    }
474 +  } else {
475 +    const gchar *typename;
476 +
477 +    typename = xmp_tag_get_type_name (xmp_tag);
478 +
479 +    string_open_tag (data, typename);
480 +    for (i = 0; i < ct; i++) {
481 +      GST_DEBUG ("mapping %s[%u/%u] to xmp", xmp_tag->gst_tag, i, ct);
482        if (xmp_tag->serialize) {
483 -        s = xmp_tag->serialize (gst_tag_list_get_value_index (list, tag, 0));
484 +        s = xmp_tag->serialize (gst_tag_list_get_value_index (list,
485 +                xmp_tag->gst_tag, i));
486        } else {
487 -        s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list, tag,
488 -                0));
489 +        s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list,
490 +                xmp_tag->gst_tag, i));
491        }
492        if (s) {
493 +        string_open_tag (data, "rdf:li");
494          g_string_append (data, s);
495 +        string_close_tag (data, "rdf:li");
496          g_free (s);
497        } else {
498 -        GST_WARNING ("unhandled type for %s to xmp", tag);
499 -      }
500 -    } else {
501 -      const gchar *typename;
502 -
503 -      typename = xmp_tag_get_type_name (xmp_tag);
504 -
505 -      string_open_tag (data, typename);
506 -      for (i = 0; i < ct; i++) {
507 -        GST_DEBUG ("mapping %s[%u/%u] to xmp", tag, i, ct);
508 -        if (xmp_tag->serialize) {
509 -          s = xmp_tag->serialize (gst_tag_list_get_value_index (list, tag, i));
510 -        } else {
511 -          s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list, tag,
512 -                  i));
513 -        }
514 -        if (s) {
515 -          string_open_tag (data, "rdf:li");
516 -          g_string_append (data, s);
517 -          string_close_tag (data, "rdf:li");
518 -          g_free (s);
519 -        } else {
520 -          GST_WARNING ("unhandled type for %s to xmp", tag);
521 -        }
522 +        GST_WARNING ("unhandled type for %s to xmp", xmp_tag->gst_tag);
523        }
524 -      string_close_tag (data, typename);
525      }
526 -
527 -    string_close_tag (data, xmp_tag->tag_name);
528 +    string_close_tag (data, typename);
529    }
530 +
531 +  string_close_tag (data, xmp_tag->tag_name);
532  }
533  
534  /**
535 @@ -1652,7 +1691,6 @@ gst_tag_list_to_xmp_buffer_full (const GstTagList * list, gboolean read_only,
536      /* use all schemas */
537      schemas = gst_tag_xmp_list_schemas ();
538    }
539 -  i = 0;
540    for (i = 0; schemas[i] != NULL; i++) {
541      GstXmpSchema *schema = _gst_xmp_get_schema (schemas[i]);
542      GHashTableIter iter;
543 @@ -1664,12 +1702,7 @@ gst_tag_list_to_xmp_buffer_full (const GstTagList * list, gboolean read_only,
544      /* Iterate over the hashtable */
545      g_hash_table_iter_init (&iter, schema);
546      while (g_hash_table_iter_next (&iter, &key, &value)) {
547 -      const gchar *tag = g_quark_to_string (GPOINTER_TO_UINT (key));
548 -
549 -      if (gst_tag_list_get_value_index (list, tag, 0) != NULL) {
550 -        write_one_tag (list, tag, value, (gpointer) & serialization_data);
551 -      }
552 -
553 +      write_one_tag (list, value, (gpointer) & serialization_data);
554      }
555    }
556