Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / gst / mxf / mxfmetadata.c
1 /* GStreamer
2  * Copyright (C) 2008-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <gst/gst.h>
25 #include <string.h>
26
27 #include "mxftypes.h"
28 #include "mxfmetadata.h"
29 #include "mxfquark.h"
30
31 GST_DEBUG_CATEGORY_EXTERN (mxf_debug);
32 #define GST_CAT_DEFAULT mxf_debug
33
34 G_DEFINE_ABSTRACT_TYPE (MXFMetadataBase, mxf_metadata_base, G_TYPE_OBJECT);
35
36 static void
37 mxf_metadata_base_finalize (GObject * object)
38 {
39   MXFMetadataBase *self = MXF_METADATA_BASE (object);
40
41   if (self->other_tags) {
42     g_hash_table_destroy (self->other_tags);
43     self->other_tags = NULL;
44   }
45
46   G_OBJECT_CLASS (mxf_metadata_base_parent_class)->finalize (object);
47 }
48
49 static gboolean
50 mxf_metadata_base_handle_tag (MXFMetadataBase * self, MXFPrimerPack * primer,
51     guint16 tag, const guint8 * tag_data, guint tag_size)
52 {
53   return (mxf_local_tag_add_to_hash_table (primer, tag, tag_data, tag_size,
54           &self->other_tags));
55 }
56
57 static gboolean
58 mxf_metadata_base_resolve_default (MXFMetadataBase * self,
59     GHashTable * metadata)
60 {
61   return TRUE;
62 }
63
64 static GstStructure *
65 mxf_metadata_base_to_structure_default (MXFMetadataBase * self)
66 {
67   MXFMetadataBaseClass *klass = MXF_METADATA_BASE_GET_CLASS (self);
68   GstStructure *ret;
69   gchar str[48];
70
71   g_return_val_if_fail (klass->name_quark != 0, NULL);
72
73   ret = gst_structure_id_empty_new (klass->name_quark);
74
75   if (!mxf_uuid_is_zero (&self->instance_uid)) {
76     mxf_uuid_to_string (&self->instance_uid, str);
77     gst_structure_id_set (ret, MXF_QUARK (INSTANCE_UID), G_TYPE_STRING, str,
78         NULL);
79   }
80
81   if (!mxf_uuid_is_zero (&self->generation_uid)) {
82     mxf_uuid_to_string (&self->generation_uid, str);
83     gst_structure_id_set (ret, MXF_QUARK (GENERATION_UID), G_TYPE_STRING, str,
84         NULL);
85   }
86
87   if (self->other_tags) {
88     MXFLocalTag *tag;
89     GValue va = { 0, };
90     GValue v = { 0, };
91     GstStructure *s;
92     GstBuffer *buf;
93     GHashTableIter iter;
94
95     g_hash_table_iter_init (&iter, self->other_tags);
96     g_value_init (&va, GST_TYPE_ARRAY);
97
98     while (g_hash_table_iter_next (&iter, NULL, (gpointer) & tag)) {
99       g_value_init (&v, GST_TYPE_STRUCTURE);
100       s = gst_structure_id_empty_new (MXF_QUARK (TAG));
101
102       mxf_ul_to_string (&tag->ul, str);
103
104       buf = gst_buffer_new_and_alloc (tag->size);
105       memcpy (GST_BUFFER_DATA (buf), tag->data, tag->size);
106
107       gst_structure_id_set (s, MXF_QUARK (NAME), G_TYPE_STRING, str,
108           MXF_QUARK (DATA), GST_TYPE_BUFFER, buf, NULL);
109
110       gst_value_set_structure (&v, s);
111       gst_structure_free (s);
112       gst_buffer_unref (buf);
113       gst_value_array_append_value (&va, &v);
114       g_value_unset (&v);
115     }
116
117     gst_structure_id_set_value (ret, MXF_QUARK (OTHER_TAGS), &va);
118     g_value_unset (&va);
119   }
120
121   return ret;
122 }
123
124 static void
125 mxf_metadata_base_init (MXFMetadataBase * self)
126 {
127
128 }
129
130 static void
131 mxf_metadata_base_class_init (MXFMetadataBaseClass * klass)
132 {
133   GObjectClass *object_class = (GObjectClass *) klass;
134
135   object_class->finalize = mxf_metadata_base_finalize;
136   klass->handle_tag = mxf_metadata_base_handle_tag;
137   klass->resolve = mxf_metadata_base_resolve_default;
138   klass->to_structure = mxf_metadata_base_to_structure_default;
139 }
140
141 gboolean
142 mxf_metadata_base_parse (MXFMetadataBase * self, MXFPrimerPack * primer,
143     const guint8 * data, guint size)
144 {
145   guint16 tag, tag_size;
146   const guint8 *tag_data;
147
148   g_return_val_if_fail (MXF_IS_METADATA_BASE (self), FALSE);
149   g_return_val_if_fail (data != NULL, FALSE);
150   g_return_val_if_fail (primer != NULL, FALSE);
151
152   while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
153     if (tag_size == 0 || tag == 0x0000)
154       goto next;
155
156     if (!MXF_METADATA_BASE_GET_CLASS (self)->handle_tag (self, primer, tag,
157             tag_data, tag_size))
158       return FALSE;
159   next:
160     data += 4 + tag_size;
161     size -= 4 + tag_size;
162   }
163
164   return TRUE;
165 }
166
167 gboolean
168 mxf_metadata_base_resolve (MXFMetadataBase * self, GHashTable * metadata)
169 {
170   MXFMetadataBaseClass *klass;
171   gboolean ret = TRUE;
172
173   g_return_val_if_fail (MXF_IS_METADATA_BASE (self), FALSE);
174   g_return_val_if_fail (metadata != NULL, FALSE);
175
176   if (self->resolved == MXF_METADATA_BASE_RESOLVE_STATE_SUCCESS)
177     return TRUE;
178   else if (self->resolved != MXF_METADATA_BASE_RESOLVE_STATE_NONE)
179     return FALSE;
180
181   self->resolved = MXF_METADATA_BASE_RESOLVE_STATE_RUNNING;
182
183   klass = MXF_METADATA_BASE_GET_CLASS (self);
184
185   if (klass->resolve)
186     ret = klass->resolve (self, metadata);
187
188   self->resolved =
189       (ret) ? MXF_METADATA_BASE_RESOLVE_STATE_SUCCESS :
190       MXF_METADATA_BASE_RESOLVE_STATE_FAILURE;
191
192   return ret;
193 }
194
195 GstStructure *
196 mxf_metadata_base_to_structure (MXFMetadataBase * self)
197 {
198   MXFMetadataBaseClass *klass;
199
200   g_return_val_if_fail (MXF_IS_METADATA_BASE (self), NULL);
201
202   g_return_val_if_fail (self->resolved ==
203       MXF_METADATA_BASE_RESOLVE_STATE_SUCCESS, NULL);
204
205   klass = MXF_METADATA_BASE_GET_CLASS (self);
206
207   if (klass->to_structure)
208     return klass->to_structure (self);
209
210   return NULL;
211 }
212
213 GstBuffer *
214 mxf_metadata_base_to_buffer (MXFMetadataBase * self, MXFPrimerPack * primer)
215 {
216   MXFMetadataBaseClass *klass;
217   GstBuffer *ret;
218   GList *tags, *l;
219   guint size = 0, slen;
220   guint8 ber[9];
221   MXFLocalTag *t, *last;
222   guint8 *data;
223
224   g_return_val_if_fail (MXF_IS_METADATA_BASE (self), NULL);
225   g_return_val_if_fail (primer != NULL, NULL);
226
227   klass = MXF_METADATA_BASE_GET_CLASS (self);
228   g_return_val_if_fail (klass->write_tags, NULL);
229
230   tags = klass->write_tags (self, primer);
231   g_return_val_if_fail (tags != NULL, NULL);
232
233   /* Add unknown tags */
234   if (self->other_tags) {
235     MXFLocalTag *tmp;
236     GHashTableIter iter;
237
238     g_hash_table_iter_init (&iter, self->other_tags);
239
240     while (g_hash_table_iter_next (&iter, NULL, (gpointer) & t)) {
241       tmp = g_slice_dup (MXFLocalTag, t);
242       if (t->g_slice) {
243         tmp->data = g_slice_alloc (t->size);
244         mxf_primer_pack_add_mapping (primer, 0x0000, &t->ul);
245         memcpy (tmp->data, t->data, t->size);
246       } else {
247         tmp->data = g_memdup (t->data, t->size);
248       }
249       tags = g_list_prepend (tags, tmp);
250     }
251   }
252
253   l = g_list_last (tags);
254   last = l->data;
255   tags = g_list_delete_link (tags, l);
256   /* Last element contains the metadata UL */
257   g_return_val_if_fail (last->size == 0, NULL);
258
259   for (l = tags; l; l = l->next) {
260     t = l->data;
261     g_assert (G_MAXUINT - t->size >= size);
262     size += 4 + t->size;
263   }
264
265   slen = mxf_ber_encode_size (size, ber);
266   size += 16 + slen;
267
268   ret = gst_buffer_new_and_alloc (size);
269
270   memcpy (GST_BUFFER_DATA (ret), &last->ul, 16);
271   mxf_local_tag_free (last);
272   last = NULL;
273   memcpy (GST_BUFFER_DATA (ret) + 16, ber, slen);
274
275   data = GST_BUFFER_DATA (ret) + 16 + slen;
276   size -= 16 + slen;
277
278   for (l = tags; l; l = l->next) {
279     guint16 local_tag;
280
281     g_assert (size >= 4);
282     t = l->data;
283
284     local_tag =
285         GPOINTER_TO_UINT (g_hash_table_lookup (primer->reverse_mappings,
286             &t->ul));
287     g_assert (local_tag != 0);
288
289     GST_WRITE_UINT16_BE (data, local_tag);
290     GST_WRITE_UINT16_BE (data + 2, t->size);
291     data += 4;
292     size -= 4;
293     g_assert (size >= t->size);
294
295     memcpy (data, t->data, t->size);
296     data += t->size;
297     size -= t->size;
298
299     mxf_local_tag_free (t);
300   }
301
302   g_list_free (tags);
303
304   return ret;
305 }
306
307 G_DEFINE_ABSTRACT_TYPE (MXFMetadata, mxf_metadata, MXF_TYPE_METADATA_BASE);
308
309 static gboolean
310 mxf_metadata_handle_tag (MXFMetadataBase * metadata, MXFPrimerPack * primer,
311     guint16 tag, const guint8 * tag_data, guint tag_size)
312 {
313 #ifndef GST_DISABLE_GST_DEBUG
314   gchar str[48];
315 #endif
316   MXFMetadata *self = MXF_METADATA (metadata);
317   gboolean ret = TRUE;
318
319   switch (tag) {
320     case 0x3c0a:
321       if (tag_size != 16)
322         goto error;
323       memcpy (&self->parent.instance_uid, tag_data, 16);
324       GST_DEBUG ("  instance uid = %s",
325           mxf_uuid_to_string (&self->parent.instance_uid, str));
326       break;
327     case 0x0102:
328       if (tag_size != 16)
329         goto error;
330       memcpy (&self->parent.generation_uid, tag_data, 16);
331       GST_DEBUG ("  generation uid = %s",
332           mxf_uuid_to_string (&self->parent.generation_uid, str));
333       break;
334     default:
335       ret =
336           MXF_METADATA_BASE_CLASS (mxf_metadata_parent_class)->handle_tag
337           (metadata, primer, tag, tag_data, tag_size);
338       break;
339   }
340
341   return ret;
342
343 error:
344
345   GST_ERROR ("Invalid metadata local tag 0x%04x of size %u", tag, tag_size);
346
347   return FALSE;
348 }
349
350 static GList *
351 mxf_metadata_write_tags (MXFMetadataBase * m, MXFPrimerPack * primer)
352 {
353   MXFMetadata *self = MXF_METADATA (m);
354   GList *ret = NULL;
355   MXFLocalTag *t;
356   MXFMetadataClass *klass;
357
358   g_return_val_if_fail (MXF_IS_METADATA (self), NULL);
359   klass = MXF_METADATA_GET_CLASS (self);
360
361   /* Last element contains the metadata key */
362   t = g_slice_new0 (MXFLocalTag);
363   memcpy (&t->ul, MXF_UL (METADATA), 16);
364   GST_WRITE_UINT16_BE (&t->ul.u[13], klass->type);
365   ret = g_list_prepend (ret, t);
366
367   t = g_slice_new0 (MXFLocalTag);
368   memcpy (&t->ul, MXF_UL (INSTANCE_UID), 16);
369   t->size = 16;
370   t->data = g_slice_alloc (16);
371   t->g_slice = TRUE;
372   memcpy (t->data, &self->parent.instance_uid, 16);
373   mxf_primer_pack_add_mapping (primer, 0x3c0a, &t->ul);
374   ret = g_list_prepend (ret, t);
375
376   if (!mxf_uuid_is_zero (&self->parent.generation_uid)) {
377     t = g_slice_new0 (MXFLocalTag);
378     memcpy (&t->ul, MXF_UL (GENERATION_UID), 16);
379     t->size = 16;
380     t->data = g_slice_alloc (16);
381     t->g_slice = TRUE;
382     memcpy (t->data, &self->parent.generation_uid, 16);
383     mxf_primer_pack_add_mapping (primer, 0x0102, &t->ul);
384     ret = g_list_prepend (ret, t);
385   }
386
387   return ret;
388 }
389
390 static void
391 mxf_metadata_class_init (MXFMetadataClass * klass)
392 {
393   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
394
395   metadata_base_class->handle_tag = mxf_metadata_handle_tag;
396   metadata_base_class->write_tags = mxf_metadata_write_tags;
397 }
398
399 static void
400 mxf_metadata_init (MXFMetadata * self)
401 {
402 }
403
404 static GArray *_mxf_metadata_registry = NULL;
405
406 #define _add_metadata_type(type) G_STMT_START { \
407   GType t = type; \
408   \
409   g_array_append_val (_mxf_metadata_registry, t); \
410 } G_STMT_END
411
412 void
413 mxf_metadata_init_types (void)
414 {
415   g_return_if_fail (_mxf_metadata_registry == NULL);
416
417   _mxf_metadata_registry = g_array_new (FALSE, TRUE, sizeof (GType));
418
419   _add_metadata_type (MXF_TYPE_METADATA_PREFACE);
420   _add_metadata_type (MXF_TYPE_METADATA_IDENTIFICATION);
421   _add_metadata_type (MXF_TYPE_METADATA_CONTENT_STORAGE);
422   _add_metadata_type (MXF_TYPE_METADATA_ESSENCE_CONTAINER_DATA);
423   _add_metadata_type (MXF_TYPE_METADATA_MATERIAL_PACKAGE);
424   _add_metadata_type (MXF_TYPE_METADATA_SOURCE_PACKAGE);
425   _add_metadata_type (MXF_TYPE_METADATA_TIMELINE_TRACK);
426   _add_metadata_type (MXF_TYPE_METADATA_EVENT_TRACK);
427   _add_metadata_type (MXF_TYPE_METADATA_STATIC_TRACK);
428   _add_metadata_type (MXF_TYPE_METADATA_SEQUENCE);
429   _add_metadata_type (MXF_TYPE_METADATA_SOURCE_CLIP);
430   _add_metadata_type (MXF_TYPE_METADATA_TIMECODE_COMPONENT);
431   _add_metadata_type (MXF_TYPE_METADATA_DM_SEGMENT);
432   _add_metadata_type (MXF_TYPE_METADATA_DM_SOURCE_CLIP);
433   _add_metadata_type (MXF_TYPE_METADATA_FILE_DESCRIPTOR);
434   _add_metadata_type (MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
435   _add_metadata_type (MXF_TYPE_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR);
436   _add_metadata_type (MXF_TYPE_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR);
437   _add_metadata_type (MXF_TYPE_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR);
438   _add_metadata_type (MXF_TYPE_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR);
439   _add_metadata_type (MXF_TYPE_METADATA_MULTIPLE_DESCRIPTOR);
440   _add_metadata_type (MXF_TYPE_METADATA_NETWORK_LOCATOR);
441   _add_metadata_type (MXF_TYPE_METADATA_TEXT_LOCATOR);
442 }
443
444 #undef _add_metadata_type
445
446 void
447 mxf_metadata_register (GType type)
448 {
449   g_return_if_fail (g_type_is_a (type, MXF_TYPE_METADATA));
450
451   g_array_append_val (_mxf_metadata_registry, type);
452 }
453
454 MXFMetadata *
455 mxf_metadata_new (guint16 type, MXFPrimerPack * primer, guint64 offset,
456     const guint8 * data, guint size)
457 {
458   guint i;
459   GType t = G_TYPE_INVALID;
460   MXFMetadata *ret = NULL;
461
462   g_return_val_if_fail (type != 0, NULL);
463   g_return_val_if_fail (primer != NULL, NULL);
464   g_return_val_if_fail (_mxf_metadata_registry != NULL, NULL);
465
466   for (i = 0; i < _mxf_metadata_registry->len; i++) {
467     GType tmp = g_array_index (_mxf_metadata_registry, GType, i);
468     MXFMetadataClass *klass = MXF_METADATA_CLASS (g_type_class_ref (tmp));
469
470     if (klass->type == type) {
471       g_type_class_unref (klass);
472       t = tmp;
473       break;
474     }
475     g_type_class_unref (klass);
476   }
477
478   if (t == G_TYPE_INVALID) {
479     GST_WARNING
480         ("No handler for type 0x%04x found -- using generic metadata parser",
481         type);
482     return NULL;
483   }
484
485
486   GST_DEBUG ("Metadata type 0x%06x is handled by type %s", type,
487       g_type_name (t));
488
489   ret = (MXFMetadata *) g_type_create_instance (t);
490   if (!mxf_metadata_base_parse (MXF_METADATA_BASE (ret), primer, data, size)) {
491     GST_ERROR ("Parsing metadata failed");
492     g_object_unref (ret);
493     return NULL;
494   }
495
496   ret->parent.offset = offset;
497   return ret;
498 }
499
500 G_DEFINE_TYPE (MXFMetadataPreface, mxf_metadata_preface, MXF_TYPE_METADATA);
501
502 static void
503 mxf_metadata_preface_finalize (GObject * object)
504 {
505   MXFMetadataPreface *self = MXF_METADATA_PREFACE (object);
506
507   g_free (self->identifications_uids);
508   self->identifications_uids = NULL;
509
510   g_free (self->identifications);
511   self->identifications = NULL;
512
513   g_free (self->essence_containers);
514   self->essence_containers = NULL;
515
516   g_free (self->dm_schemes);
517   self->dm_schemes = NULL;
518
519   G_OBJECT_CLASS (mxf_metadata_preface_parent_class)->finalize (object);
520 }
521
522 static gboolean
523 mxf_metadata_preface_handle_tag (MXFMetadataBase * metadata,
524     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
525     guint tag_size)
526 {
527   MXFMetadataPreface *self = MXF_METADATA_PREFACE (metadata);
528 #ifndef GST_DISABLE_GST_DEBUG
529   gchar str[48];
530 #endif
531   gboolean ret = TRUE;
532
533   switch (tag) {
534     case 0x3b02:
535       if (!mxf_timestamp_parse (&self->last_modified_date, tag_data, tag_size))
536         goto error;
537       GST_DEBUG ("  last modified date = %s",
538           mxf_timestamp_to_string (&self->last_modified_date, str));
539       break;
540     case 0x3b05:
541       if (tag_size != 2)
542         goto error;
543       self->version = GST_READ_UINT16_BE (tag_data);
544       GST_DEBUG ("  version = %u.%u", (self->version >> 8),
545           (self->version & 0x0f));
546       break;
547     case 0x3b07:
548       if (tag_size != 4)
549         goto error;
550       self->object_model_version = GST_READ_UINT32_BE (tag_data);
551       GST_DEBUG ("  object model version = %u", self->object_model_version);
552       break;
553     case 0x3b08:
554       if (tag_size != 16)
555         goto error;
556       memcpy (&self->primary_package_uid, tag_data, 16);
557       GST_DEBUG ("  primary package = %s",
558           mxf_uuid_to_string (&self->primary_package_uid, str));
559       break;
560     case 0x3b06:
561       if (!mxf_uuid_array_parse (&self->identifications_uids,
562               &self->n_identifications, tag_data, tag_size))
563         goto error;
564
565       GST_DEBUG ("  number of identifications = %u", self->n_identifications);
566 #ifndef GST_DISABLE_GST_DEBUG
567       {
568         guint i;
569         for (i = 0; i < self->n_identifications; i++) {
570           GST_DEBUG ("  identification %u = %s", i,
571               mxf_uuid_to_string (&self->identifications_uids[i], str));
572         }
573       }
574 #endif
575       break;
576     case 0x3b03:
577       if (tag_size != 16)
578         goto error;
579       memcpy (&self->content_storage_uid, tag_data, 16);
580       GST_DEBUG ("  content storage = %s",
581           mxf_uuid_to_string (&self->content_storage_uid, str));
582       break;
583     case 0x3b09:
584       if (tag_size != 16)
585         goto error;
586       memcpy (&self->operational_pattern, tag_data, 16);
587       GST_DEBUG ("  operational pattern = %s",
588           mxf_ul_to_string (&self->operational_pattern, str));
589       break;
590     case 0x3b0a:
591       if (!mxf_ul_array_parse (&self->essence_containers,
592               &self->n_essence_containers, tag_data, tag_size))
593         goto error;
594
595       GST_DEBUG ("  number of essence containers = %u",
596           self->n_essence_containers);
597 #ifndef GST_DISABLE_GST_DEBUG
598       {
599         guint i;
600         for (i = 0; i < self->n_essence_containers; i++) {
601           GST_DEBUG ("  essence container %u = %s", i,
602               mxf_ul_to_string (&self->essence_containers[i], str));
603         }
604       }
605 #endif
606       break;
607     case 0x3b0b:
608       if (!mxf_ul_array_parse (&self->dm_schemes, &self->n_dm_schemes, tag_data,
609               tag_size))
610         goto error;
611       GST_DEBUG ("  number of DM schemes = %u", self->n_dm_schemes);
612
613 #ifndef GST_DISABLE_GST_DEBUG
614       {
615         guint i;
616         for (i = 0; i < self->n_dm_schemes; i++) {
617           GST_DEBUG ("  DM schemes %u = %s", i,
618               mxf_ul_to_string (&self->dm_schemes[i], str));
619         }
620       }
621 #endif
622       break;
623     default:
624       ret =
625           MXF_METADATA_BASE_CLASS
626           (mxf_metadata_preface_parent_class)->handle_tag (metadata, primer,
627           tag, tag_data, tag_size);
628       break;
629   }
630
631   return ret;
632
633 error:
634
635   GST_ERROR ("Invalid preface local tag 0x%04x of size %u", tag, tag_size);
636
637   return FALSE;
638 }
639
640 static gboolean
641 mxf_metadata_preface_resolve (MXFMetadataBase * m, GHashTable * metadata)
642 {
643   MXFMetadataPreface *self = MXF_METADATA_PREFACE (m);
644   MXFMetadataBase *current = NULL;
645   guint i;
646
647   if (!mxf_uuid_is_zero (&self->primary_package_uid)) {
648     current = g_hash_table_lookup (metadata, &self->primary_package_uid);
649     if (!current || !MXF_IS_METADATA_GENERIC_PACKAGE (current)) {
650       GST_ERROR ("Primary package not found");
651     } else {
652       if (mxf_metadata_base_resolve (current, metadata)) {
653         self->primary_package = MXF_METADATA_GENERIC_PACKAGE (current);
654       }
655     }
656   }
657   current = NULL;
658
659   current = g_hash_table_lookup (metadata, &self->content_storage_uid);
660   if (!current || !MXF_IS_METADATA_CONTENT_STORAGE (current)) {
661     GST_ERROR ("Content storage not found");
662     return FALSE;
663   } else {
664     if (mxf_metadata_base_resolve (current, metadata)) {
665       self->content_storage = MXF_METADATA_CONTENT_STORAGE (current);
666     } else {
667       GST_ERROR ("Couldn't resolve content storage");
668       return FALSE;
669     }
670   }
671   current = NULL;
672
673   if (self->identifications)
674     memset (self->identifications, 0,
675         sizeof (gpointer) * self->n_identifications);
676   else
677     self->identifications =
678         g_new0 (MXFMetadataIdentification *, self->n_identifications);
679   for (i = 0; i < self->n_identifications; i++) {
680     current = g_hash_table_lookup (metadata, &self->identifications_uids[i]);
681     if (current && MXF_IS_METADATA_IDENTIFICATION (current)) {
682       if (mxf_metadata_base_resolve (current, metadata))
683         self->identifications[i] = MXF_METADATA_IDENTIFICATION (current);
684     }
685     current = NULL;
686   }
687
688   return
689       MXF_METADATA_BASE_CLASS (mxf_metadata_preface_parent_class)->resolve (m,
690       metadata);
691 }
692
693 static GstStructure *
694 mxf_metadata_preface_to_structure (MXFMetadataBase * m)
695 {
696   GstStructure *ret =
697       MXF_METADATA_BASE_CLASS (mxf_metadata_preface_parent_class)->to_structure
698       (m);
699   MXFMetadataPreface *self = MXF_METADATA_PREFACE (m);
700   gchar str[48];
701   guint i;
702
703   if (!mxf_timestamp_is_unknown (&self->last_modified_date)) {
704     mxf_timestamp_to_string (&self->last_modified_date, str);
705     gst_structure_id_set (ret, MXF_QUARK (LAST_MODIFIED_DATE), G_TYPE_STRING,
706         str, NULL);
707   }
708
709   if (self->version != 0)
710     gst_structure_id_set (ret, MXF_QUARK (VERSION), G_TYPE_UINT, self->version,
711         NULL);
712
713   if (self->object_model_version != 0)
714     gst_structure_id_set (ret, MXF_QUARK (OBJECT_MODEL_VERSION), G_TYPE_UINT,
715         self->object_model_version, NULL);
716
717   if (!mxf_uuid_is_zero (&self->primary_package_uid)) {
718     mxf_uuid_to_string (&self->primary_package_uid, str);
719     gst_structure_id_set (ret, MXF_QUARK (PRIMARY_PACKAGE), G_TYPE_STRING, str,
720         NULL);
721   }
722
723   if (self->n_identifications > 0) {
724     GValue arr = { 0, }
725     , val = {
726     0,};
727
728     g_value_init (&arr, GST_TYPE_ARRAY);
729
730     for (i = 0; i < self->n_identifications; i++) {
731       GstStructure *s;
732
733       if (self->identifications[i] == NULL)
734         continue;
735
736       g_value_init (&val, GST_TYPE_STRUCTURE);
737
738       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE
739           (self->identifications[i]));
740       gst_value_set_structure (&val, s);
741       gst_structure_free (s);
742       gst_value_array_append_value (&arr, &val);
743       g_value_unset (&val);
744     }
745
746     if (gst_value_array_get_size (&arr) > 0)
747       gst_structure_id_set_value (ret, MXF_QUARK (IDENTIFICATIONS), &arr);
748
749     g_value_unset (&arr);
750   }
751
752   if (self->content_storage) {
753     GstStructure *s =
754         mxf_metadata_base_to_structure (MXF_METADATA_BASE
755         (self->content_storage));
756     gst_structure_id_set (ret, MXF_QUARK (CONTENT_STORAGE), GST_TYPE_STRUCTURE,
757         s, NULL);
758     gst_structure_free (s);
759   }
760
761   if (!mxf_ul_is_zero (&self->operational_pattern)) {
762     mxf_ul_to_string (&self->operational_pattern, str);
763     gst_structure_id_set (ret, MXF_QUARK (OPERATIONAL_PATTERN), G_TYPE_STRING,
764         str, NULL);
765   }
766
767   if (self->n_essence_containers > 0) {
768     GValue arr = { 0, }
769     , val = {
770     0,};
771
772     g_value_init (&arr, GST_TYPE_ARRAY);
773
774     for (i = 0; i < self->n_essence_containers; i++) {
775       if (mxf_ul_is_zero (&self->essence_containers[i]))
776         continue;
777
778       g_value_init (&val, G_TYPE_STRING);
779
780       mxf_ul_to_string (&self->essence_containers[i], str);
781       g_value_set_string (&val, str);
782
783       gst_value_array_append_value (&arr, &val);
784       g_value_unset (&val);
785     }
786
787     if (gst_value_array_get_size (&arr) > 0)
788       gst_structure_id_set_value (ret, MXF_QUARK (ESSENCE_CONTAINERS), &arr);
789
790     g_value_unset (&arr);
791   }
792
793   if (self->n_dm_schemes > 0) {
794     GValue arr = { 0, }
795     , val = {
796     0,};
797
798     g_value_init (&arr, GST_TYPE_ARRAY);
799
800     for (i = 0; i < self->n_dm_schemes; i++) {
801       if (mxf_ul_is_zero (&self->dm_schemes[i]))
802         continue;
803
804       g_value_init (&val, G_TYPE_STRING);
805
806       mxf_ul_to_string (&self->dm_schemes[i], str);
807       g_value_set_string (&val, str);
808
809       gst_value_array_append_value (&arr, &val);
810       g_value_unset (&val);
811     }
812
813     if (gst_value_array_get_size (&arr) > 0)
814       gst_structure_id_set_value (ret, MXF_QUARK (DM_SCHEMES), &arr);
815
816     g_value_unset (&arr);
817   }
818
819   return ret;
820 }
821
822 static GList *
823 mxf_metadata_preface_write_tags (MXFMetadataBase * m, MXFPrimerPack * primer)
824 {
825   MXFMetadataPreface *self = MXF_METADATA_PREFACE (m);
826   GList *ret =
827       MXF_METADATA_BASE_CLASS (mxf_metadata_preface_parent_class)->write_tags
828       (m, primer);
829   MXFLocalTag *t;
830   guint i;
831
832   t = g_slice_new0 (MXFLocalTag);
833   memcpy (&t->ul, MXF_UL (LAST_MODIFIED_DATE), 16);
834   t->size = 8;
835   t->data = g_slice_alloc (8);
836   t->g_slice = TRUE;
837   mxf_timestamp_write (&self->last_modified_date, t->data);
838   mxf_primer_pack_add_mapping (primer, 0x3b02, &t->ul);
839   ret = g_list_prepend (ret, t);
840
841   t = g_slice_new0 (MXFLocalTag);
842   memcpy (&t->ul, MXF_UL (VERSION), 16);
843   t->size = 2;
844   t->data = g_slice_alloc (2);
845   t->g_slice = TRUE;
846   GST_WRITE_UINT16_BE (t->data, self->version);
847   mxf_primer_pack_add_mapping (primer, 0x3b05, &t->ul);
848   ret = g_list_prepend (ret, t);
849
850   if (self->object_model_version) {
851     t = g_slice_new0 (MXFLocalTag);
852     memcpy (&t->ul, MXF_UL (OBJECT_MODEL_VERSION), 16);
853     t->size = 4;
854     t->data = g_slice_alloc (4);
855     t->g_slice = TRUE;
856     GST_WRITE_UINT32_BE (t->data, self->object_model_version);
857     mxf_primer_pack_add_mapping (primer, 0x3b07, &t->ul);
858     ret = g_list_prepend (ret, t);
859   }
860
861   if (!mxf_uuid_is_zero (&self->primary_package_uid)) {
862     t = g_slice_new0 (MXFLocalTag);
863     memcpy (&t->ul, MXF_UL (PRIMARY_PACKAGE), 16);
864     t->size = 16;
865     t->data = g_slice_alloc (16);
866     t->g_slice = TRUE;
867     memcpy (t->data, &self->primary_package_uid, 16);
868     mxf_primer_pack_add_mapping (primer, 0x3b08, &t->ul);
869     ret = g_list_prepend (ret, t);
870   }
871
872   t = g_slice_new0 (MXFLocalTag);
873   memcpy (&t->ul, MXF_UL (IDENTIFICATIONS), 16);
874   t->size = 8 + 16 * self->n_identifications;
875   t->data = g_slice_alloc0 (t->size);
876   t->g_slice = TRUE;
877   mxf_primer_pack_add_mapping (primer, 0x3b06, &t->ul);
878   GST_WRITE_UINT32_BE (t->data, self->n_identifications);
879   GST_WRITE_UINT32_BE (t->data + 4, 16);
880   for (i = 0; i < self->n_identifications; i++) {
881     if (!self->identifications[i])
882       continue;
883
884     memcpy (t->data + 8 + 16 * i,
885         &MXF_METADATA_BASE (self->identifications[i])->instance_uid, 16);
886   }
887   ret = g_list_prepend (ret, t);
888
889   t = g_slice_new0 (MXFLocalTag);
890   memcpy (&t->ul, MXF_UL (CONTENT_STORAGE), 16);
891   t->size = 16;
892   t->data = g_slice_alloc (t->size);
893   t->g_slice = TRUE;
894   mxf_primer_pack_add_mapping (primer, 0x3b03, &t->ul);
895   memcpy (t->data, &MXF_METADATA_BASE (self->content_storage)->instance_uid,
896       16);
897   ret = g_list_prepend (ret, t);
898
899   t = g_slice_new0 (MXFLocalTag);
900   memcpy (&t->ul, MXF_UL (OPERATIONAL_PATTERN), 16);
901   t->size = 16;
902   t->data = g_slice_alloc (t->size);
903   t->g_slice = TRUE;
904   mxf_primer_pack_add_mapping (primer, 0x3b09, &t->ul);
905   memcpy (t->data, &self->operational_pattern, 16);
906   ret = g_list_prepend (ret, t);
907
908   t = g_slice_new0 (MXFLocalTag);
909   memcpy (&t->ul, MXF_UL (ESSENCE_CONTAINERS), 16);
910   t->size = 8 + 16 * self->n_essence_containers;
911   t->data = g_slice_alloc0 (t->size);
912   t->g_slice = TRUE;
913   mxf_primer_pack_add_mapping (primer, 0x3b0a, &t->ul);
914   GST_WRITE_UINT32_BE (t->data, self->n_essence_containers);
915   GST_WRITE_UINT32_BE (t->data + 4, 16);
916   for (i = 0; i < self->n_essence_containers; i++) {
917     memcpy (t->data + 8 + 16 * i, &self->essence_containers[i], 16);
918   }
919   ret = g_list_prepend (ret, t);
920
921   if (self->dm_schemes) {
922     t = g_slice_new0 (MXFLocalTag);
923     memcpy (&t->ul, MXF_UL (DM_SCHEMES), 16);
924     t->size = 8 + 16 * self->n_dm_schemes;
925     t->data = g_slice_alloc0 (t->size);
926     t->g_slice = TRUE;
927     mxf_primer_pack_add_mapping (primer, 0x3b0b, &t->ul);
928     GST_WRITE_UINT32_BE (t->data, self->n_dm_schemes);
929     GST_WRITE_UINT32_BE (t->data + 4, 16);
930     for (i = 0; i < self->n_dm_schemes; i++) {
931       memcpy (t->data + 8 + 16 * i, &self->dm_schemes[i], 16);
932     }
933     ret = g_list_prepend (ret, t);
934   }
935
936   return ret;
937 }
938
939 static void
940 mxf_metadata_preface_init (MXFMetadataPreface * self)
941 {
942
943 }
944
945 static void
946 mxf_metadata_preface_class_init (MXFMetadataPrefaceClass * klass)
947 {
948   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
949   GObjectClass *object_class = (GObjectClass *) klass;
950   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
951
952   object_class->finalize = mxf_metadata_preface_finalize;
953   metadata_base_class->handle_tag = mxf_metadata_preface_handle_tag;
954   metadata_base_class->resolve = mxf_metadata_preface_resolve;
955   metadata_base_class->to_structure = mxf_metadata_preface_to_structure;
956   metadata_base_class->write_tags = mxf_metadata_preface_write_tags;
957   metadata_base_class->name_quark = MXF_QUARK (PREFACE);
958   metadata_class->type = 0x012f;
959 }
960
961 G_DEFINE_TYPE (MXFMetadataIdentification, mxf_metadata_identification,
962     MXF_TYPE_METADATA);
963
964 static void
965 mxf_metadata_identification_finalize (GObject * object)
966 {
967   MXFMetadataIdentification *self = MXF_METADATA_IDENTIFICATION (object);
968
969   g_free (self->company_name);
970   self->company_name = NULL;
971
972   g_free (self->product_name);
973   self->product_name = NULL;
974
975   g_free (self->version_string);
976   self->version_string = NULL;
977
978   g_free (self->platform);
979   self->platform = NULL;
980
981   G_OBJECT_CLASS (mxf_metadata_identification_parent_class)->finalize (object);
982 }
983
984 static gboolean
985 mxf_metadata_identification_handle_tag (MXFMetadataBase * metadata,
986     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
987     guint tag_size)
988 {
989   MXFMetadataIdentification *self = MXF_METADATA_IDENTIFICATION (metadata);
990   gboolean ret = TRUE;
991 #ifndef GST_DISABLE_GST_DEBUG
992   gchar str[48];
993 #endif
994
995   switch (tag) {
996     case 0x3c09:
997       if (tag_size != 16)
998         goto error;
999       memcpy (&self->this_generation_uid, tag_data, 16);
1000       GST_DEBUG ("  this generation uid = %s",
1001           mxf_uuid_to_string (&self->this_generation_uid, str));
1002       break;
1003     case 0x3c01:
1004       self->company_name = mxf_utf16_to_utf8 (tag_data, tag_size);
1005       GST_DEBUG ("  company name = %s", GST_STR_NULL (self->company_name));
1006       break;
1007     case 0x3c02:
1008       self->product_name = mxf_utf16_to_utf8 (tag_data, tag_size);
1009       GST_DEBUG ("  product name = %s", GST_STR_NULL (self->product_name));
1010       break;
1011     case 0x3c03:
1012       if (!mxf_product_version_parse (&self->product_version,
1013               tag_data, tag_size))
1014         goto error;
1015       GST_DEBUG ("  product version = %u.%u.%u.%u.%u",
1016           self->product_version.major,
1017           self->product_version.minor,
1018           self->product_version.patch,
1019           self->product_version.build, self->product_version.release);
1020       break;
1021     case 0x3c04:
1022       self->version_string = mxf_utf16_to_utf8 (tag_data, tag_size);
1023       GST_DEBUG ("  version string = %s", GST_STR_NULL (self->version_string));
1024       break;
1025     case 0x3c05:
1026       if (tag_size != 16)
1027         goto error;
1028       memcpy (&self->product_uid, tag_data, 16);
1029       GST_DEBUG ("  product uid = %s",
1030           mxf_uuid_to_string (&self->product_uid, str));
1031       break;
1032     case 0x3c06:
1033       if (!mxf_timestamp_parse (&self->modification_date, tag_data, tag_size))
1034         goto error;
1035       GST_DEBUG ("  modification date = %s",
1036           mxf_timestamp_to_string (&self->modification_date, str));
1037       break;
1038     case 0x3c07:
1039       if (!mxf_product_version_parse (&self->toolkit_version,
1040               tag_data, tag_size))
1041         goto error;
1042       GST_DEBUG ("  toolkit version = %u.%u.%u.%u.%u",
1043           self->toolkit_version.major,
1044           self->toolkit_version.minor,
1045           self->toolkit_version.patch,
1046           self->toolkit_version.build, self->toolkit_version.release);
1047       break;
1048     case 0x3c08:
1049       self->platform = mxf_utf16_to_utf8 (tag_data, tag_size);
1050       GST_DEBUG ("  platform = %s", GST_STR_NULL (self->platform));
1051       break;
1052     default:
1053       ret =
1054           MXF_METADATA_BASE_CLASS
1055           (mxf_metadata_identification_parent_class)->handle_tag (metadata,
1056           primer, tag, tag_data, tag_size);
1057       break;
1058   }
1059
1060   return ret;
1061
1062 error:
1063   GST_ERROR ("Invalid identification local tag 0x%04x of size %u", tag,
1064       tag_size);
1065
1066   return FALSE;
1067 }
1068
1069 static GstStructure *
1070 mxf_metadata_identification_to_structure (MXFMetadataBase * m)
1071 {
1072   GstStructure *ret =
1073       MXF_METADATA_BASE_CLASS
1074       (mxf_metadata_identification_parent_class)->to_structure (m);
1075   MXFMetadataIdentification *self = MXF_METADATA_IDENTIFICATION (m);
1076   gchar str[48];
1077
1078   if (!mxf_uuid_is_zero (&self->this_generation_uid)) {
1079     mxf_uuid_to_string (&self->this_generation_uid, str);
1080     gst_structure_id_set (ret, MXF_QUARK (THIS_GENERATION_UID), G_TYPE_STRING,
1081         str, NULL);
1082   }
1083
1084   if (self->company_name)
1085     gst_structure_id_set (ret, MXF_QUARK (COMPANY_NAME), G_TYPE_STRING,
1086         self->company_name, NULL);
1087
1088   if (self->product_name)
1089     gst_structure_id_set (ret, MXF_QUARK (PRODUCT_NAME), G_TYPE_STRING,
1090         self->product_name, NULL);
1091
1092   if (self->product_version.major ||
1093       self->product_version.minor ||
1094       self->product_version.patch ||
1095       self->product_version.build || self->product_version.release) {
1096     g_snprintf (str, 48, "%u.%u.%u.%u.%u", self->product_version.major,
1097         self->product_version.minor,
1098         self->product_version.patch,
1099         self->product_version.build, self->product_version.release);
1100     gst_structure_id_set (ret, MXF_QUARK (PRODUCT_VERSION), G_TYPE_STRING, str,
1101         NULL);
1102   }
1103
1104   if (self->version_string)
1105     gst_structure_id_set (ret, MXF_QUARK (VERSION_STRING), G_TYPE_STRING,
1106         self->version_string, NULL);
1107
1108   if (!mxf_uuid_is_zero (&self->product_uid)) {
1109     mxf_uuid_to_string (&self->product_uid, str);
1110     gst_structure_id_set (ret, MXF_QUARK (PRODUCT_UID), G_TYPE_STRING, str,
1111         NULL);
1112   }
1113
1114   if (!mxf_timestamp_is_unknown (&self->modification_date)) {
1115     mxf_timestamp_to_string (&self->modification_date, str);
1116     gst_structure_id_set (ret, MXF_QUARK (MODIFICATION_DATE), G_TYPE_STRING,
1117         str, NULL);
1118   }
1119
1120   if (self->toolkit_version.major ||
1121       self->toolkit_version.minor ||
1122       self->toolkit_version.patch ||
1123       self->toolkit_version.build || self->toolkit_version.release) {
1124     g_snprintf (str, 48, "%u.%u.%u.%u.%u", self->toolkit_version.major,
1125         self->toolkit_version.minor,
1126         self->toolkit_version.patch,
1127         self->toolkit_version.build, self->toolkit_version.release);
1128     gst_structure_id_set (ret, MXF_QUARK (TOOLKIT_VERSION), G_TYPE_STRING, str,
1129         NULL);
1130   }
1131
1132   if (self->platform)
1133     gst_structure_id_set (ret, MXF_QUARK (PLATFORM), G_TYPE_STRING,
1134         self->platform, NULL);
1135
1136   return ret;
1137 }
1138
1139 static GList *
1140 mxf_metadata_identification_write_tags (MXFMetadataBase * m,
1141     MXFPrimerPack * primer)
1142 {
1143   MXFMetadataIdentification *self = MXF_METADATA_IDENTIFICATION (m);
1144   GList *ret =
1145       MXF_METADATA_BASE_CLASS
1146       (mxf_metadata_identification_parent_class)->write_tags (m, primer);
1147   MXFLocalTag *t;
1148
1149   if (self->company_name) {
1150     t = g_slice_new0 (MXFLocalTag);
1151     memcpy (&t->ul, MXF_UL (COMPANY_NAME), 16);
1152     t->data = mxf_utf8_to_utf16 (self->company_name, &t->size);
1153     mxf_primer_pack_add_mapping (primer, 0x3c01, &t->ul);
1154     ret = g_list_prepend (ret, t);
1155   }
1156
1157   if (self->product_name) {
1158     t = g_slice_new0 (MXFLocalTag);
1159     memcpy (&t->ul, MXF_UL (PRODUCT_NAME), 16);
1160     t->data = mxf_utf8_to_utf16 (self->product_name, &t->size);
1161     mxf_primer_pack_add_mapping (primer, 0x3c02, &t->ul);
1162     ret = g_list_prepend (ret, t);
1163   }
1164
1165   if (!mxf_product_version_is_valid (&self->product_version)) {
1166     t = g_slice_new0 (MXFLocalTag);
1167     memcpy (&t->ul, MXF_UL (PRODUCT_VERSION), 16);
1168     t->size = 10;
1169     t->data = g_slice_alloc (t->size);
1170     t->g_slice = TRUE;
1171     mxf_product_version_write (&self->product_version, t->data);
1172     mxf_primer_pack_add_mapping (primer, 0x3c03, &t->ul);
1173     ret = g_list_prepend (ret, t);
1174   }
1175
1176   if (self->version_string) {
1177     t = g_slice_new0 (MXFLocalTag);
1178     memcpy (&t->ul, MXF_UL (VERSION_STRING), 16);
1179     t->data = mxf_utf8_to_utf16 (self->version_string, &t->size);
1180     mxf_primer_pack_add_mapping (primer, 0x3c04, &t->ul);
1181     ret = g_list_prepend (ret, t);
1182   }
1183
1184   if (!mxf_uuid_is_zero (&self->product_uid)) {
1185     t = g_slice_new0 (MXFLocalTag);
1186     memcpy (&t->ul, MXF_UL (PRODUCT_UID), 16);
1187     t->size = 16;
1188     t->data = g_slice_alloc (t->size);
1189     t->g_slice = TRUE;
1190     memcpy (t->data, &self->product_uid, 16);
1191     mxf_primer_pack_add_mapping (primer, 0x3c05, &t->ul);
1192     ret = g_list_prepend (ret, t);
1193   }
1194
1195   if (!mxf_timestamp_is_unknown (&self->modification_date)) {
1196     t = g_slice_new0 (MXFLocalTag);
1197     memcpy (&t->ul, MXF_UL (MODIFICATION_DATE), 16);
1198     t->size = 8;
1199     t->data = g_slice_alloc (t->size);
1200     t->g_slice = TRUE;
1201     mxf_timestamp_write (&self->modification_date, t->data);
1202     mxf_primer_pack_add_mapping (primer, 0x3c06, &t->ul);
1203     ret = g_list_prepend (ret, t);
1204   }
1205
1206   if (!mxf_product_version_is_valid (&self->toolkit_version)) {
1207     t = g_slice_new0 (MXFLocalTag);
1208     memcpy (&t->ul, MXF_UL (TOOLKIT_VERSION), 16);
1209     t->size = 10;
1210     t->data = g_slice_alloc (t->size);
1211     t->g_slice = TRUE;
1212     mxf_product_version_write (&self->toolkit_version, t->data);
1213     mxf_primer_pack_add_mapping (primer, 0x3c07, &t->ul);
1214     ret = g_list_prepend (ret, t);
1215   }
1216
1217   if (self->platform) {
1218     t = g_slice_new0 (MXFLocalTag);
1219     memcpy (&t->ul, MXF_UL (PLATFORM), 16);
1220     t->data = mxf_utf8_to_utf16 (self->platform, &t->size);
1221     mxf_primer_pack_add_mapping (primer, 0x3c08, &t->ul);
1222     ret = g_list_prepend (ret, t);
1223   }
1224
1225   return ret;
1226 }
1227
1228 static void
1229 mxf_metadata_identification_init (MXFMetadataIdentification * self)
1230 {
1231
1232 }
1233
1234 static void
1235 mxf_metadata_identification_class_init (MXFMetadataIdentificationClass * klass)
1236 {
1237   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
1238   GObjectClass *object_class = (GObjectClass *) klass;
1239   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
1240
1241   object_class->finalize = mxf_metadata_identification_finalize;
1242   metadata_base_class->handle_tag = mxf_metadata_identification_handle_tag;
1243   metadata_base_class->name_quark = MXF_QUARK (IDENTIFICATION);
1244   metadata_base_class->to_structure = mxf_metadata_identification_to_structure;
1245   metadata_base_class->write_tags = mxf_metadata_identification_write_tags;
1246   metadata_class->type = 0x0130;
1247 }
1248
1249 G_DEFINE_TYPE (MXFMetadataContentStorage, mxf_metadata_content_storage,
1250     MXF_TYPE_METADATA);
1251
1252 static void
1253 mxf_metadata_content_storage_finalize (GObject * object)
1254 {
1255   MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (object);
1256
1257   g_free (self->packages);
1258   self->packages = NULL;
1259   g_free (self->packages_uids);
1260   self->packages_uids = NULL;
1261   g_free (self->essence_container_data);
1262   self->essence_container_data = NULL;
1263   g_free (self->essence_container_data_uids);
1264   self->essence_container_data_uids = NULL;
1265
1266   G_OBJECT_CLASS (mxf_metadata_content_storage_parent_class)->finalize (object);
1267 }
1268
1269 static gboolean
1270 mxf_metadata_content_storage_handle_tag (MXFMetadataBase * metadata,
1271     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
1272     guint tag_size)
1273 {
1274   MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (metadata);
1275   gboolean ret = TRUE;
1276 #ifndef GST_DISABLE_GST_DEBUG
1277   gchar str[48];
1278 #endif
1279
1280   switch (tag) {
1281     case 0x1901:
1282       if (!mxf_uuid_array_parse (&self->packages_uids, &self->n_packages,
1283               tag_data, tag_size))
1284         goto error;
1285       GST_DEBUG ("  number of packages = %u", self->n_packages);
1286 #ifndef GST_DISABLE_GST_DEBUG
1287       {
1288         guint i;
1289         for (i = 0; i < self->n_packages; i++) {
1290           GST_DEBUG ("  package %u = %s", i,
1291               mxf_uuid_to_string (&self->packages_uids[i], str));
1292         }
1293       }
1294 #endif
1295       break;
1296     case 0x1902:
1297       if (!mxf_uuid_array_parse (&self->essence_container_data_uids,
1298               &self->n_essence_container_data, tag_data, tag_size))
1299         goto error;
1300
1301       GST_DEBUG ("  number of essence container data = %u",
1302           self->n_essence_container_data);
1303 #ifndef GST_DISABLE_GST_DEBUG
1304       {
1305         guint i;
1306         for (i = 0; i < self->n_essence_container_data; i++) {
1307           GST_DEBUG ("  essence container data %u = %s", i,
1308               mxf_uuid_to_string (&self->essence_container_data_uids[i], str));
1309         }
1310       }
1311 #endif
1312       break;
1313     default:
1314       ret =
1315           MXF_METADATA_BASE_CLASS
1316           (mxf_metadata_content_storage_parent_class)->handle_tag (metadata,
1317           primer, tag, tag_data, tag_size);
1318       break;
1319   }
1320
1321   return ret;
1322
1323 error:
1324
1325   GST_ERROR ("Invalid content storage local tag 0x%04x of size %u", tag,
1326       tag_size);
1327
1328   return FALSE;
1329 }
1330
1331 static gboolean
1332 mxf_metadata_content_storage_resolve (MXFMetadataBase * m,
1333     GHashTable * metadata)
1334 {
1335   MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (m);
1336   MXFMetadataBase *current = NULL;
1337   guint i;
1338   gboolean have_package = FALSE;
1339   gboolean have_ecd = FALSE;
1340
1341   if (self->packages)
1342     memset (self->packages, 0, sizeof (gpointer) * self->n_packages);
1343   else
1344     self->packages = g_new0 (MXFMetadataGenericPackage *, self->n_packages);
1345
1346   for (i = 0; i < self->n_packages; i++) {
1347     current = g_hash_table_lookup (metadata, &self->packages_uids[i]);
1348     if (current && MXF_IS_METADATA_GENERIC_PACKAGE (current)) {
1349       if (mxf_metadata_base_resolve (current, metadata)) {
1350         self->packages[i] = MXF_METADATA_GENERIC_PACKAGE (current);
1351         have_package = TRUE;
1352       } else {
1353         GST_ERROR ("Couldn't resolve package");
1354       }
1355     } else {
1356       GST_ERROR ("Package not found");
1357     }
1358   }
1359
1360   if (self->essence_container_data)
1361     memset (self->essence_container_data, 0,
1362         sizeof (gpointer) * self->n_essence_container_data);
1363   else
1364     self->essence_container_data =
1365         g_new0 (MXFMetadataEssenceContainerData *,
1366         self->n_essence_container_data);
1367   for (i = 0; i < self->n_essence_container_data; i++) {
1368     current =
1369         g_hash_table_lookup (metadata, &self->essence_container_data_uids[i]);
1370     if (current && MXF_IS_METADATA_ESSENCE_CONTAINER_DATA (current)) {
1371       if (mxf_metadata_base_resolve (current, metadata)) {
1372         self->essence_container_data[i] =
1373             MXF_METADATA_ESSENCE_CONTAINER_DATA (current);
1374         have_ecd = TRUE;
1375       } else {
1376         GST_ERROR ("Couldn't resolve essence container data");
1377       }
1378     } else {
1379       GST_ERROR ("Essence container data not found");
1380     }
1381   }
1382
1383   if (!have_package) {
1384     GST_ERROR ("Couldn't resolve any package");
1385     return FALSE;
1386   } else if (!have_ecd) {
1387     GST_ERROR ("Couldn't resolve any essence container data");
1388     return FALSE;
1389   }
1390
1391   return
1392       MXF_METADATA_BASE_CLASS
1393       (mxf_metadata_content_storage_parent_class)->resolve (m, metadata);
1394 }
1395
1396 static GstStructure *
1397 mxf_metadata_content_storage_to_structure (MXFMetadataBase * m)
1398 {
1399   GstStructure *ret =
1400       MXF_METADATA_BASE_CLASS
1401       (mxf_metadata_content_storage_parent_class)->to_structure (m);
1402   MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (m);
1403   guint i;
1404
1405   if (self->n_packages > 0) {
1406     GValue arr = { 0, }
1407     , val = {
1408     0,};
1409
1410     g_value_init (&arr, GST_TYPE_ARRAY);
1411
1412     for (i = 0; i < self->n_packages; i++) {
1413       GstStructure *s;
1414
1415       if (self->packages[i] == NULL)
1416         continue;
1417
1418       g_value_init (&val, GST_TYPE_STRUCTURE);
1419
1420       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->packages
1421               [i]));
1422       gst_value_set_structure (&val, s);
1423       gst_structure_free (s);
1424       gst_value_array_append_value (&arr, &val);
1425       g_value_unset (&val);
1426     }
1427
1428     if (gst_value_array_get_size (&arr) > 0)
1429       gst_structure_id_set_value (ret, MXF_QUARK (PACKAGES), &arr);
1430
1431     g_value_unset (&arr);
1432   }
1433
1434   if (self->n_essence_container_data > 0) {
1435     GValue arr = { 0, }
1436     , val = {
1437     0,};
1438
1439     g_value_init (&arr, GST_TYPE_ARRAY);
1440
1441     for (i = 0; i < self->n_essence_container_data; i++) {
1442       GstStructure *s;
1443
1444       if (self->essence_container_data[i] == NULL)
1445         continue;
1446
1447       g_value_init (&val, GST_TYPE_STRUCTURE);
1448
1449       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE
1450           (self->essence_container_data[i]));
1451       gst_value_set_structure (&val, s);
1452       gst_structure_free (s);
1453       gst_value_array_append_value (&arr, &val);
1454       g_value_unset (&val);
1455     }
1456
1457     if (gst_value_array_get_size (&arr) > 0)
1458       gst_structure_id_set_value (ret, MXF_QUARK (ESSENCE_CONTAINER_DATA),
1459           &arr);
1460
1461     g_value_unset (&arr);
1462   }
1463
1464   return ret;
1465 }
1466
1467 static GList *
1468 mxf_metadata_content_storage_write_tags (MXFMetadataBase * m,
1469     MXFPrimerPack * primer)
1470 {
1471   MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (m);
1472   GList *ret =
1473       MXF_METADATA_BASE_CLASS
1474       (mxf_metadata_content_storage_parent_class)->write_tags (m, primer);
1475   MXFLocalTag *t;
1476   guint i;
1477
1478   if (self->packages) {
1479     t = g_slice_new0 (MXFLocalTag);
1480     memcpy (&t->ul, MXF_UL (PACKAGES), 16);
1481     t->size = 8 + 16 * self->n_packages;
1482     t->data = g_slice_alloc0 (t->size);
1483     t->g_slice = TRUE;
1484     GST_WRITE_UINT32_BE (t->data, self->n_packages);
1485     GST_WRITE_UINT32_BE (t->data + 4, 16);
1486     for (i = 0; i < self->n_packages; i++) {
1487       if (!self->packages[i])
1488         continue;
1489
1490       memcpy (t->data + 8 + i * 16,
1491           &MXF_METADATA_BASE (self->packages[i])->instance_uid, 16);
1492     }
1493
1494     mxf_primer_pack_add_mapping (primer, 0x1901, &t->ul);
1495     ret = g_list_prepend (ret, t);
1496   }
1497
1498   if (self->essence_container_data) {
1499     t = g_slice_new0 (MXFLocalTag);
1500     memcpy (&t->ul, MXF_UL (ESSENCE_CONTAINER_DATA), 16);
1501     t->size = 8 + 16 * self->n_essence_container_data;
1502     t->data = g_slice_alloc0 (t->size);
1503     t->g_slice = TRUE;
1504     GST_WRITE_UINT32_BE (t->data, self->n_essence_container_data);
1505     GST_WRITE_UINT32_BE (t->data + 4, 16);
1506     for (i = 0; i < self->n_essence_container_data; i++) {
1507       if (!self->essence_container_data[i])
1508         continue;
1509
1510       memcpy (t->data + 8 + i * 16,
1511           &MXF_METADATA_BASE (self->essence_container_data[i])->instance_uid,
1512           16);
1513     }
1514
1515     mxf_primer_pack_add_mapping (primer, 0x1902, &t->ul);
1516     ret = g_list_prepend (ret, t);
1517   }
1518
1519   return ret;
1520 }
1521
1522 static void
1523 mxf_metadata_content_storage_init (MXFMetadataContentStorage * self)
1524 {
1525
1526 }
1527
1528 static void
1529 mxf_metadata_content_storage_class_init (MXFMetadataContentStorageClass * klass)
1530 {
1531   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
1532   GObjectClass *object_class = (GObjectClass *) klass;
1533   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
1534
1535   object_class->finalize = mxf_metadata_content_storage_finalize;
1536   metadata_base_class->handle_tag = mxf_metadata_content_storage_handle_tag;
1537   metadata_base_class->resolve = mxf_metadata_content_storage_resolve;
1538   metadata_base_class->name_quark = MXF_QUARK (CONTENT_STORAGE);
1539   metadata_base_class->to_structure = mxf_metadata_content_storage_to_structure;
1540   metadata_base_class->write_tags = mxf_metadata_content_storage_write_tags;
1541   metadata_class->type = 0x0118;
1542 }
1543
1544 G_DEFINE_TYPE (MXFMetadataEssenceContainerData,
1545     mxf_metadata_essence_container_data, MXF_TYPE_METADATA);
1546
1547 static gboolean
1548 mxf_metadata_essence_container_data_handle_tag (MXFMetadataBase * metadata,
1549     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
1550     guint tag_size)
1551 {
1552   MXFMetadataEssenceContainerData *self =
1553       MXF_METADATA_ESSENCE_CONTAINER_DATA (metadata);
1554   gboolean ret = TRUE;
1555 #ifndef GST_DISABLE_GST_DEBUG
1556   gchar str[96];
1557 #endif
1558
1559   switch (tag) {
1560     case 0x2701:
1561       if (tag_size != 32)
1562         goto error;
1563       memcpy (&self->linked_package_uid, tag_data, 32);
1564       GST_DEBUG ("  linked package = %s",
1565           mxf_umid_to_string (&self->linked_package_uid, str));
1566       break;
1567     case 0x3f06:
1568       if (tag_size != 4)
1569         goto error;
1570       self->index_sid = GST_READ_UINT32_BE (tag_data);
1571       GST_DEBUG ("  index sid = %u", self->index_sid);
1572       break;
1573     case 0x3f07:
1574       if (tag_size != 4)
1575         goto error;
1576       self->body_sid = GST_READ_UINT32_BE (tag_data);
1577       GST_DEBUG ("  body sid = %u", self->body_sid);
1578       break;
1579     default:
1580       ret =
1581           MXF_METADATA_BASE_CLASS
1582           (mxf_metadata_essence_container_data_parent_class)->handle_tag
1583           (metadata, primer, tag, tag_data, tag_size);
1584       break;
1585   }
1586
1587   return ret;
1588
1589 error:
1590
1591   GST_ERROR ("Invalid essence container data local tag 0x%04x of size %u", tag,
1592       tag_size);
1593
1594   return FALSE;
1595 }
1596
1597 static gboolean
1598 mxf_metadata_essence_container_data_resolve (MXFMetadataBase * m,
1599     GHashTable * metadata)
1600 {
1601   MXFMetadataEssenceContainerData *self =
1602       MXF_METADATA_ESSENCE_CONTAINER_DATA (m);
1603   MXFMetadataBase *current = NULL;
1604   GHashTableIter iter;
1605
1606   g_hash_table_iter_init (&iter, metadata);
1607
1608   while (g_hash_table_iter_next (&iter, NULL, (gpointer) & current)) {
1609     if (MXF_IS_METADATA_SOURCE_PACKAGE (current)) {
1610       MXFMetadataSourcePackage *package = MXF_METADATA_SOURCE_PACKAGE (current);
1611
1612       if (mxf_umid_is_equal (&package->parent.package_uid,
1613               &self->linked_package_uid)) {
1614         if (mxf_metadata_base_resolve (current, metadata)) {
1615           self->linked_package = package;
1616         }
1617         break;
1618       }
1619     }
1620   }
1621
1622   if (!self->linked_package) {
1623     GST_ERROR ("Couldn't resolve a package");
1624     return FALSE;
1625   }
1626
1627   return
1628       MXF_METADATA_BASE_CLASS
1629       (mxf_metadata_essence_container_data_parent_class)->resolve (m, metadata);
1630 }
1631
1632 static GstStructure *
1633 mxf_metadata_essence_container_data_to_structure (MXFMetadataBase * m)
1634 {
1635   GstStructure *ret =
1636       MXF_METADATA_BASE_CLASS
1637       (mxf_metadata_essence_container_data_parent_class)->to_structure (m);
1638   MXFMetadataEssenceContainerData *self =
1639       MXF_METADATA_ESSENCE_CONTAINER_DATA (m);
1640   gchar str[96];
1641
1642   if (!mxf_umid_is_zero (&self->linked_package_uid)) {
1643     mxf_umid_to_string (&self->linked_package_uid, str);
1644     gst_structure_id_set (ret, MXF_QUARK (LINKED_PACKAGE), G_TYPE_STRING, str,
1645         NULL);
1646   }
1647
1648   gst_structure_id_set (ret, MXF_QUARK (INDEX_SID), G_TYPE_UINT,
1649       self->index_sid, MXF_QUARK (BODY_SID), G_TYPE_UINT, self->body_sid, NULL);
1650
1651
1652   return ret;
1653 }
1654
1655 static GList *
1656 mxf_metadata_essence_container_data_write_tags (MXFMetadataBase * m,
1657     MXFPrimerPack * primer)
1658 {
1659   MXFMetadataEssenceContainerData *self =
1660       MXF_METADATA_ESSENCE_CONTAINER_DATA (m);
1661   GList *ret =
1662       MXF_METADATA_BASE_CLASS
1663       (mxf_metadata_essence_container_data_parent_class)->write_tags (m,
1664       primer);
1665   MXFLocalTag *t;
1666
1667   t = g_slice_new0 (MXFLocalTag);
1668   memcpy (&t->ul, MXF_UL (LINKED_PACKAGE_UID), 16);
1669   t->size = 32;
1670   t->data = g_slice_alloc0 (32);
1671   t->g_slice = TRUE;
1672   if (self->linked_package)
1673     memcpy (t->data, &self->linked_package->parent.package_uid, 32);
1674   mxf_primer_pack_add_mapping (primer, 0x2701, &t->ul);
1675   ret = g_list_prepend (ret, t);
1676
1677   t = g_slice_new0 (MXFLocalTag);
1678   memcpy (&t->ul, MXF_UL (BODY_SID), 16);
1679   t->size = 4;
1680   t->data = g_slice_alloc (4);
1681   t->g_slice = TRUE;
1682   GST_WRITE_UINT32_BE (t->data, self->body_sid);
1683   mxf_primer_pack_add_mapping (primer, 0x3f07, &t->ul);
1684   ret = g_list_prepend (ret, t);
1685
1686   if (self->index_sid) {
1687     t = g_slice_new0 (MXFLocalTag);
1688     memcpy (&t->ul, MXF_UL (INDEX_SID), 16);
1689     t->size = 4;
1690     t->data = g_slice_alloc (4);
1691     t->g_slice = TRUE;
1692     GST_WRITE_UINT32_BE (t->data, self->index_sid);
1693     mxf_primer_pack_add_mapping (primer, 0x3f07, &t->ul);
1694     ret = g_list_prepend (ret, t);
1695   }
1696
1697   return ret;
1698 }
1699
1700 static void
1701 mxf_metadata_essence_container_data_init (MXFMetadataEssenceContainerData *
1702     self)
1703 {
1704
1705 }
1706
1707 static void
1708     mxf_metadata_essence_container_data_class_init
1709     (MXFMetadataEssenceContainerDataClass * klass)
1710 {
1711   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
1712   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
1713
1714   metadata_base_class->handle_tag =
1715       mxf_metadata_essence_container_data_handle_tag;
1716   metadata_base_class->resolve = mxf_metadata_essence_container_data_resolve;
1717   metadata_base_class->name_quark = MXF_QUARK (ESSENCE_CONTAINER_DATA);
1718   metadata_base_class->to_structure =
1719       mxf_metadata_essence_container_data_to_structure;
1720   metadata_base_class->write_tags =
1721       mxf_metadata_essence_container_data_write_tags;
1722   metadata_class->type = 0x0123;
1723 }
1724
1725 G_DEFINE_ABSTRACT_TYPE (MXFMetadataGenericPackage, mxf_metadata_generic_package,
1726     MXF_TYPE_METADATA);
1727
1728 static void
1729 mxf_metadata_generic_package_finalize (GObject * object)
1730 {
1731   MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (object);
1732
1733   g_free (self->name);
1734   self->name = NULL;
1735   g_free (self->tracks_uids);
1736   self->tracks_uids = NULL;
1737
1738   g_free (self->tracks);
1739   self->tracks = NULL;
1740
1741   G_OBJECT_CLASS (mxf_metadata_generic_package_parent_class)->finalize (object);
1742 }
1743
1744 static gboolean
1745 mxf_metadata_generic_package_handle_tag (MXFMetadataBase * metadata,
1746     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
1747     guint tag_size)
1748 {
1749   MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (metadata);
1750   gboolean ret = TRUE;
1751 #ifndef GST_DISABLE_GST_DEBUG
1752   gchar str[96];
1753 #endif
1754
1755   switch (tag) {
1756     case 0x4401:
1757       if (tag_size != 32)
1758         goto error;
1759       memcpy (&self->package_uid, tag_data, 32);
1760       GST_DEBUG ("  UMID = %s", mxf_umid_to_string (&self->package_uid, str));
1761       break;
1762     case 0x4402:
1763       self->name = mxf_utf16_to_utf8 (tag_data, tag_size);
1764       GST_DEBUG ("  name = %s", GST_STR_NULL (self->name));
1765       break;
1766     case 0x4405:
1767       if (!mxf_timestamp_parse (&self->package_creation_date,
1768               tag_data, tag_size))
1769         goto error;
1770       GST_DEBUG ("  creation date = %s",
1771           mxf_timestamp_to_string (&self->package_creation_date, str));
1772       break;
1773     case 0x4404:
1774       if (!mxf_timestamp_parse (&self->package_modified_date,
1775               tag_data, tag_size))
1776         goto error;
1777       GST_DEBUG ("  modification date = %s",
1778           mxf_timestamp_to_string (&self->package_modified_date, str));
1779       break;
1780     case 0x4403:
1781       if (!mxf_uuid_array_parse (&self->tracks_uids, &self->n_tracks, tag_data,
1782               tag_size))
1783         goto error;
1784
1785       GST_DEBUG ("  number of tracks = %u", self->n_tracks);
1786 #ifndef GST_DISABLE_GST_DEBUG
1787       {
1788         guint i;
1789         for (i = 0; i < self->n_tracks; i++) {
1790           GST_DEBUG ("  track %u = %s", i,
1791               mxf_uuid_to_string (&self->tracks_uids[i], str));
1792         }
1793       }
1794 #endif
1795       break;
1796     default:
1797       ret =
1798           MXF_METADATA_BASE_CLASS
1799           (mxf_metadata_generic_package_parent_class)->handle_tag (metadata,
1800           primer, tag, tag_data, tag_size);
1801       break;
1802   }
1803
1804   return ret;
1805
1806 error:
1807
1808   GST_ERROR ("Invalid generic package local tag 0x%04x of size %u", tag,
1809       tag_size);
1810
1811   return FALSE;
1812 }
1813
1814 static gboolean
1815 mxf_metadata_generic_package_resolve (MXFMetadataBase * m,
1816     GHashTable * metadata)
1817 {
1818   MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (m);
1819   MXFMetadataBase *current = NULL;
1820   guint i;
1821   gboolean have_track = FALSE;
1822
1823   if (self->tracks)
1824     memset (self->tracks, 0, sizeof (gpointer) * self->n_tracks);
1825   else
1826     self->tracks = g_new0 (MXFMetadataTrack *, self->n_tracks);
1827   for (i = 0; i < self->n_tracks; i++) {
1828     current = g_hash_table_lookup (metadata, &self->tracks_uids[i]);
1829     if (current && MXF_IS_METADATA_TRACK (current)) {
1830       if (mxf_metadata_base_resolve (current, metadata)) {
1831         MXFMetadataTrack *track = MXF_METADATA_TRACK (current);
1832
1833         self->tracks[i] = track;
1834         have_track = TRUE;
1835         if ((track->type & 0xf0) == 0x10)
1836           self->n_timecode_tracks++;
1837         else if ((track->type & 0xf0) == 0x20)
1838           self->n_metadata_tracks++;
1839         else if ((track->type & 0xf0) == 0x30)
1840           self->n_essence_tracks++;
1841         else if ((track->type & 0xf0) == 0x40)
1842           self->n_other_tracks++;
1843       } else {
1844         GST_ERROR ("Track couldn't be resolved");
1845       }
1846     } else {
1847       GST_ERROR ("Track not found");
1848     }
1849   }
1850
1851   if (!have_track) {
1852     GST_ERROR ("Couldn't resolve a track");
1853     return FALSE;
1854   }
1855
1856   return
1857       MXF_METADATA_BASE_CLASS
1858       (mxf_metadata_generic_package_parent_class)->resolve (m, metadata);
1859 }
1860
1861 static GstStructure *
1862 mxf_metadata_generic_package_to_structure (MXFMetadataBase * m)
1863 {
1864   GstStructure *ret =
1865       MXF_METADATA_BASE_CLASS
1866       (mxf_metadata_generic_package_parent_class)->to_structure (m);
1867   MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (m);
1868   guint i;
1869   gchar str[96];
1870
1871   mxf_umid_to_string (&self->package_uid, str);
1872   gst_structure_id_set (ret, MXF_QUARK (PACKAGE_UID), G_TYPE_STRING, str, NULL);
1873
1874   if (self->name)
1875     gst_structure_id_set (ret, MXF_QUARK (NAME), G_TYPE_STRING, self->name,
1876         NULL);
1877
1878   if (!mxf_timestamp_is_unknown (&self->package_creation_date)) {
1879     mxf_timestamp_to_string (&self->package_creation_date, str);
1880     gst_structure_id_set (ret, MXF_QUARK (PACKAGE_CREATION_DATE), G_TYPE_STRING,
1881         str, NULL);
1882   }
1883
1884   if (!mxf_timestamp_is_unknown (&self->package_modified_date)) {
1885     mxf_timestamp_to_string (&self->package_modified_date, str);
1886     gst_structure_id_set (ret, MXF_QUARK (PACKAGE_MODIFIED_DATE), G_TYPE_STRING,
1887         str, NULL);
1888   }
1889
1890   if (self->n_tracks > 0) {
1891     GValue arr = { 0, }
1892     , val = {
1893     0,};
1894
1895     g_value_init (&arr, GST_TYPE_ARRAY);
1896
1897     for (i = 0; i < self->n_tracks; i++) {
1898       GstStructure *s;
1899
1900       if (self->tracks[i] == NULL)
1901         continue;
1902
1903       g_value_init (&val, GST_TYPE_STRUCTURE);
1904
1905       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->tracks[i]));
1906       gst_value_set_structure (&val, s);
1907       gst_structure_free (s);
1908       gst_value_array_append_value (&arr, &val);
1909       g_value_unset (&val);
1910     }
1911
1912     if (gst_value_array_get_size (&arr) > 0)
1913       gst_structure_id_set_value (ret, MXF_QUARK (TRACKS), &arr);
1914
1915     g_value_unset (&arr);
1916   }
1917
1918   return ret;
1919 }
1920
1921 static GList *
1922 mxf_metadata_generic_package_write_tags (MXFMetadataBase * m,
1923     MXFPrimerPack * primer)
1924 {
1925   MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (m);
1926   GList *ret =
1927       MXF_METADATA_BASE_CLASS
1928       (mxf_metadata_generic_package_parent_class)->write_tags (m, primer);
1929   MXFLocalTag *t;
1930
1931   t = g_slice_new0 (MXFLocalTag);
1932   memcpy (&t->ul, MXF_UL (PACKAGE_UID), 16);
1933   t->size = 32;
1934   t->data = g_slice_alloc (t->size);
1935   t->g_slice = TRUE;
1936   memcpy (t->data, &self->package_uid, 32);
1937   mxf_primer_pack_add_mapping (primer, 0x4401, &t->ul);
1938   ret = g_list_prepend (ret, t);
1939
1940   if (self->name) {
1941     t = g_slice_new0 (MXFLocalTag);
1942     memcpy (&t->ul, MXF_UL (PACKAGE_NAME), 16);
1943     t->data = mxf_utf8_to_utf16 (self->name, &t->size);
1944     mxf_primer_pack_add_mapping (primer, 0x4402, &t->ul);
1945     ret = g_list_prepend (ret, t);
1946   }
1947
1948   t = g_slice_new0 (MXFLocalTag);
1949   memcpy (&t->ul, MXF_UL (PACKAGE_CREATION_DATE), 16);
1950   t->size = 8;
1951   t->data = g_slice_alloc (t->size);
1952   t->g_slice = TRUE;
1953   mxf_timestamp_write (&self->package_creation_date, t->data);
1954   mxf_primer_pack_add_mapping (primer, 0x4405, &t->ul);
1955   ret = g_list_prepend (ret, t);
1956
1957   t = g_slice_new0 (MXFLocalTag);
1958   memcpy (&t->ul, MXF_UL (PACKAGE_MODIFIED_DATE), 16);
1959   t->size = 8;
1960   t->data = g_slice_alloc (t->size);
1961   t->g_slice = TRUE;
1962   mxf_timestamp_write (&self->package_modified_date, t->data);
1963   mxf_primer_pack_add_mapping (primer, 0x4404, &t->ul);
1964   ret = g_list_prepend (ret, t);
1965
1966   if (self->tracks) {
1967     guint i;
1968
1969     t = g_slice_new0 (MXFLocalTag);
1970     memcpy (&t->ul, MXF_UL (TRACKS), 16);
1971     t->size = 8 + 16 * self->n_tracks;
1972     t->data = g_slice_alloc0 (t->size);
1973     t->g_slice = TRUE;
1974     GST_WRITE_UINT32_BE (t->data, self->n_tracks);
1975     GST_WRITE_UINT32_BE (t->data + 4, 16);
1976     for (i = 0; i < self->n_tracks; i++) {
1977       if (!self->tracks[i])
1978         continue;
1979
1980       memcpy (t->data + 8 + 16 * i,
1981           &MXF_METADATA_BASE (self->tracks[i])->instance_uid, 16);
1982     }
1983     mxf_primer_pack_add_mapping (primer, 0x4403, &t->ul);
1984     ret = g_list_prepend (ret, t);
1985   }
1986
1987   return ret;
1988 }
1989
1990 static void
1991 mxf_metadata_generic_package_init (MXFMetadataGenericPackage * self)
1992 {
1993
1994 }
1995
1996 static void
1997 mxf_metadata_generic_package_class_init (MXFMetadataGenericPackageClass * klass)
1998 {
1999   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2000   GObjectClass *object_class = (GObjectClass *) klass;
2001
2002   object_class->finalize = mxf_metadata_generic_package_finalize;
2003   metadata_base_class->handle_tag = mxf_metadata_generic_package_handle_tag;
2004   metadata_base_class->resolve = mxf_metadata_generic_package_resolve;
2005   metadata_base_class->to_structure = mxf_metadata_generic_package_to_structure;
2006   metadata_base_class->write_tags = mxf_metadata_generic_package_write_tags;
2007 }
2008
2009 G_DEFINE_TYPE (MXFMetadataMaterialPackage, mxf_metadata_material_package,
2010     MXF_TYPE_METADATA_GENERIC_PACKAGE);
2011
2012 static gboolean
2013 mxf_metadata_material_package_resolve (MXFMetadataBase * m,
2014     GHashTable * metadata)
2015 {
2016   gboolean ret =
2017       MXF_METADATA_BASE_CLASS
2018       (mxf_metadata_material_package_parent_class)->resolve (m, metadata);
2019   MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (m);
2020   guint i;
2021   guint ntracks = 0;
2022
2023   if (!ret)
2024     return ret;
2025
2026   for (i = 0; i < self->n_tracks; i++) {
2027     MXFMetadataTrack *track = self->tracks[i];
2028     MXFMetadataSequence *sequence;
2029     guint j;
2030
2031     if (!track)
2032       continue;
2033
2034     sequence = track->sequence;
2035
2036     if (!sequence || !sequence->structural_components)
2037       continue;
2038
2039     for (j = 0; j < sequence->n_structural_components; j++) {
2040       MXFMetadataSourceClip *sc;
2041       MXFMetadataTimelineTrack *st = NULL;
2042       guint k;
2043
2044       if (!sequence->structural_components[j]
2045           || !MXF_IS_METADATA_SOURCE_CLIP (sequence->structural_components[j]))
2046         continue;
2047
2048       sc = MXF_METADATA_SOURCE_CLIP (sequence->structural_components[j]);
2049
2050       if (!sc->source_package) {
2051         GST_ERROR ("Material package track %u without resolved source package",
2052             i);
2053         track = NULL;
2054         break;
2055       }
2056
2057       if (!mxf_metadata_base_resolve (MXF_METADATA_BASE (sc->source_package),
2058               metadata)) {
2059         GST_ERROR ("Couldn't resolve source package for track %u", i);
2060         track = NULL;
2061         break;
2062       }
2063
2064       sc->source_package->top_level = TRUE;
2065       for (k = 0; k < sc->source_package->parent.n_tracks; k++) {
2066         MXFMetadataTimelineTrack *tmp;
2067
2068         if (!sc->source_package->parent.tracks[k] ||
2069             !MXF_IS_METADATA_TIMELINE_TRACK (sc->source_package->
2070                 parent.tracks[k]))
2071           continue;
2072
2073         tmp =
2074             MXF_METADATA_TIMELINE_TRACK (sc->source_package->parent.tracks[k]);
2075         if (tmp->parent.track_id == sc->source_track_id) {
2076           st = tmp;
2077           break;
2078         }
2079       }
2080
2081       if (!st) {
2082         GST_ERROR ("Material package track %u without resolved source track",
2083             i);
2084         track = NULL;
2085       }
2086     }
2087
2088     if (track)
2089       ntracks++;
2090     else
2091       self->tracks[i] = NULL;
2092   }
2093
2094   if (ntracks == 0) {
2095     GST_ERROR ("No tracks could be resolved");
2096     return FALSE;
2097   } else if (ntracks != self->n_tracks) {
2098     GST_WARNING ("Not all tracks could be resolved");
2099   }
2100
2101   return TRUE;
2102 }
2103
2104 static void
2105 mxf_metadata_material_package_init (MXFMetadataMaterialPackage * self)
2106 {
2107 }
2108
2109 static void
2110 mxf_metadata_material_package_class_init (MXFMetadataMaterialPackageClass *
2111     klass)
2112 {
2113   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2114   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2115
2116   metadata_base_class->resolve = mxf_metadata_material_package_resolve;
2117   metadata_base_class->name_quark = MXF_QUARK (MATERIAL_PACKAGE);
2118   metadata_class->type = 0x0136;
2119 }
2120
2121 G_DEFINE_TYPE (MXFMetadataSourcePackage, mxf_metadata_source_package,
2122     MXF_TYPE_METADATA_GENERIC_PACKAGE);
2123
2124 static gboolean
2125 mxf_metadata_source_package_handle_tag (MXFMetadataBase * metadata,
2126     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2127     guint tag_size)
2128 {
2129   MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (metadata);
2130   gboolean ret = TRUE;
2131 #ifndef GST_DISABLE_GST_DEBUG
2132   gchar str[48];
2133 #endif
2134
2135   switch (tag) {
2136     case 0x4701:
2137       if (tag_size != 16)
2138         goto error;
2139
2140       memcpy (&self->descriptor_uid, tag_data, 16);
2141       GST_DEBUG ("  descriptor = %s",
2142           mxf_uuid_to_string (&self->descriptor_uid, str));
2143       break;
2144     default:
2145       ret =
2146           MXF_METADATA_BASE_CLASS
2147           (mxf_metadata_source_package_parent_class)->handle_tag (metadata,
2148           primer, tag, tag_data, tag_size);
2149       break;
2150   }
2151
2152   return ret;
2153
2154 error:
2155
2156   GST_ERROR ("Invalid source package local tag 0x%04x of size %u", tag,
2157       tag_size);
2158
2159   return FALSE;
2160 }
2161
2162 static gboolean
2163 mxf_metadata_source_package_resolve (MXFMetadataBase * m, GHashTable * metadata)
2164 {
2165   MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (m);
2166   MXFMetadataGenericPackage *package = MXF_METADATA_GENERIC_PACKAGE (m);
2167   MXFMetadataBase *current = NULL;
2168   guint i;
2169   gboolean ret;
2170   MXFMetadataFileDescriptor *d;
2171
2172   if (mxf_uuid_is_zero (&self->descriptor_uid))
2173     return
2174         MXF_METADATA_BASE_CLASS
2175         (mxf_metadata_source_package_parent_class)->resolve (m, metadata);
2176
2177   current = g_hash_table_lookup (metadata, &self->descriptor_uid);
2178   if (!current) {
2179     GST_ERROR ("Descriptor not found");
2180     return FALSE;
2181   }
2182
2183   if (!mxf_metadata_base_resolve (MXF_METADATA_BASE (current), metadata)) {
2184     GST_ERROR ("Couldn't resolve descriptor");
2185     return FALSE;
2186   }
2187
2188   self->descriptor = MXF_METADATA_GENERIC_DESCRIPTOR (current);
2189
2190   ret =
2191       MXF_METADATA_BASE_CLASS
2192       (mxf_metadata_source_package_parent_class)->resolve (m, metadata);
2193
2194   if (!MXF_IS_METADATA_FILE_DESCRIPTOR (self->descriptor))
2195     return ret;
2196
2197   d = MXF_METADATA_FILE_DESCRIPTOR (current);
2198
2199   for (i = 0; i < package->n_tracks; i++) {
2200     if (!MXF_IS_METADATA_MULTIPLE_DESCRIPTOR (d)) {
2201       if (d->linked_track_id == package->tracks[i]->track_id ||
2202           (d->linked_track_id == 0 && package->n_essence_tracks == 1 &&
2203               (package->tracks[i]->type & 0xf0) == 0x30)) {
2204         package->tracks[i]->descriptor =
2205             g_new0 (MXFMetadataFileDescriptor *, 1);
2206         package->tracks[i]->descriptor[0] = d;
2207         package->tracks[i]->n_descriptor = 1;
2208         break;
2209       }
2210     } else {
2211       guint n_descriptor = 0, j, k = 0;
2212       MXFMetadataMultipleDescriptor *md = MXF_METADATA_MULTIPLE_DESCRIPTOR (d);
2213
2214       for (j = 0; j < md->n_sub_descriptors; j++) {
2215         MXFMetadataFileDescriptor *fd;
2216
2217         if (!md->sub_descriptors[j] ||
2218             !MXF_METADATA_FILE_DESCRIPTOR (md->sub_descriptors[j]))
2219           continue;
2220
2221         fd = MXF_METADATA_FILE_DESCRIPTOR (md->sub_descriptors[j]);
2222
2223         if (fd->linked_track_id == package->tracks[i]->track_id ||
2224             (fd->linked_track_id == 0 && package->n_essence_tracks == 1 &&
2225                 (package->tracks[i]->type & 0xf0) == 0x30))
2226           n_descriptor++;
2227       }
2228
2229       package->tracks[i]->descriptor =
2230           g_new0 (MXFMetadataFileDescriptor *, n_descriptor);
2231       package->tracks[i]->n_descriptor = n_descriptor;
2232
2233       for (j = 0; j < md->n_sub_descriptors; j++) {
2234         MXFMetadataFileDescriptor *fd;
2235
2236         if (!md->sub_descriptors[j] ||
2237             !MXF_METADATA_FILE_DESCRIPTOR (md->sub_descriptors[j]))
2238           continue;
2239
2240         fd = MXF_METADATA_FILE_DESCRIPTOR (md->sub_descriptors[j]);
2241
2242         if (fd->linked_track_id == package->tracks[i]->track_id ||
2243             (fd->linked_track_id == 0 && package->n_essence_tracks == 1 &&
2244                 (package->tracks[i]->type & 0xf0) == 0x30)) {
2245           package->tracks[i]->descriptor[k] = fd;
2246           k++;
2247         }
2248       }
2249     }
2250   }
2251
2252   return ret;
2253 }
2254
2255 static GstStructure *
2256 mxf_metadata_source_package_to_structure (MXFMetadataBase * m)
2257 {
2258   GstStructure *ret =
2259       MXF_METADATA_BASE_CLASS
2260       (mxf_metadata_source_package_parent_class)->to_structure (m);
2261   MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (m);
2262   GstStructure *s;
2263
2264   if (!self->descriptor)
2265     return ret;
2266
2267   s = mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->descriptor));
2268   gst_structure_id_set (ret, MXF_QUARK (DESCRIPTOR), GST_TYPE_STRUCTURE, s,
2269       NULL);
2270   gst_structure_free (s);
2271
2272   return ret;
2273 }
2274
2275 static GList *
2276 mxf_metadata_source_package_write_tags (MXFMetadataBase * m,
2277     MXFPrimerPack * primer)
2278 {
2279   MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (m);
2280   GList *ret =
2281       MXF_METADATA_BASE_CLASS
2282       (mxf_metadata_source_package_parent_class)->write_tags (m, primer);
2283   MXFLocalTag *t;
2284
2285   if (self->descriptor) {
2286     t = g_slice_new0 (MXFLocalTag);
2287     memcpy (&t->ul, MXF_UL (DESCRIPTOR), 16);
2288     t->size = 16;
2289     t->data = g_slice_alloc (t->size);
2290     t->g_slice = TRUE;
2291     memcpy (t->data, &MXF_METADATA_BASE (self->descriptor)->instance_uid, 16);
2292     mxf_primer_pack_add_mapping (primer, 0x4701, &t->ul);
2293     ret = g_list_prepend (ret, t);
2294   }
2295
2296   return ret;
2297 }
2298
2299 static void
2300 mxf_metadata_source_package_init (MXFMetadataSourcePackage * self)
2301 {
2302
2303 }
2304
2305 static void
2306 mxf_metadata_source_package_class_init (MXFMetadataSourcePackageClass * klass)
2307 {
2308   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2309   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2310
2311   metadata_base_class->handle_tag = mxf_metadata_source_package_handle_tag;
2312   metadata_base_class->resolve = mxf_metadata_source_package_resolve;
2313   metadata_base_class->name_quark = MXF_QUARK (SOURCE_PACKAGE);
2314   metadata_base_class->to_structure = mxf_metadata_source_package_to_structure;
2315   metadata_base_class->write_tags = mxf_metadata_source_package_write_tags;
2316   metadata_class->type = 0x0137;
2317 }
2318
2319 G_DEFINE_ABSTRACT_TYPE (MXFMetadataTrack, mxf_metadata_track,
2320     MXF_TYPE_METADATA);
2321
2322 static void
2323 mxf_metadata_track_finalize (GObject * object)
2324 {
2325   MXFMetadataTrack *self = MXF_METADATA_TRACK (object);
2326
2327   g_free (self->track_name);
2328   self->track_name = NULL;
2329   g_free (self->descriptor);
2330   self->descriptor = NULL;
2331
2332   G_OBJECT_CLASS (mxf_metadata_track_parent_class)->finalize (object);
2333 }
2334
2335 static gboolean
2336 mxf_metadata_track_handle_tag (MXFMetadataBase * metadata,
2337     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2338     guint tag_size)
2339 {
2340   MXFMetadataTrack *self = MXF_METADATA_TRACK (metadata);
2341   gboolean ret = TRUE;
2342 #ifndef GST_DISABLE_GST_DEBUG
2343   gchar str[48];
2344 #endif
2345
2346   switch (tag) {
2347     case 0x4801:
2348       if (tag_size != 4)
2349         goto error;
2350       self->track_id = GST_READ_UINT32_BE (tag_data);
2351       GST_DEBUG ("  track id = %u", self->track_id);
2352       break;
2353     case 0x4804:
2354       if (tag_size != 4)
2355         goto error;
2356       self->track_number = GST_READ_UINT32_BE (tag_data);
2357       GST_DEBUG ("  track number = %u", self->track_number);
2358       break;
2359     case 0x4802:
2360       self->track_name = mxf_utf16_to_utf8 (tag_data, tag_size);
2361       GST_DEBUG ("  track name = %s", GST_STR_NULL (self->track_name));
2362       break;
2363     case 0x4803:
2364       if (tag_size != 16)
2365         goto error;
2366       memcpy (&self->sequence_uid, tag_data, 16);
2367       GST_DEBUG ("  sequence uid = %s",
2368           mxf_uuid_to_string (&self->sequence_uid, str));
2369       break;
2370     default:
2371       ret =
2372           MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->handle_tag
2373           (metadata, primer, tag, tag_data, tag_size);
2374       break;
2375   }
2376
2377   return ret;
2378
2379 error:
2380
2381   GST_ERROR ("Invalid track local tag 0x%04x of size %u", tag, tag_size);
2382
2383   return FALSE;
2384 }
2385
2386 static gboolean
2387 mxf_metadata_track_resolve (MXFMetadataBase * m, GHashTable * metadata)
2388 {
2389   MXFMetadataTrack *self = MXF_METADATA_TRACK (m);
2390   MXFMetadataBase *current = NULL;
2391   guint i;
2392
2393   current = g_hash_table_lookup (metadata, &self->sequence_uid);
2394   if (current && MXF_IS_METADATA_SEQUENCE (current)) {
2395     if (mxf_metadata_base_resolve (current, metadata)) {
2396       self->sequence = MXF_METADATA_SEQUENCE (current);
2397     } else {
2398       GST_ERROR ("Couldn't resolve sequence");
2399       return FALSE;
2400     }
2401   } else {
2402     GST_ERROR ("Couldn't find sequence");
2403     return FALSE;
2404   }
2405
2406   self->type =
2407       mxf_metadata_track_identifier_parse (&self->sequence->data_definition);
2408   if (self->type == MXF_METADATA_TRACK_UNKNOWN) {
2409     MXFMetadataSequence *sequence = self->sequence;
2410
2411     for (i = 0; i < sequence->n_structural_components; i++) {
2412       MXFMetadataStructuralComponent *component =
2413           sequence->structural_components[i];
2414
2415       if (!component)
2416         continue;
2417
2418       self->type =
2419           mxf_metadata_track_identifier_parse (&component->data_definition);
2420       if (self->type != MXF_METADATA_TRACK_UNKNOWN)
2421         break;
2422     }
2423   }
2424
2425   return MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->resolve (m,
2426       metadata);
2427 }
2428
2429 static GstStructure *
2430 mxf_metadata_track_to_structure (MXFMetadataBase * m)
2431 {
2432   GstStructure *ret =
2433       MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->to_structure
2434       (m);
2435   MXFMetadataTrack *self = MXF_METADATA_TRACK (m);
2436
2437   gst_structure_id_set (ret, MXF_QUARK (TRACK_ID), G_TYPE_UINT, self->track_id,
2438       MXF_QUARK (TRACK_NUMBER), G_TYPE_UINT, self->track_number, NULL);
2439
2440   if (self->track_name)
2441     gst_structure_id_set (ret, MXF_QUARK (TRACK_NAME), G_TYPE_STRING,
2442         self->track_name, NULL);
2443
2444   if (self->sequence) {
2445     GstStructure *s =
2446         mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->sequence));
2447
2448     gst_structure_id_set (ret, MXF_QUARK (SEQUENCE), GST_TYPE_STRUCTURE, s,
2449         NULL);
2450     gst_structure_free (s);
2451   }
2452
2453
2454   return ret;
2455 }
2456
2457 static GList *
2458 mxf_metadata_track_write_tags (MXFMetadataBase * m, MXFPrimerPack * primer)
2459 {
2460   MXFMetadataTrack *self = MXF_METADATA_TRACK (m);
2461   GList *ret =
2462       MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->write_tags (m,
2463       primer);
2464   MXFLocalTag *t;
2465
2466   t = g_slice_new0 (MXFLocalTag);
2467   memcpy (&t->ul, MXF_UL (TRACK_ID), 16);
2468   t->size = 4;
2469   t->data = g_slice_alloc (t->size);
2470   t->g_slice = TRUE;
2471   GST_WRITE_UINT32_BE (t->data, self->track_id);
2472   mxf_primer_pack_add_mapping (primer, 0x4801, &t->ul);
2473   ret = g_list_prepend (ret, t);
2474
2475   t = g_slice_new0 (MXFLocalTag);
2476   memcpy (&t->ul, MXF_UL (TRACK_NUMBER), 16);
2477   t->size = 4;
2478   t->data = g_slice_alloc (t->size);
2479   t->g_slice = TRUE;
2480   GST_WRITE_UINT32_BE (t->data, self->track_number);
2481   mxf_primer_pack_add_mapping (primer, 0x4804, &t->ul);
2482   ret = g_list_prepend (ret, t);
2483
2484   if (self->track_name) {
2485     t = g_slice_new0 (MXFLocalTag);
2486     memcpy (&t->ul, MXF_UL (TRACK_NAME), 16);
2487     t->data = mxf_utf8_to_utf16 (self->track_name, &t->size);
2488     mxf_primer_pack_add_mapping (primer, 0x4802, &t->ul);
2489     ret = g_list_prepend (ret, t);
2490   }
2491
2492   t = g_slice_new0 (MXFLocalTag);
2493   memcpy (&t->ul, MXF_UL (SEQUENCE), 16);
2494   t->size = 16;
2495   t->data = g_slice_alloc (t->size);
2496   t->g_slice = TRUE;
2497   memcpy (t->data, &MXF_METADATA_BASE (self->sequence)->instance_uid, 16);
2498   mxf_primer_pack_add_mapping (primer, 0x4803, &t->ul);
2499   ret = g_list_prepend (ret, t);
2500
2501   return ret;
2502 }
2503
2504 static void
2505 mxf_metadata_track_init (MXFMetadataTrack * self)
2506 {
2507
2508 }
2509
2510 static void
2511 mxf_metadata_track_class_init (MXFMetadataTrackClass * klass)
2512 {
2513   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2514   GObjectClass *object_class = (GObjectClass *) klass;
2515
2516   object_class->finalize = mxf_metadata_track_finalize;
2517   metadata_base_class->handle_tag = mxf_metadata_track_handle_tag;
2518   metadata_base_class->resolve = mxf_metadata_track_resolve;
2519   metadata_base_class->to_structure = mxf_metadata_track_to_structure;
2520   metadata_base_class->write_tags = mxf_metadata_track_write_tags;
2521 }
2522
2523 /* SMPTE RP224 */
2524 static const struct
2525 {
2526   const MXFUL *ul;
2527   const MXFMetadataTrackType type;
2528 } mxf_metadata_track_identifier[] = {
2529   {
2530   MXF_UL (TRACK_TIMECODE_12M_INACTIVE),
2531         MXF_METADATA_TRACK_TIMECODE_12M_INACTIVE}, {
2532   MXF_UL (TRACK_TIMECODE_12M_ACTIVE), MXF_METADATA_TRACK_TIMECODE_12M_ACTIVE}, {
2533   MXF_UL (TRACK_TIMECODE_309M), MXF_METADATA_TRACK_TIMECODE_309M}, {
2534   MXF_UL (TRACK_METADATA), MXF_METADATA_TRACK_METADATA}, {
2535   MXF_UL (TRACK_PICTURE_ESSENCE), MXF_METADATA_TRACK_PICTURE_ESSENCE}, {
2536   MXF_UL (TRACK_SOUND_ESSENCE), MXF_METADATA_TRACK_SOUND_ESSENCE}, {
2537   MXF_UL (TRACK_DATA_ESSENCE), MXF_METADATA_TRACK_DATA_ESSENCE}, {
2538   MXF_UL (TRACK_AUXILIARY_DATA), MXF_METADATA_TRACK_AUXILIARY_DATA}, {
2539   MXF_UL (TRACK_PARSED_TEXT), MXF_METADATA_TRACK_PARSED_TEXT},
2540       /* Avid video? */
2541   {
2542   MXF_UL (TRACK_AVID_PICTURE_ESSENCE), MXF_METADATA_TRACK_PICTURE_ESSENCE}
2543 };
2544
2545 MXFMetadataTrackType
2546 mxf_metadata_track_identifier_parse (const MXFUL * track_identifier)
2547 {
2548   guint i;
2549
2550   for (i = 0; i < G_N_ELEMENTS (mxf_metadata_track_identifier); i++)
2551     if (mxf_ul_is_equal (mxf_metadata_track_identifier[i].ul, track_identifier))
2552       return mxf_metadata_track_identifier[i].type;
2553
2554   return MXF_METADATA_TRACK_UNKNOWN;
2555 }
2556
2557 const MXFUL *
2558 mxf_metadata_track_identifier_get (MXFMetadataTrackType type)
2559 {
2560   guint i;
2561
2562   for (i = 0; i < G_N_ELEMENTS (mxf_metadata_track_identifier); i++)
2563     if (mxf_metadata_track_identifier[i].type == type)
2564       return mxf_metadata_track_identifier[i].ul;
2565
2566   return NULL;
2567 }
2568
2569 G_DEFINE_TYPE (MXFMetadataTimelineTrack, mxf_metadata_timeline_track,
2570     MXF_TYPE_METADATA_TRACK);
2571
2572 static gboolean
2573 mxf_metadata_timeline_track_handle_tag (MXFMetadataBase * metadata,
2574     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2575     guint tag_size)
2576 {
2577   MXFMetadataTimelineTrack *self = MXF_METADATA_TIMELINE_TRACK (metadata);
2578   gboolean ret = TRUE;
2579
2580   switch (tag) {
2581     case 0x4b01:
2582       if (!mxf_fraction_parse (&self->edit_rate, tag_data, tag_size))
2583         goto error;
2584       GST_DEBUG ("  edit rate = %d/%d", self->edit_rate.n, self->edit_rate.d);
2585       break;
2586     case 0x4b02:
2587       if (tag_size != 8)
2588         goto error;
2589       self->origin = GST_READ_UINT64_BE (tag_data);
2590       GST_DEBUG ("  origin = %" G_GINT64_FORMAT, self->origin);
2591       break;
2592     default:
2593       ret =
2594           MXF_METADATA_BASE_CLASS
2595           (mxf_metadata_timeline_track_parent_class)->handle_tag (metadata,
2596           primer, tag, tag_data, tag_size);
2597       break;
2598   }
2599
2600   return ret;
2601
2602 error:
2603
2604   GST_ERROR ("Invalid timeline track local tag 0x%04x of size %u", tag,
2605       tag_size);
2606
2607   return FALSE;
2608 }
2609
2610 static GstStructure *
2611 mxf_metadata_timeline_track_to_structure (MXFMetadataBase * m)
2612 {
2613   GstStructure *ret =
2614       MXF_METADATA_BASE_CLASS
2615       (mxf_metadata_timeline_track_parent_class)->to_structure (m);
2616   MXFMetadataTimelineTrack *self = MXF_METADATA_TIMELINE_TRACK (m);
2617
2618   gst_structure_id_set (ret, MXF_QUARK (EDIT_RATE), GST_TYPE_FRACTION,
2619       self->edit_rate.n, self->edit_rate.d, MXF_QUARK (ORIGIN), G_TYPE_INT64,
2620       self->origin, NULL);
2621
2622   return ret;
2623 }
2624
2625 static GList *
2626 mxf_metadata_timeline_track_write_tags (MXFMetadataBase * m,
2627     MXFPrimerPack * primer)
2628 {
2629   MXFMetadataTimelineTrack *self = MXF_METADATA_TIMELINE_TRACK (m);
2630   GList *ret =
2631       MXF_METADATA_BASE_CLASS
2632       (mxf_metadata_timeline_track_parent_class)->write_tags (m, primer);
2633   MXFLocalTag *t;
2634
2635   t = g_slice_new0 (MXFLocalTag);
2636   memcpy (&t->ul, MXF_UL (EDIT_RATE), 16);
2637   t->size = 8;
2638   t->data = g_slice_alloc (t->size);
2639   t->g_slice = TRUE;
2640   GST_WRITE_UINT32_BE (t->data, self->edit_rate.n);
2641   GST_WRITE_UINT32_BE (t->data + 4, self->edit_rate.d);
2642   mxf_primer_pack_add_mapping (primer, 0x4b01, &t->ul);
2643   ret = g_list_prepend (ret, t);
2644
2645   t = g_slice_new0 (MXFLocalTag);
2646   memcpy (&t->ul, MXF_UL (ORIGIN), 16);
2647   t->size = 8;
2648   t->data = g_slice_alloc (t->size);
2649   t->g_slice = TRUE;
2650   GST_WRITE_UINT64_BE (t->data, self->origin);
2651   mxf_primer_pack_add_mapping (primer, 0x4b02, &t->ul);
2652   ret = g_list_prepend (ret, t);
2653
2654   return ret;
2655 }
2656
2657 static void
2658 mxf_metadata_timeline_track_init (MXFMetadataTimelineTrack * self)
2659 {
2660
2661 }
2662
2663 static void
2664 mxf_metadata_timeline_track_class_init (MXFMetadataTimelineTrackClass * klass)
2665 {
2666   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2667   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2668
2669   metadata_base_class->handle_tag = mxf_metadata_timeline_track_handle_tag;
2670   metadata_base_class->name_quark = MXF_QUARK (TIMELINE_TRACK);
2671   metadata_base_class->to_structure = mxf_metadata_timeline_track_to_structure;
2672   metadata_base_class->write_tags = mxf_metadata_timeline_track_write_tags;
2673   metadata_class->type = 0x013b;
2674 }
2675
2676 G_DEFINE_TYPE (MXFMetadataEventTrack, mxf_metadata_event_track,
2677     MXF_TYPE_METADATA_TRACK);
2678
2679 static gboolean
2680 mxf_metadata_event_track_handle_tag (MXFMetadataBase * metadata,
2681     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2682     guint tag_size)
2683 {
2684   MXFMetadataEventTrack *self = MXF_METADATA_EVENT_TRACK (metadata);
2685   gboolean ret = TRUE;
2686
2687   switch (tag) {
2688     case 0x4901:
2689       if (!mxf_fraction_parse (&self->event_edit_rate, tag_data, tag_size))
2690         goto error;
2691       GST_DEBUG ("  event edit rate = %d/%d", self->event_edit_rate.n,
2692           self->event_edit_rate.d);
2693       break;
2694     case 0x4902:
2695       if (tag_size != 8)
2696         goto error;
2697       self->event_origin = GST_READ_UINT64_BE (tag_data);
2698       GST_DEBUG ("  event origin = %" G_GINT64_FORMAT, self->event_origin);
2699       break;
2700     default:
2701       ret =
2702           MXF_METADATA_BASE_CLASS
2703           (mxf_metadata_event_track_parent_class)->handle_tag (metadata, primer,
2704           tag, tag_data, tag_size);
2705       break;
2706   }
2707
2708   return ret;
2709
2710 error:
2711
2712   GST_ERROR ("Invalid event track local tag 0x%04x of size %u", tag, tag_size);
2713
2714   return FALSE;
2715 }
2716
2717 static GstStructure *
2718 mxf_metadata_event_track_to_structure (MXFMetadataBase * m)
2719 {
2720   GstStructure *ret =
2721       MXF_METADATA_BASE_CLASS
2722       (mxf_metadata_event_track_parent_class)->to_structure (m);
2723   MXFMetadataEventTrack *self = MXF_METADATA_EVENT_TRACK (m);
2724
2725   gst_structure_id_set (ret, MXF_QUARK (EVENT_EDIT_RATE), GST_TYPE_FRACTION,
2726       self->event_edit_rate.n, self->event_edit_rate.d,
2727       MXF_QUARK (EVENT_ORIGIN), G_TYPE_INT64, self->event_origin, NULL);
2728
2729   return ret;
2730 }
2731
2732 static GList *
2733 mxf_metadata_event_track_write_tags (MXFMetadataBase * m,
2734     MXFPrimerPack * primer)
2735 {
2736   MXFMetadataEventTrack *self = MXF_METADATA_EVENT_TRACK (m);
2737   GList *ret =
2738       MXF_METADATA_BASE_CLASS
2739       (mxf_metadata_event_track_parent_class)->write_tags (m, primer);
2740   MXFLocalTag *t;
2741
2742   t = g_slice_new0 (MXFLocalTag);
2743   memcpy (&t->ul, MXF_UL (EVENT_EDIT_RATE), 16);
2744   t->size = 8;
2745   t->data = g_slice_alloc (t->size);
2746   t->g_slice = TRUE;
2747   GST_WRITE_UINT32_BE (t->data, self->event_edit_rate.n);
2748   GST_WRITE_UINT32_BE (t->data + 4, self->event_edit_rate.d);
2749   mxf_primer_pack_add_mapping (primer, 0x4901, &t->ul);
2750   ret = g_list_prepend (ret, t);
2751
2752   t = g_slice_new0 (MXFLocalTag);
2753   memcpy (&t->ul, MXF_UL (EVENT_ORIGIN), 16);
2754   t->size = 8;
2755   t->data = g_slice_alloc (t->size);
2756   t->g_slice = TRUE;
2757   GST_WRITE_UINT64_BE (t->data, self->event_origin);
2758   mxf_primer_pack_add_mapping (primer, 0x4902, &t->ul);
2759   ret = g_list_prepend (ret, t);
2760
2761   return ret;
2762 }
2763
2764 static void
2765 mxf_metadata_event_track_init (MXFMetadataEventTrack * self)
2766 {
2767
2768 }
2769
2770 static void
2771 mxf_metadata_event_track_class_init (MXFMetadataEventTrackClass * klass)
2772 {
2773   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2774   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2775
2776   metadata_base_class->handle_tag = mxf_metadata_event_track_handle_tag;
2777   metadata_base_class->name_quark = MXF_QUARK (EVENT_TRACK);
2778   metadata_base_class->to_structure = mxf_metadata_event_track_to_structure;
2779   metadata_base_class->write_tags = mxf_metadata_event_track_write_tags;
2780   metadata_class->type = 0x0139;
2781 }
2782
2783 G_DEFINE_TYPE (MXFMetadataStaticTrack, mxf_metadata_static_track,
2784     MXF_TYPE_METADATA_TRACK);
2785
2786 static void
2787 mxf_metadata_static_track_init (MXFMetadataStaticTrack * self)
2788 {
2789 }
2790
2791 static void
2792 mxf_metadata_static_track_class_init (MXFMetadataStaticTrackClass * klass)
2793 {
2794   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2795   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2796
2797   metadata_base_class->name_quark = MXF_QUARK (STATIC_TRACK);
2798   metadata_class->type = 0x013a;
2799 }
2800
2801 G_DEFINE_TYPE (MXFMetadataSequence, mxf_metadata_sequence, MXF_TYPE_METADATA);
2802
2803 static void
2804 mxf_metadata_sequence_finalize (GObject * object)
2805 {
2806   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (object);
2807
2808   g_free (self->structural_components_uids);
2809   self->structural_components_uids = NULL;
2810   g_free (self->structural_components);
2811   self->structural_components = NULL;
2812
2813   G_OBJECT_CLASS (mxf_metadata_sequence_parent_class)->finalize (object);
2814 }
2815
2816 static gboolean
2817 mxf_metadata_sequence_handle_tag (MXFMetadataBase * metadata,
2818     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2819     guint tag_size)
2820 {
2821   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (metadata);
2822   gboolean ret = TRUE;
2823 #ifndef GST_DISABLE_GST_DEBUG
2824   gchar str[48];
2825 #endif
2826
2827   switch (tag) {
2828     case 0x0201:
2829       if (tag_size != 16)
2830         goto error;
2831       memcpy (&self->data_definition, tag_data, 16);
2832       GST_DEBUG ("  data definition = %s",
2833           mxf_ul_to_string (&self->data_definition, str));
2834       break;
2835     case 0x0202:
2836       if (tag_size != 8)
2837         goto error;
2838       self->duration = GST_READ_UINT64_BE (tag_data);
2839       GST_DEBUG ("  duration = %" G_GINT64_FORMAT, self->duration);
2840       break;
2841     case 0x1001:
2842       if (!mxf_uuid_array_parse (&self->structural_components_uids,
2843               &self->n_structural_components, tag_data, tag_size))
2844         goto error;
2845
2846       GST_DEBUG ("  number of structural components = %u",
2847           self->n_structural_components);
2848 #ifndef GST_DISABLE_GST_DEBUG
2849       {
2850         guint i;
2851         for (i = 0; i < self->n_structural_components; i++) {
2852           GST_DEBUG ("  structural component %u = %s", i,
2853               mxf_uuid_to_string (&self->structural_components_uids[i], str));
2854         }
2855       }
2856 #endif
2857       break;
2858     default:
2859       ret =
2860           MXF_METADATA_BASE_CLASS
2861           (mxf_metadata_sequence_parent_class)->handle_tag (metadata, primer,
2862           tag, tag_data, tag_size);
2863       break;
2864   }
2865
2866   return ret;
2867
2868 error:
2869
2870   GST_ERROR ("Invalid sequence local tag 0x%04x of size %u", tag, tag_size);
2871
2872   return FALSE;
2873 }
2874
2875 static gboolean
2876 mxf_metadata_sequence_resolve (MXFMetadataBase * m, GHashTable * metadata)
2877 {
2878   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (m);
2879   MXFMetadataBase *current = NULL;
2880   guint i;
2881
2882   if (self->structural_components)
2883     memset (self->structural_components, 0,
2884         sizeof (gpointer) * self->n_structural_components);
2885   else
2886     self->structural_components =
2887         g_new0 (MXFMetadataStructuralComponent *,
2888         self->n_structural_components);
2889   for (i = 0; i < self->n_structural_components; i++) {
2890     current =
2891         g_hash_table_lookup (metadata, &self->structural_components_uids[i]);
2892     if (current && MXF_IS_METADATA_STRUCTURAL_COMPONENT (current)) {
2893       if (mxf_metadata_base_resolve (current, metadata)) {
2894         self->structural_components[i] =
2895             MXF_METADATA_STRUCTURAL_COMPONENT (current);
2896       } else {
2897         GST_ERROR ("Couldn't resolve structural component");
2898         return FALSE;
2899       }
2900     } else {
2901       GST_ERROR ("Structural component not found");
2902       return FALSE;
2903     }
2904   }
2905
2906   return
2907       MXF_METADATA_BASE_CLASS (mxf_metadata_sequence_parent_class)->resolve (m,
2908       metadata);
2909
2910 }
2911
2912 static GstStructure *
2913 mxf_metadata_sequence_to_structure (MXFMetadataBase * m)
2914 {
2915   GstStructure *ret =
2916       MXF_METADATA_BASE_CLASS (mxf_metadata_sequence_parent_class)->to_structure
2917       (m);
2918   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (m);
2919   guint i;
2920   gchar str[48];
2921
2922   mxf_ul_to_string (&self->data_definition, str);
2923   gst_structure_id_set (ret, MXF_QUARK (DATA_DEFINITION), G_TYPE_STRING, str,
2924       MXF_QUARK (DURATION), G_TYPE_INT64, self->duration, NULL);
2925
2926   if (self->n_structural_components > 0) {
2927     GValue arr = { 0, }
2928     , val = {
2929     0,};
2930
2931     g_value_init (&arr, GST_TYPE_ARRAY);
2932
2933     for (i = 0; i < self->n_structural_components; i++) {
2934       GstStructure *s;
2935
2936       if (self->structural_components[i] == NULL)
2937         continue;
2938
2939       g_value_init (&val, GST_TYPE_STRUCTURE);
2940
2941       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE
2942           (self->structural_components[i]));
2943       gst_value_set_structure (&val, s);
2944       gst_structure_free (s);
2945       gst_value_array_append_value (&arr, &val);
2946       g_value_unset (&val);
2947     }
2948
2949     if (gst_value_array_get_size (&arr) > 0)
2950       gst_structure_id_set_value (ret, MXF_QUARK (STRUCTURAL_COMPONENTS), &arr);
2951
2952     g_value_unset (&arr);
2953   }
2954
2955   return ret;
2956 }
2957
2958 static GList *
2959 mxf_metadata_sequence_write_tags (MXFMetadataBase * m, MXFPrimerPack * primer)
2960 {
2961   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (m);
2962   GList *ret =
2963       MXF_METADATA_BASE_CLASS (mxf_metadata_sequence_parent_class)->write_tags
2964       (m, primer);
2965   MXFLocalTag *t;
2966
2967   t = g_slice_new0 (MXFLocalTag);
2968   memcpy (&t->ul, MXF_UL (DATA_DEFINITION), 16);
2969   t->size = 16;
2970   t->data = g_slice_alloc (t->size);
2971   t->g_slice = TRUE;
2972   memcpy (t->data, &self->data_definition, 16);
2973   mxf_primer_pack_add_mapping (primer, 0x0201, &t->ul);
2974   ret = g_list_prepend (ret, t);
2975
2976   t = g_slice_new0 (MXFLocalTag);
2977   memcpy (&t->ul, MXF_UL (DURATION), 16);
2978   t->size = 8;
2979   t->data = g_slice_alloc (t->size);
2980   t->g_slice = TRUE;
2981   GST_WRITE_UINT64_BE (t->data, self->duration);
2982   mxf_primer_pack_add_mapping (primer, 0x0202, &t->ul);
2983   ret = g_list_prepend (ret, t);
2984
2985   if (self->structural_components) {
2986     guint i;
2987     t = g_slice_new0 (MXFLocalTag);
2988     memcpy (&t->ul, MXF_UL (STRUCTURAL_COMPONENTS), 16);
2989     t->size = 8 + 16 * self->n_structural_components;
2990     t->data = g_slice_alloc0 (t->size);
2991     t->g_slice = TRUE;
2992
2993     GST_WRITE_UINT32_BE (t->data, self->n_structural_components);
2994     GST_WRITE_UINT32_BE (t->data + 4, 16);
2995     for (i = 0; i < self->n_structural_components; i++) {
2996       if (!self->structural_components[i])
2997         continue;
2998
2999       memcpy (t->data + 8 + i * 16,
3000           &MXF_METADATA_BASE (self->structural_components[i])->instance_uid,
3001           16);
3002     }
3003
3004     mxf_primer_pack_add_mapping (primer, 0x1001, &t->ul);
3005     ret = g_list_prepend (ret, t);
3006   }
3007
3008   return ret;
3009 }
3010
3011 static void
3012 mxf_metadata_sequence_init (MXFMetadataSequence * self)
3013 {
3014   self->duration = -1;
3015 }
3016
3017 static void
3018 mxf_metadata_sequence_class_init (MXFMetadataSequenceClass * klass)
3019 {
3020   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3021   GObjectClass *object_class = (GObjectClass *) klass;
3022   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3023
3024   object_class->finalize = mxf_metadata_sequence_finalize;
3025   metadata_base_class->handle_tag = mxf_metadata_sequence_handle_tag;
3026   metadata_base_class->resolve = mxf_metadata_sequence_resolve;
3027   metadata_base_class->name_quark = MXF_QUARK (SEQUENCE);
3028   metadata_base_class->to_structure = mxf_metadata_sequence_to_structure;
3029   metadata_base_class->write_tags = mxf_metadata_sequence_write_tags;
3030   metadata_class->type = 0x010f;
3031 }
3032
3033 G_DEFINE_TYPE (MXFMetadataStructuralComponent,
3034     mxf_metadata_structural_component, MXF_TYPE_METADATA);
3035
3036 static gboolean
3037 mxf_metadata_structural_component_handle_tag (MXFMetadataBase * metadata,
3038     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3039     guint tag_size)
3040 {
3041   MXFMetadataStructuralComponent *self =
3042       MXF_METADATA_STRUCTURAL_COMPONENT (metadata);
3043   gboolean ret = TRUE;
3044 #ifndef GST_DISABLE_GST_DEBUG
3045   gchar str[48];
3046 #endif
3047
3048   switch (tag) {
3049     case 0x0201:
3050       if (tag_size != 16)
3051         goto error;
3052       memcpy (&self->data_definition, tag_data, 16);
3053       GST_DEBUG ("  data definition = %s",
3054           mxf_ul_to_string (&self->data_definition, str));
3055       break;
3056     case 0x0202:
3057       if (tag_size != 8)
3058         goto error;
3059       self->duration = GST_READ_UINT64_BE (tag_data);
3060       GST_DEBUG ("  duration = %" G_GINT64_FORMAT, self->duration);
3061       break;
3062     default:
3063       ret =
3064           MXF_METADATA_BASE_CLASS
3065           (mxf_metadata_structural_component_parent_class)->handle_tag
3066           (metadata, primer, tag, tag_data, tag_size);
3067       break;
3068   }
3069
3070   return ret;
3071
3072 error:
3073
3074   GST_ERROR ("Invalid structural component local tag 0x%04x of size %u", tag,
3075       tag_size);
3076
3077   return FALSE;
3078 }
3079
3080 static GstStructure *
3081 mxf_metadata_structural_component_to_structure (MXFMetadataBase * m)
3082 {
3083   GstStructure *ret =
3084       MXF_METADATA_BASE_CLASS
3085       (mxf_metadata_structural_component_parent_class)->to_structure (m);
3086   MXFMetadataStructuralComponent *self = MXF_METADATA_STRUCTURAL_COMPONENT (m);
3087   gchar str[48];
3088
3089   mxf_ul_to_string (&self->data_definition, str);
3090   gst_structure_id_set (ret, MXF_QUARK (DATA_DEFINITION), G_TYPE_STRING, str,
3091       MXF_QUARK (DURATION), G_TYPE_INT64, self->duration, NULL);
3092
3093   return ret;
3094 }
3095
3096 static GList *
3097 mxf_metadata_structural_component_write_tags (MXFMetadataBase * m,
3098     MXFPrimerPack * primer)
3099 {
3100   MXFMetadataStructuralComponent *self = MXF_METADATA_STRUCTURAL_COMPONENT (m);
3101   GList *ret =
3102       MXF_METADATA_BASE_CLASS
3103       (mxf_metadata_structural_component_parent_class)->write_tags (m, primer);
3104   MXFLocalTag *t;
3105
3106   t = g_slice_new0 (MXFLocalTag);
3107   memcpy (&t->ul, MXF_UL (DATA_DEFINITION), 16);
3108   t->size = 16;
3109   t->data = g_slice_alloc (t->size);
3110   t->g_slice = TRUE;
3111   memcpy (t->data, &self->data_definition, 16);
3112   mxf_primer_pack_add_mapping (primer, 0x0201, &t->ul);
3113   ret = g_list_prepend (ret, t);
3114
3115   t = g_slice_new0 (MXFLocalTag);
3116   memcpy (&t->ul, MXF_UL (DURATION), 16);
3117   t->size = 8;
3118   t->data = g_slice_alloc (t->size);
3119   t->g_slice = TRUE;
3120   GST_WRITE_UINT64_BE (t->data, self->duration);
3121   mxf_primer_pack_add_mapping (primer, 0x0202, &t->ul);
3122   ret = g_list_prepend (ret, t);
3123
3124   return ret;
3125 }
3126
3127 static void
3128 mxf_metadata_structural_component_init (MXFMetadataStructuralComponent * self)
3129 {
3130   self->duration = -1;
3131 }
3132
3133 static void
3134     mxf_metadata_structural_component_class_init
3135     (MXFMetadataStructuralComponentClass * klass)
3136 {
3137   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3138
3139   metadata_base_class->handle_tag =
3140       mxf_metadata_structural_component_handle_tag;
3141   metadata_base_class->to_structure =
3142       mxf_metadata_structural_component_to_structure;
3143   metadata_base_class->write_tags =
3144       mxf_metadata_structural_component_write_tags;
3145 }
3146
3147 G_DEFINE_TYPE (MXFMetadataTimecodeComponent, mxf_metadata_timecode_component,
3148     MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
3149
3150 static gboolean
3151 mxf_metadata_timecode_component_handle_tag (MXFMetadataBase * metadata,
3152     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3153     guint tag_size)
3154 {
3155   MXFMetadataTimecodeComponent *self =
3156       MXF_METADATA_TIMECODE_COMPONENT (metadata);
3157   gboolean ret = TRUE;
3158
3159   switch (tag) {
3160     case 0x1502:
3161       if (tag_size != 2)
3162         goto error;
3163       self->rounded_timecode_base = GST_READ_UINT16_BE (tag_data);
3164       GST_DEBUG ("  rounded timecode base = %u", self->rounded_timecode_base);
3165       break;
3166     case 0x1501:
3167       if (tag_size != 8)
3168         goto error;
3169       self->start_timecode = GST_READ_UINT64_BE (tag_data);
3170       GST_DEBUG ("  start timecode = %" G_GINT64_FORMAT, self->start_timecode);
3171       break;
3172     case 0x1503:
3173       if (tag_size != 1)
3174         goto error;
3175       self->drop_frame = (GST_READ_UINT8 (tag_data) != 0);
3176       GST_DEBUG ("  drop frame = %s", (self->drop_frame) ? "yes" : "no");
3177       break;
3178     default:
3179       ret =
3180           MXF_METADATA_BASE_CLASS
3181           (mxf_metadata_timecode_component_parent_class)->handle_tag (metadata,
3182           primer, tag, tag_data, tag_size);
3183       break;
3184   }
3185
3186   return ret;
3187
3188 error:
3189
3190   GST_ERROR ("Invalid timecode component local tag 0x%04x of size %u", tag,
3191       tag_size);
3192
3193   return FALSE;
3194 }
3195
3196 static GstStructure *
3197 mxf_metadata_timecode_component_to_structure (MXFMetadataBase * m)
3198 {
3199   GstStructure *ret =
3200       MXF_METADATA_BASE_CLASS
3201       (mxf_metadata_timecode_component_parent_class)->to_structure (m);
3202   MXFMetadataTimecodeComponent *self = MXF_METADATA_TIMECODE_COMPONENT (m);
3203
3204   gst_structure_id_set (ret, MXF_QUARK (START_TIMECODE), G_TYPE_INT64,
3205       self->start_timecode, MXF_QUARK (ROUNDED_TIMECODE_BASE), G_TYPE_UINT,
3206       self->rounded_timecode_base, MXF_QUARK (DROP_FRAME), G_TYPE_BOOLEAN,
3207       self->drop_frame, NULL);
3208
3209   return ret;
3210 }
3211
3212 static GList *
3213 mxf_metadata_timecode_component_write_tags (MXFMetadataBase * m,
3214     MXFPrimerPack * primer)
3215 {
3216   MXFMetadataTimecodeComponent *self = MXF_METADATA_TIMECODE_COMPONENT (m);
3217   GList *ret =
3218       MXF_METADATA_BASE_CLASS
3219       (mxf_metadata_timecode_component_parent_class)->write_tags (m, primer);
3220   MXFLocalTag *t;
3221
3222   t = g_slice_new0 (MXFLocalTag);
3223   memcpy (&t->ul, MXF_UL (ROUNDED_TIMECODE_BASE), 16);
3224   t->size = 2;
3225   t->data = g_slice_alloc (t->size);
3226   t->g_slice = TRUE;
3227   GST_WRITE_UINT16_BE (t->data, self->rounded_timecode_base);
3228   mxf_primer_pack_add_mapping (primer, 0x1502, &t->ul);
3229   ret = g_list_prepend (ret, t);
3230
3231   t = g_slice_new0 (MXFLocalTag);
3232   memcpy (&t->ul, MXF_UL (START_TIMECODE), 16);
3233   t->size = 8;
3234   t->data = g_slice_alloc (t->size);
3235   t->g_slice = TRUE;
3236   GST_WRITE_UINT64_BE (t->data, self->start_timecode);
3237   mxf_primer_pack_add_mapping (primer, 0x1501, &t->ul);
3238   ret = g_list_prepend (ret, t);
3239
3240   t = g_slice_new0 (MXFLocalTag);
3241   memcpy (&t->ul, MXF_UL (DROP_FRAME), 16);
3242   t->size = 1;
3243   t->data = g_slice_alloc (t->size);
3244   t->g_slice = TRUE;
3245   GST_WRITE_UINT8 (t->data, (self->drop_frame) ? 1 : 0);
3246   mxf_primer_pack_add_mapping (primer, 0x1503, &t->ul);
3247   ret = g_list_prepend (ret, t);
3248
3249   return ret;
3250 }
3251
3252 static void
3253 mxf_metadata_timecode_component_init (MXFMetadataTimecodeComponent * self)
3254 {
3255
3256 }
3257
3258 static void
3259 mxf_metadata_timecode_component_class_init (MXFMetadataTimecodeComponentClass *
3260     klass)
3261 {
3262   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3263   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3264
3265   metadata_base_class->handle_tag = mxf_metadata_timecode_component_handle_tag;
3266   metadata_base_class->name_quark = MXF_QUARK (TIMECODE_COMPONENT);
3267   metadata_base_class->to_structure =
3268       mxf_metadata_timecode_component_to_structure;
3269   metadata_base_class->write_tags = mxf_metadata_timecode_component_write_tags;
3270   metadata_class->type = 0x0114;
3271 }
3272
3273 G_DEFINE_TYPE (MXFMetadataSourceClip, mxf_metadata_source_clip,
3274     MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
3275
3276 static gboolean
3277 mxf_metadata_source_clip_handle_tag (MXFMetadataBase * metadata,
3278     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3279     guint tag_size)
3280 {
3281   MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (metadata);
3282   gboolean ret = TRUE;
3283 #ifndef GST_DISABLE_GST_DEBUG
3284   gchar str[96];
3285 #endif
3286
3287   switch (tag) {
3288     case 0x1201:
3289       if (tag_size != 8)
3290         goto error;
3291
3292       self->start_position = GST_READ_UINT64_BE (tag_data);
3293       GST_DEBUG ("  start position = %" G_GINT64_FORMAT, self->start_position);
3294       break;
3295     case 0x1101:
3296       if (tag_size != 32)
3297         goto error;
3298
3299       memcpy (&self->source_package_id, tag_data, 32);
3300       GST_DEBUG ("  source package id = %s",
3301           mxf_umid_to_string (&self->source_package_id, str));
3302       break;
3303     case 0x1102:
3304       if (tag_size != 4)
3305         goto error;
3306
3307       self->source_track_id = GST_READ_UINT32_BE (tag_data);
3308       GST_DEBUG ("  source track id = %u", self->source_track_id);
3309       break;
3310     default:
3311       ret =
3312           MXF_METADATA_BASE_CLASS
3313           (mxf_metadata_source_clip_parent_class)->handle_tag (metadata, primer,
3314           tag, tag_data, tag_size);
3315       break;
3316   }
3317
3318   return ret;
3319
3320 error:
3321
3322   GST_ERROR ("Invalid source clip local tag 0x%04x of size %u", tag, tag_size);
3323
3324   return FALSE;
3325 }
3326
3327 static gboolean
3328 mxf_metadata_source_clip_resolve (MXFMetadataBase * m, GHashTable * metadata)
3329 {
3330   MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (m);
3331   MXFMetadataBase *current = NULL;
3332   GHashTableIter iter;
3333
3334   g_hash_table_iter_init (&iter, metadata);
3335
3336   while (g_hash_table_iter_next (&iter, NULL, (gpointer) & current)) {
3337     if (MXF_IS_METADATA_SOURCE_PACKAGE (current)) {
3338       MXFMetadataGenericPackage *p = MXF_METADATA_GENERIC_PACKAGE (current);
3339
3340       if (mxf_umid_is_equal (&p->package_uid, &self->source_package_id)) {
3341         self->source_package = MXF_METADATA_SOURCE_PACKAGE (current);
3342         break;
3343       }
3344     }
3345   }
3346
3347   return
3348       MXF_METADATA_BASE_CLASS (mxf_metadata_source_clip_parent_class)->resolve
3349       (m, metadata);
3350 }
3351
3352 static GstStructure *
3353 mxf_metadata_source_clip_to_structure (MXFMetadataBase * m)
3354 {
3355   GstStructure *ret =
3356       MXF_METADATA_BASE_CLASS
3357       (mxf_metadata_source_clip_parent_class)->to_structure (m);
3358   MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (m);
3359   gchar str[96];
3360
3361   mxf_umid_to_string (&self->source_package_id, str);
3362   gst_structure_id_set (ret, MXF_QUARK (START_POSITION), G_TYPE_INT64,
3363       self->start_position, MXF_QUARK (SOURCE_PACKAGE), G_TYPE_STRING, str,
3364       MXF_QUARK (SOURCE_TRACK_ID), G_TYPE_UINT, self->source_track_id, NULL);
3365
3366   return ret;
3367 }
3368
3369 static GList *
3370 mxf_metadata_source_clip_write_tags (MXFMetadataBase * m,
3371     MXFPrimerPack * primer)
3372 {
3373   MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (m);
3374   GList *ret =
3375       MXF_METADATA_BASE_CLASS
3376       (mxf_metadata_source_clip_parent_class)->write_tags (m, primer);
3377   MXFLocalTag *t;
3378
3379   t = g_slice_new0 (MXFLocalTag);
3380   memcpy (&t->ul, MXF_UL (START_POSITION), 16);
3381   t->size = 8;
3382   t->data = g_slice_alloc (t->size);
3383   t->g_slice = TRUE;
3384   GST_WRITE_UINT64_BE (t->data, self->start_position);
3385   mxf_primer_pack_add_mapping (primer, 0x1201, &t->ul);
3386   ret = g_list_prepend (ret, t);
3387
3388   t = g_slice_new0 (MXFLocalTag);
3389   memcpy (&t->ul, MXF_UL (SOURCE_PACKAGE_ID), 16);
3390   t->size = 32;
3391   t->data = g_slice_alloc (t->size);
3392   t->g_slice = TRUE;
3393   memcpy (t->data, &self->source_package_id, 32);
3394   mxf_primer_pack_add_mapping (primer, 0x1101, &t->ul);
3395   ret = g_list_prepend (ret, t);
3396
3397   t = g_slice_new0 (MXFLocalTag);
3398   memcpy (&t->ul, MXF_UL (SOURCE_TRACK_ID), 16);
3399   t->size = 4;
3400   t->data = g_slice_alloc (t->size);
3401   t->g_slice = TRUE;
3402   GST_WRITE_UINT32_BE (t->data, self->source_track_id);
3403   mxf_primer_pack_add_mapping (primer, 0x1102, &t->ul);
3404   ret = g_list_prepend (ret, t);
3405
3406   return ret;
3407 }
3408
3409 static void
3410 mxf_metadata_source_clip_init (MXFMetadataSourceClip * self)
3411 {
3412
3413 }
3414
3415 static void
3416 mxf_metadata_source_clip_class_init (MXFMetadataSourceClipClass * klass)
3417 {
3418   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3419   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3420
3421   metadata_base_class->handle_tag = mxf_metadata_source_clip_handle_tag;
3422   metadata_base_class->resolve = mxf_metadata_source_clip_resolve;
3423   metadata_base_class->name_quark = MXF_QUARK (SOURCE_CLIP);
3424   metadata_base_class->to_structure = mxf_metadata_source_clip_to_structure;
3425   metadata_base_class->write_tags = mxf_metadata_source_clip_write_tags;
3426   metadata_class->type = 0x0111;
3427 }
3428
3429 G_DEFINE_TYPE (MXFMetadataDMSourceClip, mxf_metadata_dm_source_clip,
3430     MXF_TYPE_METADATA_SOURCE_CLIP);
3431
3432 static void
3433 mxf_metadata_dm_source_clip_finalize (GObject * object)
3434 {
3435   MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (object);
3436
3437   g_free (self->track_ids);
3438   self->track_ids = NULL;
3439
3440   G_OBJECT_CLASS (mxf_metadata_dm_source_clip_parent_class)->finalize (object);
3441 }
3442
3443 static gboolean
3444 mxf_metadata_dm_source_clip_handle_tag (MXFMetadataBase * metadata,
3445     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3446     guint tag_size)
3447 {
3448   MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (metadata);
3449   gboolean ret = TRUE;
3450
3451   switch (tag) {
3452     case 0x6103:
3453     {
3454       guint32 len;
3455       guint i;
3456
3457       if (tag_size < 8)
3458         goto error;
3459
3460       len = GST_READ_UINT32_BE (tag_data);
3461       GST_DEBUG ("  number of track ids = %u", len);
3462       if (len == 0)
3463         return TRUE;
3464
3465       if (GST_READ_UINT32_BE (tag_data + 4) != 4)
3466         goto error;
3467
3468       if (tag_size < 8 + 4 * len)
3469         goto error;
3470
3471       tag_data += 8;
3472       tag_size -= 8;
3473
3474       self->n_track_ids = len;
3475       self->track_ids = g_new0 (guint32, len);
3476
3477       for (i = 0; i < len; i++) {
3478         self->track_ids[i] = GST_READ_UINT32_BE (tag_data);
3479         GST_DEBUG ("    track id %u = %u", i, self->track_ids[i]);
3480         tag_data += 4;
3481         tag_size -= 4;
3482       }
3483       break;
3484     }
3485     default:
3486       ret =
3487           MXF_METADATA_BASE_CLASS
3488           (mxf_metadata_dm_source_clip_parent_class)->handle_tag (metadata,
3489           primer, tag, tag_data, tag_size);
3490       break;
3491   }
3492
3493   return ret;
3494
3495 error:
3496
3497   GST_ERROR ("Invalid DM source clip local tag 0x%04x of size %u", tag,
3498       tag_size);
3499
3500   return FALSE;
3501 }
3502
3503 static GstStructure *
3504 mxf_metadata_dm_source_clip_to_structure (MXFMetadataBase * m)
3505 {
3506   GstStructure *ret =
3507       MXF_METADATA_BASE_CLASS
3508       (mxf_metadata_dm_source_clip_parent_class)->to_structure (m);
3509   MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (m);
3510   guint i;
3511
3512   if (self->n_track_ids > 0) {
3513     GValue arr = { 0, }
3514     , val = {
3515     0,};
3516
3517     g_value_init (&arr, GST_TYPE_ARRAY);
3518
3519     for (i = 0; i < self->n_track_ids; i++) {
3520       g_value_init (&val, G_TYPE_UINT);
3521
3522       g_value_set_uint (&val, self->track_ids[i]);
3523       gst_value_array_append_value (&arr, &val);
3524       g_value_unset (&val);
3525     }
3526
3527     if (gst_value_array_get_size (&arr) > 0)
3528       gst_structure_id_set_value (ret, MXF_QUARK (TRACK_IDS), &arr);
3529
3530     g_value_unset (&arr);
3531   }
3532
3533   return ret;
3534 }
3535
3536 static GList *
3537 mxf_metadata_dm_source_clip_write_tags (MXFMetadataBase * m,
3538     MXFPrimerPack * primer)
3539 {
3540   MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (m);
3541   GList *ret =
3542       MXF_METADATA_BASE_CLASS
3543       (mxf_metadata_dm_source_clip_parent_class)->write_tags (m, primer);
3544   MXFLocalTag *t;
3545
3546   if (self->track_ids) {
3547     guint i;
3548
3549     t = g_slice_new0 (MXFLocalTag);
3550     memcpy (&t->ul, MXF_UL (DM_SOURCECLIP_TRACK_IDS), 16);
3551     t->size = 8 + 4 * self->n_track_ids;
3552     t->data = g_slice_alloc (t->size);
3553     t->g_slice = TRUE;
3554     GST_WRITE_UINT32_BE (t->data, self->n_track_ids);
3555     GST_WRITE_UINT32_BE (t->data + 4, 4);
3556     for (i = 0; i < self->n_track_ids; i++)
3557       GST_WRITE_UINT32_BE (t->data + 8 + i * 4, self->track_ids[i]);
3558     mxf_primer_pack_add_mapping (primer, 0x6103, &t->ul);
3559     ret = g_list_prepend (ret, t);
3560   }
3561
3562   return ret;
3563 }
3564
3565 static void
3566 mxf_metadata_dm_source_clip_init (MXFMetadataDMSourceClip * self)
3567 {
3568
3569 }
3570
3571 static void
3572 mxf_metadata_dm_source_clip_class_init (MXFMetadataDMSourceClipClass * klass)
3573 {
3574   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3575   GObjectClass *object_class = (GObjectClass *) klass;
3576   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3577
3578   object_class->finalize = mxf_metadata_dm_source_clip_finalize;
3579   metadata_base_class->handle_tag = mxf_metadata_dm_source_clip_handle_tag;
3580   metadata_base_class->name_quark = MXF_QUARK (DM_SOURCE_CLIP);
3581   metadata_base_class->to_structure = mxf_metadata_dm_source_clip_to_structure;
3582   metadata_base_class->write_tags = mxf_metadata_dm_source_clip_write_tags;
3583   metadata_class->type = 0x0145;
3584 }
3585
3586 G_DEFINE_TYPE (MXFMetadataDMSegment, mxf_metadata_dm_segment,
3587     MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
3588
3589 static void
3590 mxf_metadata_dm_segment_finalize (GObject * object)
3591 {
3592   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (object);
3593
3594   g_free (self->track_ids);
3595   self->track_ids = NULL;
3596
3597   g_free (self->event_comment);
3598   self->event_comment = NULL;
3599
3600   G_OBJECT_CLASS (mxf_metadata_dm_segment_parent_class)->finalize (object);
3601 }
3602
3603 static gboolean
3604 mxf_metadata_dm_segment_handle_tag (MXFMetadataBase * metadata,
3605     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3606     guint tag_size)
3607 {
3608   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (metadata);
3609   gboolean ret = TRUE;
3610 #ifndef GST_DISABLE_GST_DEBUG
3611   gchar str[48];
3612 #endif
3613
3614   switch (tag) {
3615     case 0x0601:
3616       if (tag_size != 8)
3617         goto error;
3618       self->event_start_position = GST_READ_UINT64_BE (tag_data);
3619       GST_DEBUG ("  event start position = %" G_GINT64_FORMAT,
3620           self->event_start_position);
3621       break;
3622     case 0x0602:
3623       self->event_comment = mxf_utf16_to_utf8 (tag_data, tag_size);
3624       GST_DEBUG ("  event comment = %s", GST_STR_NULL (self->event_comment));
3625       break;
3626     case 0x6102:
3627     {
3628       guint32 len;
3629       guint i;
3630
3631       if (tag_size < 8)
3632         goto error;
3633       len = GST_READ_UINT32_BE (tag_data);
3634       GST_DEBUG ("  number of track ids = %u", len);
3635       if (len == 0)
3636         return TRUE;
3637
3638       if (GST_READ_UINT32_BE (tag_data + 4) != 4)
3639         goto error;
3640
3641       if (len * 4 + 8 < tag_size)
3642         goto error;
3643
3644       self->n_track_ids = len;
3645       self->track_ids = g_new0 (guint32, len);
3646
3647       tag_data += 8;
3648       tag_size -= 8;
3649
3650       for (i = 0; i < len; i++) {
3651         self->track_ids[i] = GST_READ_UINT32_BE (tag_data);
3652         GST_DEBUG ("    track id %u = %u", i, self->track_ids[i]);
3653         tag_data += 4;
3654         tag_size -= 4;
3655       }
3656       break;
3657     }
3658     case 0x6101:
3659       if (tag_size != 16)
3660         goto error;
3661
3662       memcpy (&self->dm_framework_uid, tag_data, 16);
3663       GST_DEBUG ("  DM framework = %s",
3664           mxf_uuid_to_string (&self->dm_framework_uid, str));
3665       break;
3666     default:
3667       ret =
3668           MXF_METADATA_BASE_CLASS
3669           (mxf_metadata_dm_segment_parent_class)->handle_tag (metadata, primer,
3670           tag, tag_data, tag_size);
3671       break;
3672   }
3673
3674   return ret;
3675
3676 error:
3677
3678   GST_ERROR ("Invalid DM segment local tag 0x%04x of size %u", tag, tag_size);
3679
3680   return FALSE;
3681 }
3682
3683 static gboolean
3684 mxf_metadata_dm_segment_resolve (MXFMetadataBase * m, GHashTable * metadata)
3685 {
3686   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (m);
3687   MXFMetadataBase *current = NULL;
3688
3689   current = g_hash_table_lookup (metadata, &self->dm_framework_uid);
3690   if (current && MXF_IS_DESCRIPTIVE_METADATA_FRAMEWORK (current)) {
3691     if (mxf_metadata_base_resolve (current, metadata)) {
3692       self->dm_framework = MXF_DESCRIPTIVE_METADATA_FRAMEWORK (current);
3693     } else {
3694       GST_ERROR ("Couldn't resolve DM framework");
3695       return FALSE;
3696     }
3697   } else {
3698     GST_ERROR ("Couldn't find DM framework");
3699     return FALSE;
3700   }
3701
3702
3703   return
3704       MXF_METADATA_BASE_CLASS (mxf_metadata_dm_segment_parent_class)->resolve
3705       (m, metadata);
3706 }
3707
3708 static GstStructure *
3709 mxf_metadata_dm_segment_to_structure (MXFMetadataBase * m)
3710 {
3711   GstStructure *ret =
3712       MXF_METADATA_BASE_CLASS
3713       (mxf_metadata_dm_segment_parent_class)->to_structure (m);
3714   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (m);
3715   guint i;
3716
3717   gst_structure_id_set (ret, MXF_QUARK (EVENT_START_POSITION), G_TYPE_INT64,
3718       self->event_start_position, NULL);
3719
3720   if (self->event_comment)
3721     gst_structure_id_set (ret, MXF_QUARK (EVENT_COMMENT), G_TYPE_STRING,
3722         self->event_comment, NULL);
3723   /* FIXME: DMS1 doesn't support serializing to a structure yet */
3724 #if 0
3725   if (self->dm_framework) {
3726     GstStructure *s =
3727         mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->dm_framework));
3728
3729     gst_structure_id_set (ret, MXF_QUARK (DM_FRAMEWORK), GST_TYPE_STRUCTURE,
3730         s, NULL);
3731     gst_structure_free (s);
3732   }
3733 #endif
3734
3735   if (self->n_track_ids > 0) {
3736     GValue arr = { 0, }
3737     , val = {
3738     0,};
3739
3740     g_value_init (&arr, GST_TYPE_ARRAY);
3741
3742     for (i = 0; i < self->n_track_ids; i++) {
3743       g_value_init (&val, G_TYPE_UINT);
3744
3745       g_value_set_uint (&val, self->track_ids[i]);
3746       gst_value_array_append_value (&arr, &val);
3747       g_value_unset (&val);
3748     }
3749
3750     if (gst_value_array_get_size (&arr) > 0)
3751       gst_structure_id_set_value (ret, MXF_QUARK (TRACK_IDS), &arr);
3752
3753     g_value_unset (&arr);
3754   }
3755
3756   return ret;
3757 }
3758
3759 static GList *
3760 mxf_metadata_dm_segment_write_tags (MXFMetadataBase * m, MXFPrimerPack * primer)
3761 {
3762   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (m);
3763   GList *ret =
3764       MXF_METADATA_BASE_CLASS (mxf_metadata_dm_segment_parent_class)->write_tags
3765       (m, primer);
3766   MXFLocalTag *t;
3767
3768   if (self->event_start_position != -1) {
3769     t = g_slice_new0 (MXFLocalTag);
3770     memcpy (&t->ul, MXF_UL (EVENT_START_POSITION), 16);
3771     t->size = 8;
3772     t->data = g_slice_alloc (t->size);
3773     t->g_slice = TRUE;
3774     GST_WRITE_UINT64_BE (t->data, self->event_start_position);
3775     mxf_primer_pack_add_mapping (primer, 0x0601, &t->ul);
3776     ret = g_list_prepend (ret, t);
3777   }
3778
3779   if (self->event_comment) {
3780     t = g_slice_new0 (MXFLocalTag);
3781     memcpy (&t->ul, MXF_UL (EVENT_COMMENT), 16);
3782     t->data = mxf_utf8_to_utf16 (self->event_comment, &t->size);
3783     mxf_primer_pack_add_mapping (primer, 0x0602, &t->ul);
3784     ret = g_list_prepend (ret, t);
3785   }
3786
3787   if (self->track_ids) {
3788     guint i;
3789
3790     t = g_slice_new0 (MXFLocalTag);
3791     memcpy (&t->ul, MXF_UL (DM_SEGMENT_TRACK_IDS), 16);
3792     t->size = 8 + 4 * self->n_track_ids;
3793     t->data = g_slice_alloc (t->size);
3794     t->g_slice = TRUE;
3795     GST_WRITE_UINT32_BE (t->data, self->n_track_ids);
3796     GST_WRITE_UINT32_BE (t->data + 4, 4);
3797     for (i = 0; i < self->n_track_ids; i++)
3798       GST_WRITE_UINT32_BE (t->data + 8 + i * 4, self->track_ids[i]);
3799     mxf_primer_pack_add_mapping (primer, 0x6102, &t->ul);
3800     ret = g_list_prepend (ret, t);
3801   }
3802
3803   if (self->dm_framework) {
3804     t = g_slice_new0 (MXFLocalTag);
3805     memcpy (&t->ul, MXF_UL (DM_FRAMEWORK), 16);
3806     t->size = 16;
3807     t->data = g_slice_alloc (t->size);
3808     t->g_slice = TRUE;
3809     memcpy (t->data, &MXF_METADATA_BASE (self->dm_framework)->instance_uid, 16);
3810     mxf_primer_pack_add_mapping (primer, 0x6101, &t->ul);
3811     ret = g_list_prepend (ret, t);
3812   }
3813
3814   return ret;
3815 }
3816
3817 static void
3818 mxf_metadata_dm_segment_init (MXFMetadataDMSegment * self)
3819 {
3820   self->event_start_position = -1;
3821 }
3822
3823 static void
3824 mxf_metadata_dm_segment_class_init (MXFMetadataDMSegmentClass * klass)
3825 {
3826   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3827   GObjectClass *object_class = (GObjectClass *) klass;
3828   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3829
3830   object_class->finalize = mxf_metadata_dm_segment_finalize;
3831   metadata_base_class->handle_tag = mxf_metadata_dm_segment_handle_tag;
3832   metadata_base_class->resolve = mxf_metadata_dm_segment_resolve;
3833   metadata_base_class->name_quark = MXF_QUARK (DM_SEGMENT);
3834   metadata_base_class->to_structure = mxf_metadata_dm_segment_to_structure;
3835   metadata_base_class->write_tags = mxf_metadata_dm_segment_write_tags;
3836   metadata_class->type = 0x0141;
3837 }
3838
3839 G_DEFINE_ABSTRACT_TYPE (MXFMetadataGenericDescriptor,
3840     mxf_metadata_generic_descriptor, MXF_TYPE_METADATA);
3841
3842 static void
3843 mxf_metadata_generic_descriptor_finalize (GObject * object)
3844 {
3845   MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (object);
3846
3847   g_free (self->locators_uids);
3848   self->locators_uids = NULL;
3849
3850   g_free (self->locators);
3851   self->locators = NULL;
3852
3853   G_OBJECT_CLASS (mxf_metadata_generic_descriptor_parent_class)->finalize
3854       (object);
3855 }
3856
3857 static gboolean
3858 mxf_metadata_generic_descriptor_handle_tag (MXFMetadataBase * metadata,
3859     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3860     guint tag_size)
3861 {
3862   MXFMetadataGenericDescriptor *self =
3863       MXF_METADATA_GENERIC_DESCRIPTOR (metadata);
3864   gboolean ret = TRUE;
3865 #ifndef GST_DISABLE_GST_DEBUG
3866   gchar str[48];
3867 #endif
3868
3869   switch (tag) {
3870     case 0x2f01:
3871       if (!mxf_uuid_array_parse (&self->locators_uids, &self->n_locators,
3872               tag_data, tag_size))
3873         goto error;
3874
3875       GST_DEBUG ("  number of locators = %u", self->n_locators);
3876 #ifndef GST_DISABLE_GST_DEBUG
3877       {
3878         guint i;
3879         for (i = 0; i < self->n_locators; i++) {
3880           GST_DEBUG ("  locator %u = %s", i,
3881               mxf_uuid_to_string (&self->locators_uids[i], str));
3882         }
3883       }
3884 #endif
3885       break;
3886     default:
3887       ret =
3888           MXF_METADATA_BASE_CLASS
3889           (mxf_metadata_generic_descriptor_parent_class)->handle_tag (metadata,
3890           primer, tag, tag_data, tag_size);
3891       break;
3892   }
3893
3894   return ret;
3895
3896 error:
3897
3898   GST_ERROR ("Invalid generic descriptor local tag 0x%04x of size %u", tag,
3899       tag_size);
3900
3901   return FALSE;
3902 }
3903
3904 static gboolean
3905 mxf_metadata_generic_descriptor_resolve (MXFMetadataBase * m,
3906     GHashTable * metadata)
3907 {
3908   MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (m);
3909   MXFMetadataBase *current = NULL;
3910   guint i;
3911   gboolean have_locator = FALSE;
3912
3913   if (self->locators)
3914     memset (self->locators, 0, sizeof (gpointer) * self->n_locators);
3915   else
3916     self->locators = g_new0 (MXFMetadataLocator *, self->n_locators);
3917   for (i = 0; i < self->n_locators; i++) {
3918     current = g_hash_table_lookup (metadata, &self->locators_uids[i]);
3919     if (current && MXF_IS_METADATA_LOCATOR (current)) {
3920       if (mxf_metadata_base_resolve (current, metadata)) {
3921         self->locators[i] = MXF_METADATA_LOCATOR (current);
3922         have_locator = TRUE;
3923       } else {
3924         GST_ERROR ("Couldn't resolve locator");
3925       }
3926     } else {
3927       GST_ERROR ("Locator not found");
3928     }
3929   }
3930
3931   if (!have_locator && self->n_locators > 0) {
3932     GST_ERROR ("Couldn't resolve a locator");
3933     return FALSE;
3934   }
3935
3936   return
3937       MXF_METADATA_BASE_CLASS
3938       (mxf_metadata_generic_descriptor_parent_class)->resolve (m, metadata);
3939 }
3940
3941 static GstStructure *
3942 mxf_metadata_generic_descriptor_to_structure (MXFMetadataBase * m)
3943 {
3944   GstStructure *ret =
3945       MXF_METADATA_BASE_CLASS
3946       (mxf_metadata_generic_descriptor_parent_class)->to_structure (m);
3947   MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (m);
3948   guint i;
3949
3950   if (self->n_locators > 0) {
3951     GValue arr = { 0, }
3952     , val = {
3953     0,};
3954
3955     g_value_init (&arr, GST_TYPE_ARRAY);
3956
3957     for (i = 0; i < self->n_locators; i++) {
3958       GstStructure *s;
3959
3960       if (self->locators[i] == NULL)
3961         continue;
3962
3963       g_value_init (&val, GST_TYPE_STRUCTURE);
3964
3965       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->locators
3966               [i]));
3967       gst_value_set_structure (&val, s);
3968       gst_structure_free (s);
3969       gst_value_array_append_value (&arr, &val);
3970       g_value_unset (&val);
3971     }
3972
3973     if (gst_value_array_get_size (&arr) > 0)
3974       gst_structure_id_set_value (ret, MXF_QUARK (LOCATORS), &arr);
3975
3976     g_value_unset (&arr);
3977   }
3978
3979   return ret;
3980 }
3981
3982 static GList *
3983 mxf_metadata_generic_descriptor_write_tags (MXFMetadataBase * m,
3984     MXFPrimerPack * primer)
3985 {
3986   MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (m);
3987   GList *ret =
3988       MXF_METADATA_BASE_CLASS
3989       (mxf_metadata_generic_descriptor_parent_class)->write_tags (m, primer);
3990   MXFLocalTag *t;
3991
3992   if (self->locators) {
3993     guint i;
3994
3995     t = g_slice_new0 (MXFLocalTag);
3996     memcpy (&t->ul, MXF_UL (LOCATORS), 16);
3997     t->size = 8 + 16 * self->n_locators;;
3998     t->data = g_slice_alloc0 (t->size);
3999     t->g_slice = TRUE;
4000     GST_WRITE_UINT32_BE (t->data, self->n_locators);
4001     GST_WRITE_UINT32_BE (t->data + 4, 16);
4002     for (i = 0; i < self->n_locators; i++) {
4003       if (!self->locators[i])
4004         continue;
4005       memcpy (t->data + 8 + 16 * i,
4006           &MXF_METADATA_BASE (self->locators[i])->instance_uid, 16);
4007     }
4008     mxf_primer_pack_add_mapping (primer, 0x2f01, &t->ul);
4009     ret = g_list_prepend (ret, t);
4010   }
4011
4012   return ret;
4013 }
4014
4015 static void
4016 mxf_metadata_generic_descriptor_init (MXFMetadataGenericDescriptor * self)
4017 {
4018
4019 }
4020
4021 static void
4022 mxf_metadata_generic_descriptor_class_init (MXFMetadataGenericDescriptorClass *
4023     klass)
4024 {
4025   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
4026   GObjectClass *object_class = (GObjectClass *) klass;
4027
4028   object_class->finalize = mxf_metadata_generic_descriptor_finalize;
4029   metadata_base_class->handle_tag = mxf_metadata_generic_descriptor_handle_tag;
4030   metadata_base_class->resolve = mxf_metadata_generic_descriptor_resolve;
4031   metadata_base_class->to_structure =
4032       mxf_metadata_generic_descriptor_to_structure;
4033   metadata_base_class->write_tags = mxf_metadata_generic_descriptor_write_tags;
4034 }
4035
4036 G_DEFINE_TYPE (MXFMetadataFileDescriptor, mxf_metadata_file_descriptor,
4037     MXF_TYPE_METADATA_GENERIC_DESCRIPTOR);
4038
4039 static gboolean
4040 mxf_metadata_file_descriptor_handle_tag (MXFMetadataBase * metadata,
4041     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
4042     guint tag_size)
4043 {
4044   MXFMetadataFileDescriptor *self = MXF_METADATA_FILE_DESCRIPTOR (metadata);
4045   gboolean ret = TRUE;
4046 #ifndef GST_DISABLE_GST_DEBUG
4047   gchar str[48];
4048 #endif
4049
4050   switch (tag) {
4051     case 0x3006:
4052       if (tag_size != 4)
4053         goto error;
4054       self->linked_track_id = GST_READ_UINT32_BE (tag_data);
4055       GST_DEBUG ("  linked track id = %u", self->linked_track_id);
4056       break;
4057     case 0x3001:
4058       if (!mxf_fraction_parse (&self->sample_rate, tag_data, tag_size))
4059         goto error;
4060       GST_DEBUG ("  sample rate = %d/%d", self->sample_rate.n,
4061           self->sample_rate.d);
4062       break;
4063     case 0x3002:
4064       if (tag_size != 8)
4065         goto error;
4066       self->container_duration = GST_READ_UINT64_BE (tag_data);
4067       GST_DEBUG ("  container duration = %" G_GINT64_FORMAT,
4068           self->container_duration);
4069       break;
4070     case 0x3004:
4071       if (tag_size != 16)
4072         goto error;
4073       memcpy (&self->essence_container, tag_data, 16);
4074       GST_DEBUG ("  essence container = %s",
4075           mxf_ul_to_string (&self->essence_container, str));
4076       break;
4077     case 0x3005:
4078       if (tag_size != 16)
4079         goto error;
4080       memcpy (&self->codec, tag_data, 16);
4081       GST_DEBUG ("  codec = %s", mxf_ul_to_string (&self->codec, str));
4082       break;
4083     default:
4084       ret =
4085           MXF_METADATA_BASE_CLASS
4086           (mxf_metadata_file_descriptor_parent_class)->handle_tag (metadata,
4087           primer, tag, tag_data, tag_size);
4088       break;
4089   }
4090
4091   return ret;
4092
4093 error:
4094
4095   GST_ERROR ("Invalid file descriptor local tag 0x%04x of size %u", tag,
4096       tag_size);
4097
4098   return FALSE;
4099 }
4100
4101 static GstStructure *
4102 mxf_metadata_file_descriptor_to_structure (MXFMetadataBase * m)
4103 {
4104   GstStructure *ret =
4105       MXF_METADATA_BASE_CLASS
4106       (mxf_metadata_file_descriptor_parent_class)->to_structure (m);
4107   MXFMetadataFileDescriptor *self = MXF_METADATA_FILE_DESCRIPTOR (m);
4108   gchar str[48];
4109
4110   if (self->linked_track_id)
4111     gst_structure_id_set (ret, MXF_QUARK (LINKED_TRACK_ID), G_TYPE_UINT,
4112         self->linked_track_id, NULL);
4113
4114   if (self->sample_rate.n && self->sample_rate.d)
4115     gst_structure_id_set (ret, MXF_QUARK (SAMPLE_RATE), GST_TYPE_FRACTION,
4116         self->sample_rate.n, self->sample_rate.d, NULL);
4117
4118   if (self->container_duration)
4119     gst_structure_id_set (ret, MXF_QUARK (CONTAINER_DURATION), G_TYPE_INT64,
4120         self->container_duration, NULL);
4121
4122   mxf_ul_to_string (&self->essence_container, str);
4123   gst_structure_id_set (ret, MXF_QUARK (ESSENCE_CONTAINER), G_TYPE_STRING, str,
4124       NULL);
4125
4126   if (!mxf_ul_is_zero (&self->codec)) {
4127     mxf_ul_to_string (&self->codec, str);
4128     gst_structure_id_set (ret, MXF_QUARK (CODEC), G_TYPE_STRING, str, NULL);
4129   }
4130
4131   return ret;
4132 }
4133
4134 static GList *
4135 mxf_metadata_file_descriptor_write_tags (MXFMetadataBase * m,
4136     MXFPrimerPack * primer)
4137 {
4138   MXFMetadataFileDescriptor *self = MXF_METADATA_FILE_DESCRIPTOR (m);
4139   GList *ret =
4140       MXF_METADATA_BASE_CLASS
4141       (mxf_metadata_file_descriptor_parent_class)->write_tags (m, primer);
4142   MXFLocalTag *t;
4143
4144   if (self->linked_track_id) {
4145     t = g_slice_new0 (MXFLocalTag);
4146     memcpy (&t->ul, MXF_UL (LINKED_TRACK_ID), 16);
4147     t->size = 4;
4148     t->data = g_slice_alloc (t->size);
4149     t->g_slice = TRUE;
4150     GST_WRITE_UINT32_BE (t->data, self->linked_track_id);
4151     mxf_primer_pack_add_mapping (primer, 0x3006, &t->ul);
4152     ret = g_list_prepend (ret, t);
4153   }
4154
4155   t = g_slice_new0 (MXFLocalTag);
4156   memcpy (&t->ul, MXF_UL (SAMPLE_RATE), 16);
4157   t->size = 8;
4158   t->data = g_slice_alloc (t->size);
4159   t->g_slice = TRUE;
4160   GST_WRITE_UINT32_BE (t->data, self->sample_rate.n);
4161   GST_WRITE_UINT32_BE (t->data + 4, self->sample_rate.d);
4162   mxf_primer_pack_add_mapping (primer, 0x3001, &t->ul);
4163   ret = g_list_prepend (ret, t);
4164
4165   if (self->container_duration > 0) {
4166     t = g_slice_new0 (MXFLocalTag);
4167     memcpy (&t->ul, MXF_UL (CONTAINER_DURATION), 16);
4168     t->size = 8;
4169     t->data = g_slice_alloc (t->size);
4170     t->g_slice = TRUE;
4171     GST_WRITE_UINT64_BE (t->data, self->container_duration);
4172     mxf_primer_pack_add_mapping (primer, 0x3002, &t->ul);
4173     ret = g_list_prepend (ret, t);
4174   }
4175
4176   t = g_slice_new0 (MXFLocalTag);
4177   memcpy (&t->ul, MXF_UL (ESSENCE_CONTAINER), 16);
4178   t->size = 16;
4179   t->data = g_slice_alloc (t->size);
4180   t->g_slice = TRUE;
4181   memcpy (t->data, &self->essence_container, 16);
4182   mxf_primer_pack_add_mapping (primer, 0x3004, &t->ul);
4183   ret = g_list_prepend (ret, t);
4184
4185   if (!mxf_ul_is_zero (&self->codec)) {
4186     t = g_slice_new0 (MXFLocalTag);
4187     memcpy (&t->ul, MXF_UL (CODEC), 16);
4188     t->size = 16;
4189     t->data = g_slice_alloc (t->size);
4190     t->g_slice = TRUE;
4191     memcpy (t->data, &self->codec, 16);
4192     mxf_primer_pack_add_mapping (primer, 0x3005, &t->ul);
4193     ret = g_list_prepend (ret, t);
4194   }
4195
4196   return ret;
4197 }
4198
4199 static void
4200 mxf_metadata_file_descriptor_init (MXFMetadataFileDescriptor * self)
4201 {
4202
4203 }
4204
4205 static void
4206 mxf_metadata_file_descriptor_class_init (MXFMetadataFileDescriptorClass * klass)
4207 {
4208   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
4209   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
4210
4211   metadata_base_class->handle_tag = mxf_metadata_file_descriptor_handle_tag;
4212   metadata_base_class->name_quark = MXF_QUARK (FILE_DESCRIPTOR);
4213   metadata_base_class->to_structure = mxf_metadata_file_descriptor_to_structure;
4214   metadata_base_class->write_tags = mxf_metadata_file_descriptor_write_tags;
4215   metadata_class->type = 0x0125;
4216 }
4217
4218 G_DEFINE_TYPE (MXFMetadataGenericPictureEssenceDescriptor,
4219     mxf_metadata_generic_picture_essence_descriptor,
4220     MXF_TYPE_METADATA_FILE_DESCRIPTOR);
4221
4222 static gboolean
4223 mxf_metadata_generic_picture_essence_descriptor_handle_tag (MXFMetadataBase *
4224     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
4225     guint tag_size)
4226 {
4227   MXFMetadataGenericPictureEssenceDescriptor *self =
4228       MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (metadata);
4229   gboolean ret = TRUE;
4230 #ifndef GST_DISABLE_GST_DEBUG
4231   gchar str[48];
4232 #endif
4233
4234   switch (tag) {
4235     case 0x3215:
4236       if (tag_size != 1)
4237         goto error;
4238       self->signal_standard = GST_READ_UINT8 (tag_data);
4239       GST_DEBUG ("  signal standard = %u", self->signal_standard);
4240       break;
4241     case 0x320c:
4242       if (tag_size != 1)
4243         goto error;
4244       self->frame_layout = GST_READ_UINT8 (tag_data);
4245       GST_DEBUG ("  frame layout = %u", self->frame_layout);
4246       break;
4247     case 0x3203:
4248       if (tag_size != 4)
4249         goto error;
4250       self->stored_width = GST_READ_UINT32_BE (tag_data);
4251       GST_DEBUG ("  stored width = %u", self->stored_width);
4252       break;
4253     case 0x3202:
4254       if (tag_size != 4)
4255         goto error;
4256       self->stored_height = GST_READ_UINT32_BE (tag_data);
4257       GST_DEBUG ("  stored height = %u", self->stored_height);
4258       break;
4259     case 0x3216:
4260       if (tag_size != 4)
4261         goto error;
4262       self->stored_f2_offset = GST_READ_UINT32_BE (tag_data);
4263       GST_DEBUG ("  stored f2 offset = %d", self->stored_f2_offset);
4264       break;
4265     case 0x3205:
4266       if (tag_size != 4)
4267         goto error;
4268       self->sampled_width = GST_READ_UINT32_BE (tag_data);
4269       GST_DEBUG ("  sampled width = %u", self->sampled_width);
4270       break;
4271     case 0x3204:
4272       if (tag_size != 4)
4273         goto error;
4274       self->sampled_height = GST_READ_UINT32_BE (tag_data);
4275       GST_DEBUG ("  sampled height = %u", self->sampled_height);
4276       break;
4277     case 0x3206:
4278       if (tag_size != 4)
4279         goto error;
4280       self->sampled_x_offset = GST_READ_UINT32_BE (tag_data);
4281       GST_DEBUG ("  sampled x offset = %d", self->sampled_x_offset);
4282       break;
4283     case 0x3207:
4284       if (tag_size != 4)
4285         goto error;
4286       self->sampled_y_offset = GST_READ_UINT32_BE (tag_data);
4287       GST_DEBUG ("  sampled y offset = %d", self->sampled_y_offset);
4288       break;
4289     case 0x3208:
4290       if (tag_size != 4)
4291         goto error;
4292       self->display_height = GST_READ_UINT32_BE (tag_data);
4293       GST_DEBUG ("  display height = %u", self->display_height);
4294       break;
4295     case 0x3209:
4296       if (tag_size != 4)
4297         goto error;
4298       self->display_width = GST_READ_UINT32_BE (tag_data);
4299       GST_DEBUG ("  display width = %u", self->display_width);
4300       break;
4301     case 0x320a:
4302       if (tag_size != 4)
4303         goto error;
4304       self->display_x_offset = GST_READ_UINT32_BE (tag_data);
4305       GST_DEBUG ("  display x offset = %d", self->display_x_offset);
4306       break;
4307     case 0x320b:
4308       if (tag_size != 4)
4309         goto error;
4310       self->display_y_offset = GST_READ_UINT32_BE (tag_data);
4311       GST_DEBUG ("  display y offset = %d", self->display_y_offset);
4312       break;
4313     case 0x3217:
4314       if (tag_size != 4)
4315         goto error;
4316       self->display_f2_offset = GST_READ_UINT32_BE (tag_data);
4317       GST_DEBUG ("  display f2 offset = %d", self->display_f2_offset);
4318       break;
4319     case 0x320e:
4320       if (!mxf_fraction_parse (&self->aspect_ratio, tag_data, tag_size))
4321         goto error;
4322       GST_DEBUG ("  aspect ratio = %d/%d", self->aspect_ratio.n,
4323           self->aspect_ratio.d);
4324       break;
4325     case 0x3218:
4326       if (tag_size != 1)
4327         goto error;
4328       self->active_format_descriptor = GST_READ_UINT8 (tag_data);
4329       GST_DEBUG ("  active format descriptor = %u",
4330           self->active_format_descriptor);
4331       break;
4332     case 0x320d:
4333       if (tag_size < 8)
4334         goto error;
4335
4336       if (GST_READ_UINT32_BE (tag_data) == 0)
4337         return TRUE;
4338
4339       if (GST_READ_UINT32_BE (tag_data) != 2 &&
4340           GST_READ_UINT32_BE (tag_data + 4) != 4)
4341         goto error;
4342
4343       if (tag_size != 16)
4344         goto error;
4345
4346       self->video_line_map[0] = GST_READ_UINT32_BE (tag_data + 8);
4347       self->video_line_map[1] = GST_READ_UINT32_BE (tag_data + 12);
4348       GST_DEBUG ("  video line map = {%i, %i}", self->video_line_map[0],
4349           self->video_line_map[1]);
4350       break;
4351     case 0x320f:
4352       if (tag_size != 1)
4353         goto error;
4354       self->alpha_transparency = GST_READ_UINT8 (tag_data);
4355       GST_DEBUG ("  alpha transparency = %u", self->alpha_transparency);
4356       break;
4357     case 0x3210:
4358       if (tag_size != 16)
4359         goto error;
4360       memcpy (&self->capture_gamma, tag_data, 16);
4361       GST_DEBUG ("  capture gamma = %s",
4362           mxf_ul_to_string (&self->capture_gamma, str));
4363       break;
4364     case 0x3211:
4365       if (tag_size != 4)
4366         goto error;
4367       self->image_alignment_offset = GST_READ_UINT32_BE (tag_data);
4368       GST_DEBUG ("  image alignment offset = %u", self->image_alignment_offset);
4369       break;
4370     case 0x3213:
4371       if (tag_size != 4)
4372         goto error;
4373       self->image_start_offset = GST_READ_UINT32_BE (tag_data);
4374       GST_DEBUG ("  image start offset = %u", self->image_start_offset);
4375       break;
4376     case 0x3214:
4377       if (tag_size != 4)
4378         goto error;
4379       self->image_end_offset = GST_READ_UINT32_BE (tag_data);
4380       GST_DEBUG ("  image end offset = %u", self->image_end_offset);
4381       break;
4382     case 0x3212:
4383       if (tag_size != 1)
4384         goto error;
4385       self->field_dominance = GST_READ_UINT8 (tag_data);
4386       GST_DEBUG ("  field dominance = %u", self->field_dominance);
4387       break;
4388     case 0x3201:
4389       if (tag_size != 16)
4390         goto error;
4391       memcpy (&self->picture_essence_coding, tag_data, 16);
4392       GST_DEBUG ("  picture essence coding = %s",
4393           mxf_ul_to_string (&self->picture_essence_coding, str));
4394       break;
4395     default:
4396       ret =
4397           MXF_METADATA_BASE_CLASS
4398           (mxf_metadata_generic_picture_essence_descriptor_parent_class)->
4399           handle_tag (metadata, primer, tag, tag_data, tag_size);
4400       break;
4401   }
4402
4403   return ret;
4404
4405 error:
4406
4407   GST_ERROR
4408       ("Invalid generic picture essence descriptor local tag 0x%04x of size %u",
4409       tag, tag_size);
4410
4411   return FALSE;
4412 }
4413
4414 static GstStructure *
4415 mxf_metadata_generic_picture_essence_descriptor_to_structure (MXFMetadataBase *
4416     m)
4417 {
4418   GstStructure *ret =
4419       MXF_METADATA_BASE_CLASS
4420       (mxf_metadata_generic_picture_essence_descriptor_parent_class)->
4421       to_structure (m);
4422   MXFMetadataGenericPictureEssenceDescriptor *self =
4423       MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (m);
4424   gchar str[48];
4425
4426   gst_structure_id_set (ret, MXF_QUARK (SIGNAL_STANDARD), G_TYPE_UCHAR,
4427       self->signal_standard, NULL);
4428
4429   if (self->frame_layout != 255)
4430     gst_structure_id_set (ret, MXF_QUARK (FRAME_LAYOUT), G_TYPE_UCHAR,
4431         self->frame_layout, NULL);
4432
4433   if (self->stored_width != 0 && self->stored_height != 0)
4434     gst_structure_id_set (ret, MXF_QUARK (STORED_WIDTH), G_TYPE_UINT,
4435         self->stored_width, MXF_QUARK (STORED_HEIGHT), G_TYPE_UINT,
4436         self->stored_height, NULL);
4437
4438   if (self->stored_f2_offset != 0)
4439     gst_structure_id_set (ret, MXF_QUARK (STORED_F2_OFFSET), G_TYPE_INT,
4440         self->stored_f2_offset, NULL);
4441
4442   if (self->sampled_width != 0 && self->sampled_height != 0)
4443     gst_structure_id_set (ret, MXF_QUARK (SAMPLED_WIDTH), G_TYPE_UINT,
4444         self->sampled_width, MXF_QUARK (SAMPLED_HEIGHT), G_TYPE_UINT,
4445         self->sampled_height, NULL);
4446
4447   if (self->sampled_x_offset != 0)
4448     gst_structure_id_set (ret, MXF_QUARK (SAMPLED_X_OFFSET), G_TYPE_INT,
4449         self->sampled_x_offset, NULL);
4450
4451   if (self->sampled_y_offset != 0)
4452     gst_structure_id_set (ret, MXF_QUARK (SAMPLED_Y_OFFSET), G_TYPE_INT,
4453         self->sampled_y_offset, NULL);
4454
4455   if (self->display_width != 0 && self->display_height != 0)
4456     gst_structure_id_set (ret, MXF_QUARK (DISPLAY_WIDTH), G_TYPE_UINT,
4457         self->display_width, MXF_QUARK (DISPLAY_HEIGHT), G_TYPE_UINT,
4458         self->display_height, NULL);
4459
4460   if (self->display_x_offset != 0)
4461     gst_structure_id_set (ret, MXF_QUARK (DISPLAY_X_OFFSET), G_TYPE_INT,
4462         self->display_x_offset, NULL);
4463
4464   if (self->display_y_offset != 0)
4465     gst_structure_id_set (ret, MXF_QUARK (DISPLAY_Y_OFFSET), G_TYPE_INT,
4466         self->display_y_offset, NULL);
4467
4468   if (self->display_f2_offset != 0)
4469     gst_structure_id_set (ret, MXF_QUARK (DISPLAY_F2_OFFSET), G_TYPE_INT,
4470         self->display_f2_offset, NULL);
4471
4472   if (self->aspect_ratio.n != 0 && self->aspect_ratio.d != 0)
4473     gst_structure_id_set (ret, MXF_QUARK (ASPECT_RATIO), GST_TYPE_FRACTION,
4474         self->aspect_ratio.n, self->aspect_ratio.d, NULL);
4475
4476   if (self->active_format_descriptor)
4477     gst_structure_id_set (ret, MXF_QUARK (ACTIVE_FORMAT_DESCRIPTOR),
4478         G_TYPE_UCHAR, self->active_format_descriptor, NULL);
4479
4480   if (self->video_line_map[0] != 0 && self->video_line_map[1] != 0)
4481     gst_structure_id_set (ret, MXF_QUARK (VIDEO_LINE_MAP_0), G_TYPE_UINT,
4482         self->video_line_map[0], MXF_QUARK (VIDEO_LINE_MAP_1), G_TYPE_UINT,
4483         self->video_line_map[1], NULL);
4484
4485   if (self->alpha_transparency != 0)
4486     gst_structure_id_set (ret, MXF_QUARK (ALPHA_TRANSPARENCY), G_TYPE_UCHAR,
4487         self->alpha_transparency, NULL);
4488
4489   if (!mxf_ul_is_zero (&self->capture_gamma)) {
4490     mxf_ul_to_string (&self->capture_gamma, str);
4491     gst_structure_id_set (ret, MXF_QUARK (CAPTURE_GAMMA), G_TYPE_STRING, str,
4492         NULL);
4493   }
4494
4495   if (self->image_alignment_offset != 0)
4496     gst_structure_id_set (ret, MXF_QUARK (IMAGE_ALIGNMENT_OFFSET), G_TYPE_UINT,
4497         self->image_alignment_offset, NULL);
4498
4499   if (self->image_start_offset != 0)
4500     gst_structure_id_set (ret, MXF_QUARK (IMAGE_START_OFFSET), G_TYPE_UINT,
4501         self->image_start_offset, NULL);
4502
4503   if (self->image_end_offset != 0)
4504     gst_structure_id_set (ret, MXF_QUARK (IMAGE_END_OFFSET), G_TYPE_UINT,
4505         self->image_end_offset, NULL);
4506
4507   if (self->field_dominance != 0)
4508     gst_structure_id_set (ret, MXF_QUARK (FIELD_DOMINANCE), G_TYPE_UCHAR,
4509         self->field_dominance, NULL);
4510
4511   if (!mxf_ul_is_zero (&self->picture_essence_coding)) {
4512     mxf_ul_to_string (&self->picture_essence_coding, str);
4513     gst_structure_id_set (ret, MXF_QUARK (PICTURE_ESSENCE_CODING),
4514         G_TYPE_STRING, str, NULL);
4515   }
4516
4517   return ret;
4518 }
4519
4520 static GList *
4521 mxf_metadata_generic_picture_essence_descriptor_write_tags (MXFMetadataBase * m,
4522     MXFPrimerPack * primer)
4523 {
4524   MXFMetadataGenericPictureEssenceDescriptor *self =
4525       MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (m);
4526   GList *ret =
4527       MXF_METADATA_BASE_CLASS
4528       (mxf_metadata_generic_picture_essence_descriptor_parent_class)->write_tags
4529       (m, primer);
4530   MXFLocalTag *t;
4531
4532   if (self->signal_standard != 1) {
4533     t = g_slice_new0 (MXFLocalTag);
4534     memcpy (&t->ul, MXF_UL (SIGNAL_STANDARD), 16);
4535     t->size = 1;
4536     t->data = g_slice_alloc (t->size);
4537     t->g_slice = TRUE;
4538     GST_WRITE_UINT8 (t->data, self->signal_standard);
4539     mxf_primer_pack_add_mapping (primer, 0x3215, &t->ul);
4540     ret = g_list_prepend (ret, t);
4541   }
4542
4543   if (self->frame_layout != 255) {
4544     t = g_slice_new0 (MXFLocalTag);
4545     memcpy (&t->ul, MXF_UL (FRAME_LAYOUT), 16);
4546     t->size = 1;
4547     t->data = g_slice_alloc (t->size);
4548     t->g_slice = TRUE;
4549     GST_WRITE_UINT8 (t->data, self->frame_layout);
4550     mxf_primer_pack_add_mapping (primer, 0x320c, &t->ul);
4551     ret = g_list_prepend (ret, t);
4552   }
4553
4554   if (self->stored_width != 0) {
4555     t = g_slice_new0 (MXFLocalTag);
4556     memcpy (&t->ul, MXF_UL (STORED_WIDTH), 16);
4557     t->size = 4;
4558     t->data = g_slice_alloc (t->size);
4559     t->g_slice = TRUE;
4560     GST_WRITE_UINT32_BE (t->data, self->stored_width);
4561     mxf_primer_pack_add_mapping (primer, 0x3203, &t->ul);
4562     ret = g_list_prepend (ret, t);
4563   }
4564
4565   if (self->stored_height != 0) {
4566     t = g_slice_new0 (MXFLocalTag);
4567     memcpy (&t->ul, MXF_UL (STORED_HEIGHT), 16);
4568     t->size = 4;
4569     t->data = g_slice_alloc (t->size);
4570     t->g_slice = TRUE;
4571     GST_WRITE_UINT32_BE (t->data, self->stored_height);
4572     mxf_primer_pack_add_mapping (primer, 0x3202, &t->ul);
4573     ret = g_list_prepend (ret, t);
4574   }
4575
4576   if (self->stored_f2_offset != 0) {
4577     t = g_slice_new0 (MXFLocalTag);
4578     memcpy (&t->ul, MXF_UL (STORED_F2_OFFSET), 16);
4579     t->size = 4;
4580     t->data = g_slice_alloc (t->size);
4581     t->g_slice = TRUE;
4582     GST_WRITE_UINT32_BE (t->data, self->stored_f2_offset);
4583     mxf_primer_pack_add_mapping (primer, 0x3216, &t->ul);
4584     ret = g_list_prepend (ret, t);
4585   }
4586
4587   if (self->sampled_width != 0) {
4588     t = g_slice_new0 (MXFLocalTag);
4589     memcpy (&t->ul, MXF_UL (SAMPLED_WIDTH), 16);
4590     t->size = 4;
4591     t->data = g_slice_alloc (t->size);
4592     t->g_slice = TRUE;
4593     GST_WRITE_UINT32_BE (t->data, self->sampled_width);
4594     mxf_primer_pack_add_mapping (primer, 0x3205, &t->ul);
4595     ret = g_list_prepend (ret, t);
4596   }
4597
4598   if (self->sampled_height != 0) {
4599     t = g_slice_new0 (MXFLocalTag);
4600     memcpy (&t->ul, MXF_UL (SAMPLED_HEIGHT), 16);
4601     t->size = 4;
4602     t->data = g_slice_alloc (t->size);
4603     t->g_slice = TRUE;
4604     GST_WRITE_UINT32_BE (t->data, self->sampled_height);
4605     mxf_primer_pack_add_mapping (primer, 0x3204, &t->ul);
4606     ret = g_list_prepend (ret, t);
4607   }
4608
4609   if (self->sampled_x_offset != 0) {
4610     t = g_slice_new0 (MXFLocalTag);
4611     memcpy (&t->ul, MXF_UL (SAMPLED_X_OFFSET), 16);
4612     t->size = 4;
4613     t->data = g_slice_alloc (t->size);
4614     t->g_slice = TRUE;
4615     GST_WRITE_UINT32_BE (t->data, self->sampled_x_offset);
4616     mxf_primer_pack_add_mapping (primer, 0x3206, &t->ul);
4617     ret = g_list_prepend (ret, t);
4618   }
4619
4620   if (self->sampled_y_offset != 0) {
4621     t = g_slice_new0 (MXFLocalTag);
4622     memcpy (&t->ul, MXF_UL (SAMPLED_Y_OFFSET), 16);
4623     t->size = 4;
4624     t->data = g_slice_alloc (t->size);
4625     t->g_slice = TRUE;
4626     GST_WRITE_UINT32_BE (t->data, self->sampled_y_offset);
4627     mxf_primer_pack_add_mapping (primer, 0x3207, &t->ul);
4628     ret = g_list_prepend (ret, t);
4629   }
4630
4631   if (self->display_height != 0) {
4632     t = g_slice_new0 (MXFLocalTag);
4633     memcpy (&t->ul, MXF_UL (DISPLAY_HEIGHT), 16);
4634     t->size = 4;
4635     t->data = g_slice_alloc (t->size);
4636     t->g_slice = TRUE;
4637     GST_WRITE_UINT32_BE (t->data, self->display_height);
4638     mxf_primer_pack_add_mapping (primer, 0x3208, &t->ul);
4639     ret = g_list_prepend (ret, t);
4640   }
4641
4642   if (self->display_width != 0) {
4643     t = g_slice_new0 (MXFLocalTag);
4644     memcpy (&t->ul, MXF_UL (DISPLAY_WIDTH), 16);
4645     t->size = 4;
4646     t->data = g_slice_alloc (t->size);
4647     t->g_slice = TRUE;
4648     GST_WRITE_UINT32_BE (t->data, self->display_width);
4649     mxf_primer_pack_add_mapping (primer, 0x3209, &t->ul);
4650     ret = g_list_prepend (ret, t);
4651   }
4652
4653   if (self->display_x_offset != 0) {
4654     t = g_slice_new0 (MXFLocalTag);
4655     memcpy (&t->ul, MXF_UL (DISPLAY_X_OFFSET), 16);
4656     t->size = 4;
4657     t->data = g_slice_alloc (t->size);
4658     t->g_slice = TRUE;
4659     GST_WRITE_UINT32_BE (t->data, self->display_x_offset);
4660     mxf_primer_pack_add_mapping (primer, 0x320a, &t->ul);
4661     ret = g_list_prepend (ret, t);
4662   }
4663
4664   if (self->display_y_offset != 0) {
4665     t = g_slice_new0 (MXFLocalTag);
4666     memcpy (&t->ul, MXF_UL (DISPLAY_Y_OFFSET), 16);
4667     t->size = 4;
4668     t->data = g_slice_alloc (t->size);
4669     t->g_slice = TRUE;
4670     GST_WRITE_UINT32_BE (t->data, self->display_y_offset);
4671     mxf_primer_pack_add_mapping (primer, 0x320b, &t->ul);
4672     ret = g_list_prepend (ret, t);
4673   }
4674
4675   if (self->display_f2_offset != 0) {
4676     t = g_slice_new0 (MXFLocalTag);
4677     memcpy (&t->ul, MXF_UL (DISPLAY_F2_OFFSET), 16);
4678     t->size = 4;
4679     t->data = g_slice_alloc (t->size);
4680     t->g_slice = TRUE;
4681     GST_WRITE_UINT32_BE (t->data, self->display_f2_offset);
4682     mxf_primer_pack_add_mapping (primer, 0x3217, &t->ul);
4683     ret = g_list_prepend (ret, t);
4684   }
4685
4686   if (self->aspect_ratio.n != 0 && self->aspect_ratio.d != 0) {
4687     t = g_slice_new0 (MXFLocalTag);
4688     memcpy (&t->ul, MXF_UL (ASPECT_RATIO), 16);
4689     t->size = 8;
4690     t->data = g_slice_alloc (t->size);
4691     t->g_slice = TRUE;
4692     GST_WRITE_UINT32_BE (t->data, self->aspect_ratio.n);
4693     GST_WRITE_UINT32_BE (t->data + 4, self->aspect_ratio.d);
4694     mxf_primer_pack_add_mapping (primer, 0x320e, &t->ul);
4695     ret = g_list_prepend (ret, t);
4696   }
4697
4698   if (self->active_format_descriptor != 0) {
4699     t = g_slice_new0 (MXFLocalTag);
4700     memcpy (&t->ul, MXF_UL (ACTIVE_FORMAT_DESCRIPTOR), 16);
4701     t->size = 1;
4702     t->data = g_slice_alloc (t->size);
4703     t->g_slice = TRUE;
4704     GST_WRITE_UINT8 (t->data, self->active_format_descriptor);
4705     mxf_primer_pack_add_mapping (primer, 0x3218, &t->ul);
4706     ret = g_list_prepend (ret, t);
4707   }
4708
4709   if (self->video_line_map[0] != 0 || self->video_line_map[1] != 0) {
4710     t = g_slice_new0 (MXFLocalTag);
4711     memcpy (&t->ul, MXF_UL (VIDEO_LINE_MAP), 16);
4712     t->size = 16;
4713     t->data = g_slice_alloc (t->size);
4714     t->g_slice = TRUE;
4715     GST_WRITE_UINT64_BE (t->data, self->video_line_map[0]);
4716     GST_WRITE_UINT64_BE (t->data + 8, self->video_line_map[1]);
4717     mxf_primer_pack_add_mapping (primer, 0x320d, &t->ul);
4718     ret = g_list_prepend (ret, t);
4719   }
4720
4721   if (self->alpha_transparency != 0) {
4722     t = g_slice_new0 (MXFLocalTag);
4723     memcpy (&t->ul, MXF_UL (ALPHA_TRANSPARENCY), 16);
4724     t->size = 1;
4725     t->data = g_slice_alloc (t->size);
4726     t->g_slice = TRUE;
4727     GST_WRITE_UINT8 (t->data, self->alpha_transparency);
4728     mxf_primer_pack_add_mapping (primer, 0x320f, &t->ul);
4729     ret = g_list_prepend (ret, t);
4730   }
4731
4732   if (!mxf_ul_is_zero (&self->capture_gamma)) {
4733     t = g_slice_new0 (MXFLocalTag);
4734     memcpy (&t->ul, MXF_UL (CAPTURE_GAMMA), 16);
4735     t->size = 16;
4736     t->data = g_slice_alloc (t->size);
4737     t->g_slice = TRUE;
4738     memcpy (t->data, &self->capture_gamma, 16);
4739     mxf_primer_pack_add_mapping (primer, 0x3210, &t->ul);
4740     ret = g_list_prepend (ret, t);
4741   }
4742
4743   if (self->image_alignment_offset != 0) {
4744     t = g_slice_new0 (MXFLocalTag);
4745     memcpy (&t->ul, MXF_UL (IMAGE_ALIGNMENT_OFFSET), 16);
4746     t->size = 4;
4747     t->data = g_slice_alloc (t->size);
4748     t->g_slice = TRUE;
4749     GST_WRITE_UINT32_BE (t->data, self->image_alignment_offset);
4750     mxf_primer_pack_add_mapping (primer, 0x3211, &t->ul);
4751     ret = g_list_prepend (ret, t);
4752   }
4753
4754   if (self->image_start_offset != 0) {
4755     t = g_slice_new0 (MXFLocalTag);
4756     memcpy (&t->ul, MXF_UL (IMAGE_START_OFFSET), 16);
4757     t->size = 4;
4758     t->data = g_slice_alloc (t->size);
4759     t->g_slice = TRUE;
4760     GST_WRITE_UINT32_BE (t->data, self->image_start_offset);
4761     mxf_primer_pack_add_mapping (primer, 0x3213, &t->ul);
4762     ret = g_list_prepend (ret, t);
4763   }
4764
4765   if (self->image_end_offset != 0) {
4766     t = g_slice_new0 (MXFLocalTag);
4767     memcpy (&t->ul, MXF_UL (IMAGE_END_OFFSET), 16);
4768     t->size = 4;
4769     t->data = g_slice_alloc (t->size);
4770     t->g_slice = TRUE;
4771     GST_WRITE_UINT32_BE (t->data, self->image_end_offset);
4772     mxf_primer_pack_add_mapping (primer, 0x3214, &t->ul);
4773     ret = g_list_prepend (ret, t);
4774   }
4775
4776   if (self->field_dominance != 0) {
4777     t = g_slice_new0 (MXFLocalTag);
4778     memcpy (&t->ul, MXF_UL (FIELD_DOMINANCE), 16);
4779     t->size = 1;
4780     t->data = g_slice_alloc (t->size);
4781     t->g_slice = TRUE;
4782     GST_WRITE_UINT8 (t->data, self->field_dominance);
4783     mxf_primer_pack_add_mapping (primer, 0x3212, &t->ul);
4784     ret = g_list_prepend (ret, t);
4785   }
4786
4787   if (!mxf_ul_is_zero (&self->picture_essence_coding)) {
4788     t = g_slice_new0 (MXFLocalTag);
4789     memcpy (&t->ul, MXF_UL (PICTURE_ESSENCE_CODING), 16);
4790     t->size = 16;
4791     t->data = g_slice_alloc (t->size);
4792     t->g_slice = TRUE;
4793     memcpy (t->data, &self->picture_essence_coding, 16);
4794     mxf_primer_pack_add_mapping (primer, 0x3201, &t->ul);
4795     ret = g_list_prepend (ret, t);
4796   }
4797
4798   return ret;
4799 }
4800
4801 static void
4802     mxf_metadata_generic_picture_essence_descriptor_init
4803     (MXFMetadataGenericPictureEssenceDescriptor * self)
4804 {
4805   self->signal_standard = 1;
4806   self->frame_layout = 255;
4807 }
4808
4809 static void
4810     mxf_metadata_generic_picture_essence_descriptor_class_init
4811     (MXFMetadataGenericPictureEssenceDescriptorClass * klass)
4812 {
4813   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
4814   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
4815
4816   metadata_base_class->handle_tag =
4817       mxf_metadata_generic_picture_essence_descriptor_handle_tag;
4818   metadata_base_class->name_quark =
4819       MXF_QUARK (GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
4820   metadata_base_class->to_structure =
4821       mxf_metadata_generic_picture_essence_descriptor_to_structure;
4822   metadata_base_class->write_tags =
4823       mxf_metadata_generic_picture_essence_descriptor_write_tags;
4824   metadata_class->type = 0x0127;
4825 }
4826
4827 void mxf_metadata_generic_picture_essence_descriptor_set_caps
4828     (MXFMetadataGenericPictureEssenceDescriptor * self, GstCaps * caps)
4829 {
4830   guint par_n, par_d;
4831   guint width, height;
4832   MXFMetadataFileDescriptor *f = (MXFMetadataFileDescriptor *) self;
4833
4834   g_return_if_fail (MXF_IS_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (self));
4835   g_return_if_fail (GST_IS_CAPS (caps));
4836
4837   if (f->sample_rate.d == 0) {
4838     GST_ERROR ("Invalid framerate");
4839   } else {
4840     gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, f->sample_rate.n,
4841         f->sample_rate.d, NULL);
4842   }
4843
4844   width = self->stored_width;
4845   height = self->stored_height;
4846
4847   /* If the video is stored as separate fields the
4848    * height is only the height of one field, i.e.
4849    * half the height of the frame.
4850    *
4851    * See SMPTE 377M E2.2 and E1.2
4852    */
4853   if (self->frame_layout == 1 || self->frame_layout == 2
4854       || self->frame_layout == 4) {
4855     height *= 2;
4856     gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL);
4857   }
4858
4859   if (width == 0 || height == 0) {
4860     GST_ERROR ("Invalid width/height");
4861     return;
4862   }
4863
4864   gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height", G_TYPE_INT,
4865       height, NULL);
4866
4867   if (self->aspect_ratio.n == 0 || self->aspect_ratio.d == 0) {
4868     GST_ERROR ("Invalid aspect ratio");
4869     return;
4870   }
4871
4872   par_n = height * self->aspect_ratio.n;
4873   par_d = width * self->aspect_ratio.d;
4874
4875   gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
4876       par_n, par_d, NULL);
4877 }
4878
4879 static gint
4880 gst_greatest_common_divisor (gint a, gint b)
4881 {
4882   while (b != 0) {
4883     int temp = a;
4884
4885     a = b;
4886     b = temp % b;
4887   }
4888
4889   return ABS (a);
4890 }
4891
4892 gboolean
4893     mxf_metadata_generic_picture_essence_descriptor_from_caps
4894     (MXFMetadataGenericPictureEssenceDescriptor * self, GstCaps * caps) {
4895   gint par_n, par_d, gcd;
4896   gint width, height;
4897   gint fps_n, fps_d;
4898   MXFMetadataFileDescriptor *f = (MXFMetadataFileDescriptor *) self;
4899   GstStructure *s;
4900   gboolean interlaced;
4901
4902   g_return_val_if_fail (MXF_IS_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR
4903       (self), FALSE);
4904   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
4905
4906   s = gst_caps_get_structure (caps, 0);
4907
4908   if (!gst_structure_get_boolean (s, "interlaced", &interlaced) || !interlaced)
4909     self->frame_layout = 0;
4910   else
4911     self->frame_layout = 3;
4912
4913   if (!gst_structure_get_fraction (s, "framerate", &fps_n, &fps_d)) {
4914     GST_ERROR ("Invalid framerate");
4915     return FALSE;
4916   }
4917   f->sample_rate.n = fps_n;
4918   f->sample_rate.d = fps_d;
4919
4920   if (!gst_structure_get_int (s, "width", &width) ||
4921       !gst_structure_get_int (s, "height", &height)) {
4922     GST_ERROR ("Invalid width/height");
4923     return FALSE;
4924   }
4925
4926   self->stored_width = width;
4927   self->stored_height = height;
4928
4929   if (!gst_structure_get_fraction (s, "pixel-aspect-ratio", &par_n, &par_d)) {
4930     par_n = 1;
4931     par_d = 1;
4932   }
4933
4934   self->aspect_ratio.n = par_n * width;
4935   self->aspect_ratio.d = par_d * height;
4936   gcd =
4937       gst_greatest_common_divisor (self->aspect_ratio.n, self->aspect_ratio.d);
4938   self->aspect_ratio.n /= gcd;
4939   self->aspect_ratio.d /= gcd;
4940
4941   return TRUE;
4942 }
4943
4944
4945 G_DEFINE_TYPE (MXFMetadataGenericSoundEssenceDescriptor,
4946     mxf_metadata_generic_sound_essence_descriptor,
4947     MXF_TYPE_METADATA_FILE_DESCRIPTOR);
4948
4949 static gboolean
4950 mxf_metadata_generic_sound_essence_descriptor_handle_tag (MXFMetadataBase *
4951     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
4952     guint tag_size)
4953 {
4954   MXFMetadataGenericSoundEssenceDescriptor *self =
4955       MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (metadata);
4956   gboolean ret = TRUE;
4957 #ifndef GST_DISABLE_GST_DEBUG
4958   gchar str[48];
4959 #endif
4960
4961   switch (tag) {
4962     case 0x3d03:
4963       if (!mxf_fraction_parse (&self->audio_sampling_rate, tag_data, tag_size))
4964         goto error;
4965       GST_DEBUG ("  audio sampling rate = %d/%d",
4966           self->audio_sampling_rate.n, self->audio_sampling_rate.d);
4967       break;
4968     case 0x3d02:
4969       if (tag_size != 1)
4970         goto error;
4971       self->locked = (GST_READ_UINT8 (tag_data) != 0);
4972       GST_DEBUG ("  locked = %s", (self->locked) ? "yes" : "no");
4973       break;
4974     case 0x3d04:
4975       if (tag_size != 1)
4976         goto error;
4977       self->audio_ref_level = GST_READ_UINT8 (tag_data);
4978       GST_DEBUG ("  audio ref level = %d", self->audio_ref_level);
4979       break;
4980     case 0x3d05:
4981       if (tag_size != 1)
4982         goto error;
4983       self->electro_spatial_formulation = GST_READ_UINT8 (tag_data);
4984       GST_DEBUG ("  electro spatial formulation = %u",
4985           self->electro_spatial_formulation);
4986       break;
4987     case 0x3d07:
4988       if (tag_size != 4)
4989         goto error;
4990       self->channel_count = GST_READ_UINT32_BE (tag_data);
4991       GST_DEBUG ("  channel count = %u", self->channel_count);
4992       break;
4993     case 0x3d01:
4994       if (tag_size != 4)
4995         goto error;
4996       self->quantization_bits = GST_READ_UINT32_BE (tag_data);
4997       GST_DEBUG ("  quantization bits = %u", self->quantization_bits);
4998       break;
4999     case 0x3d0c:
5000       if (tag_size != 1)
5001         goto error;
5002       self->dial_norm = GST_READ_UINT8 (tag_data);
5003       GST_DEBUG ("  dial norm = %d", self->dial_norm);
5004       break;
5005     case 0x3d06:
5006       if (tag_size != 16)
5007         goto error;
5008       memcpy (&self->sound_essence_compression, tag_data, 16);
5009       GST_DEBUG ("  sound essence compression = %s",
5010           mxf_ul_to_string (&self->sound_essence_compression, str));
5011       break;
5012     default:
5013       ret =
5014           MXF_METADATA_BASE_CLASS
5015           (mxf_metadata_generic_sound_essence_descriptor_parent_class)->
5016           handle_tag (metadata, primer, tag, tag_data, tag_size);
5017       break;
5018   }
5019
5020   return ret;
5021
5022 error:
5023
5024   GST_ERROR
5025       ("Invalid generic sound essence descriptor local tag 0x%04x of size %u",
5026       tag, tag_size);
5027
5028   return FALSE;
5029 }
5030
5031 static GstStructure *
5032 mxf_metadata_generic_sound_essence_descriptor_to_structure (MXFMetadataBase * m)
5033 {
5034   GstStructure *ret =
5035       MXF_METADATA_BASE_CLASS
5036       (mxf_metadata_generic_sound_essence_descriptor_parent_class)->to_structure
5037       (m);
5038   MXFMetadataGenericSoundEssenceDescriptor *self =
5039       MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (m);
5040
5041   gst_structure_id_set (ret, MXF_QUARK (AUDIO_SAMPLING_RATE), GST_TYPE_FRACTION,
5042       self->audio_sampling_rate.n, self->audio_sampling_rate.d, NULL);
5043
5044   gst_structure_id_set (ret, MXF_QUARK (LOCKED), G_TYPE_BOOLEAN, self->locked,
5045       NULL);
5046
5047   if (self->electro_spatial_formulation != 0)
5048     gst_structure_id_set (ret, MXF_QUARK (ELECTRO_SPATIAL_FORMULATION),
5049         G_TYPE_UCHAR, self->electro_spatial_formulation, NULL);
5050
5051   if (self->channel_count != 0)
5052     gst_structure_id_set (ret, MXF_QUARK (CHANNEL_COUNT), G_TYPE_UINT,
5053         self->channel_count, NULL);
5054
5055   if (self->quantization_bits != 0)
5056     gst_structure_id_set (ret, MXF_QUARK (QUANTIZATION_BITS), G_TYPE_UINT,
5057         self->quantization_bits, NULL);
5058
5059   if (self->dial_norm != 0)
5060     gst_structure_id_set (ret, MXF_QUARK (DIAL_NORM), G_TYPE_CHAR,
5061         self->dial_norm, NULL);
5062
5063   if (!mxf_ul_is_zero (&self->sound_essence_compression)) {
5064     gchar str[48];
5065
5066     mxf_ul_to_string (&self->sound_essence_compression, str);
5067     gst_structure_id_set (ret, MXF_QUARK (SOUND_ESSENCE_COMPRESSION),
5068         G_TYPE_STRING, str, NULL);
5069   }
5070
5071   return ret;
5072 }
5073
5074 static GList *
5075 mxf_metadata_generic_sound_essence_descriptor_write_tags (MXFMetadataBase * m,
5076     MXFPrimerPack * primer)
5077 {
5078   MXFMetadataGenericSoundEssenceDescriptor *self =
5079       MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (m);
5080   GList *ret =
5081       MXF_METADATA_BASE_CLASS
5082       (mxf_metadata_generic_sound_essence_descriptor_parent_class)->write_tags
5083       (m, primer);
5084   MXFLocalTag *t;
5085
5086   if (self->audio_sampling_rate.d && self->audio_sampling_rate.n) {
5087     t = g_slice_new0 (MXFLocalTag);
5088     memcpy (&t->ul, MXF_UL (AUDIO_SAMPLING_RATE), 16);
5089     t->size = 8;
5090     t->data = g_slice_alloc (t->size);
5091     t->g_slice = TRUE;
5092     GST_WRITE_UINT32_BE (t->data, self->audio_sampling_rate.n);
5093     GST_WRITE_UINT32_BE (t->data + 4, self->audio_sampling_rate.d);
5094     mxf_primer_pack_add_mapping (primer, 0x3d03, &t->ul);
5095     ret = g_list_prepend (ret, t);
5096   }
5097
5098   t = g_slice_new0 (MXFLocalTag);
5099   memcpy (&t->ul, MXF_UL (LOCKED), 16);
5100   t->size = 1;
5101   t->data = g_slice_alloc (t->size);
5102   t->g_slice = TRUE;
5103   GST_WRITE_UINT8 (t->data, (self->locked) ? 1 : 0);
5104   mxf_primer_pack_add_mapping (primer, 0x3d02, &t->ul);
5105   ret = g_list_prepend (ret, t);
5106
5107   if (self->audio_ref_level) {
5108     t = g_slice_new0 (MXFLocalTag);
5109     memcpy (&t->ul, MXF_UL (AUDIO_REF_LEVEL), 16);
5110     t->size = 1;
5111     t->data = g_slice_alloc (t->size);
5112     t->g_slice = TRUE;
5113     GST_WRITE_UINT8 (t->data, self->audio_ref_level);
5114     mxf_primer_pack_add_mapping (primer, 0x3d04, &t->ul);
5115     ret = g_list_prepend (ret, t);
5116   }
5117
5118   if (self->electro_spatial_formulation != 255) {
5119     t = g_slice_new0 (MXFLocalTag);
5120     memcpy (&t->ul, MXF_UL (ELECTRO_SPATIAL_FORMULATION), 16);
5121     t->size = 1;
5122     t->data = g_slice_alloc (t->size);
5123     t->g_slice = TRUE;
5124     GST_WRITE_UINT8 (t->data, self->electro_spatial_formulation);
5125     mxf_primer_pack_add_mapping (primer, 0x3d05, &t->ul);
5126     ret = g_list_prepend (ret, t);
5127   }
5128
5129   if (self->channel_count) {
5130     t = g_slice_new0 (MXFLocalTag);
5131     memcpy (&t->ul, MXF_UL (CHANNEL_COUNT), 16);
5132     t->size = 4;
5133     t->data = g_slice_alloc (t->size);
5134     t->g_slice = TRUE;
5135     GST_WRITE_UINT32_BE (t->data, self->channel_count);
5136     mxf_primer_pack_add_mapping (primer, 0x3d07, &t->ul);
5137     ret = g_list_prepend (ret, t);
5138   }
5139
5140   if (self->quantization_bits) {
5141     t = g_slice_new0 (MXFLocalTag);
5142     memcpy (&t->ul, MXF_UL (QUANTIZATION_BITS), 16);
5143     t->size = 4;
5144     t->data = g_slice_alloc (t->size);
5145     t->g_slice = TRUE;
5146     GST_WRITE_UINT32_BE (t->data, self->quantization_bits);
5147     mxf_primer_pack_add_mapping (primer, 0x3d01, &t->ul);
5148     ret = g_list_prepend (ret, t);
5149   }
5150
5151   if (self->dial_norm != 0) {
5152     t = g_slice_new0 (MXFLocalTag);
5153     memcpy (&t->ul, MXF_UL (DIAL_NORM), 16);
5154     t->size = 1;
5155     t->data = g_slice_alloc (t->size);
5156     t->g_slice = TRUE;
5157     GST_WRITE_UINT8 (t->data, self->dial_norm);
5158     mxf_primer_pack_add_mapping (primer, 0x3d0c, &t->ul);
5159     ret = g_list_prepend (ret, t);
5160   }
5161
5162   if (!mxf_ul_is_zero (&self->sound_essence_compression)) {
5163     t = g_slice_new0 (MXFLocalTag);
5164     memcpy (&t->ul, MXF_UL (SOUND_ESSENCE_COMPRESSION), 16);
5165     t->size = 16;
5166     t->data = g_slice_alloc (t->size);
5167     t->g_slice = TRUE;
5168     memcpy (t->data, &self->sound_essence_compression, 16);
5169     mxf_primer_pack_add_mapping (primer, 0x3d06, &t->ul);
5170     ret = g_list_prepend (ret, t);
5171   }
5172
5173   return ret;
5174 }
5175
5176 static void
5177     mxf_metadata_generic_sound_essence_descriptor_init
5178     (MXFMetadataGenericSoundEssenceDescriptor * self)
5179 {
5180   self->audio_sampling_rate.n = 48000;
5181   self->audio_sampling_rate.d = 1;
5182   self->electro_spatial_formulation = 255;
5183 }
5184
5185 static void
5186     mxf_metadata_generic_sound_essence_descriptor_class_init
5187     (MXFMetadataGenericSoundEssenceDescriptorClass * klass)
5188 {
5189   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
5190   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
5191
5192   metadata_base_class->handle_tag =
5193       mxf_metadata_generic_sound_essence_descriptor_handle_tag;
5194   metadata_base_class->name_quark =
5195       MXF_QUARK (GENERIC_SOUND_ESSENCE_DESCRIPTOR);
5196   metadata_base_class->to_structure =
5197       mxf_metadata_generic_sound_essence_descriptor_to_structure;
5198   metadata_base_class->write_tags =
5199       mxf_metadata_generic_sound_essence_descriptor_write_tags;
5200   metadata_class->type = 0x0142;
5201 }
5202
5203 void mxf_metadata_generic_sound_essence_descriptor_set_caps
5204     (MXFMetadataGenericSoundEssenceDescriptor * self, GstCaps * caps)
5205 {
5206   g_return_if_fail (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (self));
5207   g_return_if_fail (GST_IS_CAPS (caps));
5208
5209   if (self->audio_sampling_rate.n == 0 || self->audio_sampling_rate.d == 0) {
5210     GST_ERROR ("Invalid audio sampling rate");
5211   } else {
5212     gst_caps_set_simple (caps,
5213         "rate", G_TYPE_INT,
5214         (gint) (mxf_fraction_to_double (&self->audio_sampling_rate)
5215             + 0.5), NULL);
5216   }
5217
5218   if (self->channel_count == 0) {
5219     GST_ERROR ("Invalid number of channels (0)");
5220   } else {
5221     gst_caps_set_simple (caps, "channels", G_TYPE_INT, self->channel_count,
5222         NULL);
5223   }
5224 }
5225
5226 gboolean
5227     mxf_metadata_generic_sound_essence_descriptor_from_caps
5228     (MXFMetadataGenericSoundEssenceDescriptor * self, GstCaps * caps) {
5229   gint rate;
5230   gint channels;
5231   GstStructure *s;
5232
5233   g_return_val_if_fail (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (self),
5234       FALSE);
5235   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
5236
5237   s = gst_caps_get_structure (caps, 0);
5238
5239   if (!gst_structure_get_int (s, "rate", &rate) || rate == 0) {
5240     GST_WARNING ("No samplerate");
5241     return FALSE;
5242   } else {
5243     self->audio_sampling_rate.n = rate;
5244     self->audio_sampling_rate.d = 1;
5245   }
5246
5247   if (!gst_structure_get_int (s, "channels", &channels) || channels == 0) {
5248     GST_WARNING ("No channels");
5249     return FALSE;
5250   } else {
5251     self->channel_count = channels;
5252   }
5253
5254   return TRUE;
5255 }
5256
5257
5258 G_DEFINE_TYPE (MXFMetadataCDCIPictureEssenceDescriptor,
5259     mxf_metadata_cdci_picture_essence_descriptor,
5260     MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
5261
5262 static gboolean
5263 mxf_metadata_cdci_picture_essence_descriptor_handle_tag (MXFMetadataBase *
5264     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
5265     guint tag_size)
5266 {
5267   MXFMetadataCDCIPictureEssenceDescriptor *self =
5268       MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR (metadata);
5269   gboolean ret = TRUE;
5270
5271   switch (tag) {
5272     case 0x3301:
5273       if (tag_size != 4)
5274         goto error;
5275       self->component_depth = GST_READ_UINT32_BE (tag_data);
5276       GST_DEBUG ("  component depth = %u", self->component_depth);
5277       break;
5278     case 0x3302:
5279       if (tag_size != 4)
5280         goto error;
5281       self->horizontal_subsampling = GST_READ_UINT32_BE (tag_data);
5282       GST_DEBUG ("  horizontal subsampling = %u", self->horizontal_subsampling);
5283       break;
5284     case 0x3308:
5285       if (tag_size != 4)
5286         goto error;
5287       self->vertical_subsampling = GST_READ_UINT32_BE (tag_data);
5288       GST_DEBUG ("  vertical subsampling = %u", self->vertical_subsampling);
5289       break;
5290     case 0x3303:
5291       if (tag_size != 1)
5292         goto error;
5293       self->color_siting = GST_READ_UINT8 (tag_data);
5294       GST_DEBUG ("  color siting = %u", self->color_siting);
5295       break;
5296     case 0x330b:
5297       if (tag_size != 1)
5298         goto error;
5299       self->reversed_byte_order = GST_READ_UINT8 (tag_data);
5300       GST_DEBUG ("  reversed byte order = %s",
5301           (self->reversed_byte_order) ? "yes" : "no");
5302       break;
5303     case 0x3307:
5304       if (tag_size != 2)
5305         goto error;
5306       self->padding_bits = GST_READ_UINT16_BE (tag_data);
5307       GST_DEBUG ("  padding bits = %d", self->padding_bits);
5308       break;
5309     case 0x3309:
5310       if (tag_size != 4)
5311         goto error;
5312       self->alpha_sample_depth = GST_READ_UINT32_BE (tag_data);
5313       GST_DEBUG ("  alpha sample depth = %u", self->alpha_sample_depth);
5314       break;
5315     case 0x3304:
5316       if (tag_size != 4)
5317         goto error;
5318       self->black_ref_level = GST_READ_UINT32_BE (tag_data);
5319       GST_DEBUG ("  black ref level = %u", self->black_ref_level);
5320       break;
5321     case 0x3305:
5322       if (tag_size != 4)
5323         goto error;
5324       self->white_ref_level = GST_READ_UINT32_BE (tag_data);
5325       GST_DEBUG ("  white ref level = %u", self->white_ref_level);
5326       break;
5327     case 0x3306:
5328       if (tag_size != 4)
5329         goto error;
5330       self->color_range = GST_READ_UINT32_BE (tag_data);
5331       GST_DEBUG ("  color range = %u", self->color_range);
5332       break;
5333     default:
5334       ret =
5335           MXF_METADATA_BASE_CLASS
5336           (mxf_metadata_cdci_picture_essence_descriptor_parent_class)->
5337           handle_tag (metadata, primer, tag, tag_data, tag_size);
5338       break;
5339   }
5340
5341   return ret;
5342
5343 error:
5344
5345   GST_ERROR
5346       ("Invalid CDCI picture essence descriptor local tag 0x%04x of size %u",
5347       tag, tag_size);
5348
5349   return FALSE;
5350 }
5351
5352 static GstStructure *
5353 mxf_metadata_cdci_picture_essence_descriptor_to_structure (MXFMetadataBase * m)
5354 {
5355   GstStructure *ret =
5356       MXF_METADATA_BASE_CLASS
5357       (mxf_metadata_cdci_picture_essence_descriptor_parent_class)->to_structure
5358       (m);
5359   MXFMetadataCDCIPictureEssenceDescriptor *self =
5360       MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR (m);
5361
5362   if (self->component_depth != 0)
5363     gst_structure_id_set (ret, MXF_QUARK (COMPONENT_DEPTH), G_TYPE_UINT,
5364         self->component_depth, NULL);
5365
5366   if (self->horizontal_subsampling != 0)
5367     gst_structure_id_set (ret, MXF_QUARK (HORIZONTAL_SUBSAMPLING), G_TYPE_UINT,
5368         self->horizontal_subsampling, NULL);
5369
5370   if (self->vertical_subsampling != 0)
5371     gst_structure_id_set (ret, MXF_QUARK (VERTICAL_SUBSAMPLING), G_TYPE_UINT,
5372         self->vertical_subsampling, NULL);
5373
5374   if (self->color_siting != 255)
5375     gst_structure_id_set (ret, MXF_QUARK (COLOR_SITING), G_TYPE_UCHAR,
5376         self->color_siting, NULL);
5377
5378   gst_structure_id_set (ret, MXF_QUARK (REVERSED_BYTE_ORDER), G_TYPE_BOOLEAN,
5379       self->reversed_byte_order, NULL);
5380
5381   if (self->padding_bits != 0)
5382     gst_structure_id_set (ret, MXF_QUARK (PADDING_BITS), G_TYPE_INT,
5383         self->padding_bits, NULL);
5384
5385   if (self->alpha_sample_depth != 0)
5386     gst_structure_id_set (ret, MXF_QUARK (ALPHA_SAMPLE_DEPTH), G_TYPE_UINT,
5387         self->alpha_sample_depth, NULL);
5388
5389   if (self->black_ref_level != 0)
5390     gst_structure_id_set (ret, MXF_QUARK (BLACK_REF_LEVEL), G_TYPE_UINT,
5391         self->black_ref_level, NULL);
5392
5393   if (self->white_ref_level != 0)
5394     gst_structure_id_set (ret, MXF_QUARK (WHITE_REF_LEVEL), G_TYPE_UINT,
5395         self->white_ref_level, NULL);
5396
5397   if (self->color_range != 0)
5398     gst_structure_id_set (ret, MXF_QUARK (COLOR_RANGE), G_TYPE_UINT,
5399         self->color_range, NULL);
5400
5401   return ret;
5402 }
5403
5404 static GList *
5405 mxf_metadata_cdci_picture_essence_descriptor_write_tags (MXFMetadataBase * m,
5406     MXFPrimerPack * primer)
5407 {
5408   MXFMetadataCDCIPictureEssenceDescriptor *self =
5409       MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR (m);
5410   GList *ret =
5411       MXF_METADATA_BASE_CLASS
5412       (mxf_metadata_cdci_picture_essence_descriptor_parent_class)->write_tags
5413       (m, primer);
5414   MXFLocalTag *t;
5415
5416   if (self->component_depth) {
5417     t = g_slice_new0 (MXFLocalTag);
5418     memcpy (&t->ul, MXF_UL (COMPONENT_DEPTH), 16);
5419     t->size = 4;
5420     t->data = g_slice_alloc (t->size);
5421     t->g_slice = TRUE;
5422     GST_WRITE_UINT32_BE (t->data, self->component_depth);
5423     mxf_primer_pack_add_mapping (primer, 0x3301, &t->ul);
5424     ret = g_list_prepend (ret, t);
5425   }
5426
5427   if (self->horizontal_subsampling) {
5428     t = g_slice_new0 (MXFLocalTag);
5429     memcpy (&t->ul, MXF_UL (HORIZONTAL_SUBSAMPLING), 16);
5430     t->size = 4;
5431     t->data = g_slice_alloc (t->size);
5432     t->g_slice = TRUE;
5433     GST_WRITE_UINT32_BE (t->data, self->horizontal_subsampling);
5434     mxf_primer_pack_add_mapping (primer, 0x3302, &t->ul);
5435     ret = g_list_prepend (ret, t);
5436   }
5437
5438   if (self->vertical_subsampling) {
5439     t = g_slice_new0 (MXFLocalTag);
5440     memcpy (&t->ul, MXF_UL (VERTICAL_SUBSAMPLING), 16);
5441     t->size = 4;
5442     t->data = g_slice_alloc (t->size);
5443     t->g_slice = TRUE;
5444     GST_WRITE_UINT32_BE (t->data, self->vertical_subsampling);
5445     mxf_primer_pack_add_mapping (primer, 0x3308, &t->ul);
5446     ret = g_list_prepend (ret, t);
5447   }
5448
5449   if (self->color_siting != 0xff) {
5450     t = g_slice_new0 (MXFLocalTag);
5451     memcpy (&t->ul, MXF_UL (COLOR_SITING), 16);
5452     t->size = 1;
5453     t->data = g_slice_alloc (t->size);
5454     t->g_slice = TRUE;
5455     GST_WRITE_UINT8 (t->data, self->color_siting);
5456     mxf_primer_pack_add_mapping (primer, 0x3303, &t->ul);
5457     ret = g_list_prepend (ret, t);
5458   }
5459
5460   if (self->reversed_byte_order) {
5461     t = g_slice_new0 (MXFLocalTag);
5462     memcpy (&t->ul, MXF_UL (REVERSED_BYTE_ORDER), 16);
5463     t->size = 1;
5464     t->data = g_slice_alloc (t->size);
5465     t->g_slice = TRUE;
5466     GST_WRITE_UINT8 (t->data, (self->reversed_byte_order) ? 1 : 0);
5467     mxf_primer_pack_add_mapping (primer, 0x330b, &t->ul);
5468     ret = g_list_prepend (ret, t);
5469   }
5470
5471   if (self->padding_bits) {
5472     t = g_slice_new0 (MXFLocalTag);
5473     memcpy (&t->ul, MXF_UL (PADDING_BITS), 16);
5474     t->size = 2;
5475     t->data = g_slice_alloc (t->size);
5476     t->g_slice = TRUE;
5477     GST_WRITE_UINT16_BE (t->data, self->padding_bits);
5478     mxf_primer_pack_add_mapping (primer, 0x3307, &t->ul);
5479     ret = g_list_prepend (ret, t);
5480   }
5481
5482   if (self->alpha_sample_depth) {
5483     t = g_slice_new0 (MXFLocalTag);
5484     memcpy (&t->ul, MXF_UL (ALPHA_SAMPLE_DEPTH), 16);
5485     t->size = 4;
5486     t->data = g_slice_alloc (t->size);
5487     t->g_slice = TRUE;
5488     GST_WRITE_UINT32_BE (t->data, self->alpha_sample_depth);
5489     mxf_primer_pack_add_mapping (primer, 0x3309, &t->ul);
5490     ret = g_list_prepend (ret, t);
5491   }
5492
5493   if (self->black_ref_level) {
5494     t = g_slice_new0 (MXFLocalTag);
5495     memcpy (&t->ul, MXF_UL (BLACK_REF_LEVEL), 16);
5496     t->size = 4;
5497     t->data = g_slice_alloc (t->size);
5498     t->g_slice = TRUE;
5499     GST_WRITE_UINT32_BE (t->data, self->black_ref_level);
5500     mxf_primer_pack_add_mapping (primer, 0x3304, &t->ul);
5501     ret = g_list_prepend (ret, t);
5502   }
5503
5504   if (self->white_ref_level) {
5505     t = g_slice_new0 (MXFLocalTag);
5506     memcpy (&t->ul, MXF_UL (WHITE_REF_LEVEL), 16);
5507     t->size = 4;
5508     t->data = g_slice_alloc (t->size);
5509     t->g_slice = TRUE;
5510     GST_WRITE_UINT32_BE (t->data, self->white_ref_level);
5511     mxf_primer_pack_add_mapping (primer, 0x3305, &t->ul);
5512     ret = g_list_prepend (ret, t);
5513   }
5514
5515   if (self->color_range) {
5516     t = g_slice_new0 (MXFLocalTag);
5517     memcpy (&t->ul, MXF_UL (COLOR_RANGE), 16);
5518     t->size = 4;
5519     t->data = g_slice_alloc (t->size);
5520     t->g_slice = TRUE;
5521     GST_WRITE_UINT32_BE (t->data, self->color_range);
5522     mxf_primer_pack_add_mapping (primer, 0x3306, &t->ul);
5523     ret = g_list_prepend (ret, t);
5524   }
5525
5526   return ret;
5527 }
5528
5529 static void
5530     mxf_metadata_cdci_picture_essence_descriptor_init
5531     (MXFMetadataCDCIPictureEssenceDescriptor * self)
5532 {
5533   self->color_siting = 0xff;
5534 }
5535
5536 static void
5537     mxf_metadata_cdci_picture_essence_descriptor_class_init
5538     (MXFMetadataCDCIPictureEssenceDescriptorClass * klass)
5539 {
5540   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
5541   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
5542
5543   metadata_base_class->handle_tag =
5544       mxf_metadata_cdci_picture_essence_descriptor_handle_tag;
5545   metadata_base_class->name_quark = MXF_QUARK (CDCI_PICTURE_ESSENCE_DESCRIPTOR);
5546   metadata_base_class->to_structure =
5547       mxf_metadata_cdci_picture_essence_descriptor_to_structure;
5548   metadata_base_class->write_tags =
5549       mxf_metadata_cdci_picture_essence_descriptor_write_tags;
5550   metadata_class->type = 0x0128;
5551 }
5552
5553 G_DEFINE_TYPE (MXFMetadataRGBAPictureEssenceDescriptor,
5554     mxf_metadata_rgba_picture_essence_descriptor,
5555     MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
5556
5557 static void
5558 mxf_metadata_rgba_picture_essence_descriptor_finalize (GObject * object)
5559 {
5560   MXFMetadataRGBAPictureEssenceDescriptor *self =
5561       MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (object);
5562
5563   g_free (self->pixel_layout);
5564   self->pixel_layout = NULL;
5565
5566   G_OBJECT_CLASS
5567       (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->finalize
5568       (object);
5569 }
5570
5571 static gboolean
5572 mxf_metadata_rgba_picture_essence_descriptor_handle_tag (MXFMetadataBase *
5573     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
5574     guint tag_size)
5575 {
5576   MXFMetadataRGBAPictureEssenceDescriptor *self =
5577       MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (metadata);
5578   gboolean ret = TRUE;
5579
5580   switch (tag) {
5581     case 0x3406:
5582       if (tag_size != 4)
5583         goto error;
5584       self->component_max_ref = GST_READ_UINT32_BE (tag_data);
5585       GST_DEBUG ("  component max ref = %u", self->component_max_ref);
5586       break;
5587     case 0x3407:
5588       if (tag_size != 4)
5589         goto error;
5590       self->component_min_ref = GST_READ_UINT32_BE (tag_data);
5591       GST_DEBUG ("  component min ref = %u", self->component_min_ref);
5592       break;
5593     case 0x3408:
5594       if (tag_size != 4)
5595         goto error;
5596       self->alpha_max_ref = GST_READ_UINT32_BE (tag_data);
5597       GST_DEBUG ("  alpha max ref = %u", self->alpha_max_ref);
5598       break;
5599     case 0x3409:
5600       if (tag_size != 4)
5601         goto error;
5602       self->alpha_min_ref = GST_READ_UINT32_BE (tag_data);
5603       GST_DEBUG ("  alpha min ref = %u", self->alpha_min_ref);
5604       break;
5605     case 0x3405:
5606       if (tag_size != 1)
5607         goto error;
5608       self->scanning_direction = GST_READ_UINT8 (tag_data);
5609       GST_DEBUG ("  scanning direction = %u", self->scanning_direction);
5610       break;
5611     case 0x3401:{
5612       guint i, len;
5613
5614       if (tag_size % 2 != 0)
5615         goto error;
5616
5617       i = 0;
5618       while (tag_data[i] != 0 && tag_data[i + 1] != 0 && i + 2 <= tag_size)
5619         i += 2;
5620       len = i / 2;
5621
5622       self->n_pixel_layout = len;
5623       GST_DEBUG ("  number of pixel layouts = %u", len);
5624       if (len == 0)
5625         return TRUE;
5626
5627       self->pixel_layout = g_malloc0 (2 * len);
5628
5629       for (i = 0; i < len; i++) {
5630         self->pixel_layout[2 * i] = tag_data[2 * i];
5631         self->pixel_layout[2 * i + 1] = tag_data[2 * i + 1];
5632         GST_DEBUG ("    pixel layout %u = %c : %u", i,
5633             (gchar) self->pixel_layout[2 * i], self->pixel_layout[2 * i + 1]);
5634       }
5635
5636       break;
5637     }
5638     case 0x3403:
5639     case 0x3404:
5640       /* TODO: handle this */
5641       GST_WARNING ("  tag 0x%04x not implemented yet", tag);
5642       break;
5643     default:
5644       ret =
5645           MXF_METADATA_BASE_CLASS
5646           (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->
5647           handle_tag (metadata, primer, tag, tag_data, tag_size);
5648       break;
5649   }
5650
5651   return ret;
5652
5653 error:
5654
5655   GST_ERROR
5656       ("Invalid RGBA picture essence descriptor local tag 0x%04x of size %u",
5657       tag, tag_size);
5658
5659   return FALSE;
5660 }
5661
5662 static GstStructure *
5663 mxf_metadata_rgba_picture_essence_descriptor_to_structure (MXFMetadataBase * m)
5664 {
5665   GstStructure *ret =
5666       MXF_METADATA_BASE_CLASS
5667       (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->to_structure
5668       (m);
5669   MXFMetadataRGBAPictureEssenceDescriptor *self =
5670       MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (m);
5671
5672   if (self->component_max_ref != 255)
5673     gst_structure_id_set (ret, MXF_QUARK (COMPONENT_MAX_REF), G_TYPE_UINT,
5674         self->component_max_ref, NULL);
5675
5676   if (self->component_min_ref != 0)
5677     gst_structure_id_set (ret, MXF_QUARK (COMPONENT_MIN_REF), G_TYPE_UINT,
5678         self->component_min_ref, NULL);
5679
5680   if (self->alpha_max_ref != 255)
5681     gst_structure_id_set (ret, MXF_QUARK (ALPHA_MAX_REF), G_TYPE_UINT,
5682         self->alpha_max_ref, NULL);
5683
5684   if (self->alpha_min_ref != 0)
5685     gst_structure_id_set (ret, MXF_QUARK (ALPHA_MIN_REF), G_TYPE_UINT,
5686         self->alpha_min_ref, NULL);
5687
5688   if (self->scanning_direction != 0)
5689     gst_structure_id_set (ret, MXF_QUARK (SCANNING_DIRECTION), G_TYPE_UCHAR,
5690         self->scanning_direction, NULL);
5691
5692   if (self->n_pixel_layout != 0) {
5693     gchar *pl = g_new0 (gchar, self->n_pixel_layout * 2 + 1);
5694
5695     memcpy (pl, self->pixel_layout, self->n_pixel_layout * 2);
5696
5697     gst_structure_id_set (ret, MXF_QUARK (PIXEL_LAYOUT), G_TYPE_STRING, pl,
5698         NULL);
5699
5700     g_free (pl);
5701   }
5702
5703   return ret;
5704 }
5705
5706 static GList *
5707 mxf_metadata_rgba_picture_essence_descriptor_write_tags (MXFMetadataBase * m,
5708     MXFPrimerPack * primer)
5709 {
5710   MXFMetadataRGBAPictureEssenceDescriptor *self =
5711       MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (m);
5712   GList *ret =
5713       MXF_METADATA_BASE_CLASS
5714       (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->write_tags
5715       (m, primer);
5716   MXFLocalTag *t;
5717
5718   if (self->component_max_ref != 255) {
5719     t = g_slice_new0 (MXFLocalTag);
5720     memcpy (&t->ul, MXF_UL (COMPONENT_MAX_REF), 16);
5721     t->size = 4;
5722     t->data = g_slice_alloc (t->size);
5723     t->g_slice = TRUE;
5724     GST_WRITE_UINT32_BE (t->data, self->component_max_ref);
5725     mxf_primer_pack_add_mapping (primer, 0x3406, &t->ul);
5726     ret = g_list_prepend (ret, t);
5727   }
5728
5729   if (self->component_min_ref) {
5730     t = g_slice_new0 (MXFLocalTag);
5731     memcpy (&t->ul, MXF_UL (COMPONENT_MIN_REF), 16);
5732     t->size = 4;
5733     t->data = g_slice_alloc (t->size);
5734     t->g_slice = TRUE;
5735     GST_WRITE_UINT32_BE (t->data, self->component_min_ref);
5736     mxf_primer_pack_add_mapping (primer, 0x3407, &t->ul);
5737     ret = g_list_prepend (ret, t);
5738   }
5739
5740   if (self->alpha_max_ref != 255) {
5741     t = g_slice_new0 (MXFLocalTag);
5742     memcpy (&t->ul, MXF_UL (ALPHA_MAX_REF), 16);
5743     t->size = 4;
5744     t->data = g_slice_alloc (t->size);
5745     t->g_slice = TRUE;
5746     GST_WRITE_UINT32_BE (t->data, self->alpha_max_ref);
5747     mxf_primer_pack_add_mapping (primer, 0x3408, &t->ul);
5748     ret = g_list_prepend (ret, t);
5749   }
5750
5751   if (self->alpha_min_ref) {
5752     t = g_slice_new0 (MXFLocalTag);
5753     memcpy (&t->ul, MXF_UL (ALPHA_MIN_REF), 16);
5754     t->size = 4;
5755     t->data = g_slice_alloc (t->size);
5756     t->g_slice = TRUE;
5757     GST_WRITE_UINT32_BE (t->data, self->alpha_min_ref);
5758     mxf_primer_pack_add_mapping (primer, 0x3409, &t->ul);
5759     ret = g_list_prepend (ret, t);
5760   }
5761
5762   if (self->scanning_direction) {
5763     t = g_slice_new0 (MXFLocalTag);
5764     memcpy (&t->ul, MXF_UL (SCANNING_DIRECTION), 16);
5765     t->size = 1;
5766     t->data = g_slice_alloc (t->size);
5767     t->g_slice = TRUE;
5768     GST_WRITE_UINT8 (t->data, self->scanning_direction);
5769     mxf_primer_pack_add_mapping (primer, 0x3405, &t->ul);
5770     ret = g_list_prepend (ret, t);
5771   }
5772
5773   if (self->pixel_layout) {
5774     t = g_slice_new0 (MXFLocalTag);
5775     memcpy (&t->ul, MXF_UL (PIXEL_LAYOUT), 16);
5776     t->size = 2 * self->n_pixel_layout + 2;
5777     t->data = g_slice_alloc0 (t->size);
5778     t->g_slice = TRUE;
5779     memcpy (t->data, self->pixel_layout, self->n_pixel_layout * 2);
5780     mxf_primer_pack_add_mapping (primer, 0x3401, &t->ul);
5781     ret = g_list_prepend (ret, t);
5782
5783   }
5784
5785   return ret;
5786 }
5787
5788 static void
5789     mxf_metadata_rgba_picture_essence_descriptor_init
5790     (MXFMetadataRGBAPictureEssenceDescriptor * self)
5791 {
5792   self->component_max_ref = 255;
5793   self->alpha_max_ref = 255;
5794 }
5795
5796 static void
5797     mxf_metadata_rgba_picture_essence_descriptor_class_init
5798     (MXFMetadataRGBAPictureEssenceDescriptorClass * klass)
5799 {
5800   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
5801   GObjectClass *object_class = (GObjectClass *) klass;
5802   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
5803
5804   object_class->finalize =
5805       mxf_metadata_rgba_picture_essence_descriptor_finalize;
5806   metadata_base_class->handle_tag =
5807       mxf_metadata_rgba_picture_essence_descriptor_handle_tag;
5808   metadata_base_class->name_quark = MXF_QUARK (RGBA_PICTURE_ESSENCE_DESCRIPTOR);
5809   metadata_base_class->to_structure =
5810       mxf_metadata_rgba_picture_essence_descriptor_to_structure;
5811   metadata_base_class->write_tags =
5812       mxf_metadata_rgba_picture_essence_descriptor_write_tags;
5813   metadata_class->type = 0x0129;
5814 }
5815
5816 G_DEFINE_TYPE (MXFMetadataGenericDataEssenceDescriptor,
5817     mxf_metadata_generic_data_essence_descriptor,
5818     MXF_TYPE_METADATA_FILE_DESCRIPTOR);
5819
5820 static gboolean
5821 mxf_metadata_generic_data_essence_descriptor_handle_tag (MXFMetadataBase *
5822     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
5823     guint tag_size)
5824 {
5825   MXFMetadataGenericDataEssenceDescriptor *self =
5826       MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR (metadata);
5827   gboolean ret = TRUE;
5828 #ifndef GST_DISABLE_GST_DEBUG
5829   gchar str[48];
5830 #endif
5831
5832   switch (tag) {
5833     case 0x3e01:
5834       if (tag_size != 16)
5835         goto error;
5836       memcpy (&self->data_essence_coding, tag_data, 16);
5837       GST_DEBUG ("  data essence coding = %s",
5838           mxf_ul_to_string (&self->data_essence_coding, str));
5839       break;
5840     default:
5841       ret =
5842           MXF_METADATA_BASE_CLASS
5843           (mxf_metadata_generic_data_essence_descriptor_parent_class)->
5844           handle_tag (metadata, primer, tag, tag_data, tag_size);
5845       break;
5846   }
5847
5848   return ret;
5849
5850 error:
5851
5852   GST_ERROR
5853       ("Invalid generic data essence descriptor local tag 0x%04x of size %u",
5854       tag, tag_size);
5855
5856   return FALSE;
5857 }
5858
5859 static GstStructure *
5860 mxf_metadata_generic_data_essence_descriptor_to_structure (MXFMetadataBase * m)
5861 {
5862   GstStructure *ret =
5863       MXF_METADATA_BASE_CLASS
5864       (mxf_metadata_generic_data_essence_descriptor_parent_class)->to_structure
5865       (m);
5866   MXFMetadataGenericDataEssenceDescriptor *self =
5867       MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR (m);
5868   gchar str[48];
5869
5870   if (!mxf_ul_is_zero (&self->data_essence_coding)) {
5871     mxf_ul_to_string (&self->data_essence_coding, str);
5872     gst_structure_id_set (ret, MXF_QUARK (DATA_ESSENCE_CODING), G_TYPE_STRING,
5873         str, NULL);
5874   }
5875
5876   return ret;
5877 }
5878
5879 static GList *
5880 mxf_metadata_generic_data_essence_descriptor_write_tags (MXFMetadataBase * m,
5881     MXFPrimerPack * primer)
5882 {
5883   MXFMetadataGenericDataEssenceDescriptor *self =
5884       MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR (m);
5885   GList *ret =
5886       MXF_METADATA_BASE_CLASS
5887       (mxf_metadata_generic_data_essence_descriptor_parent_class)->write_tags
5888       (m, primer);
5889   MXFLocalTag *t;
5890
5891   if (!mxf_ul_is_zero (&self->data_essence_coding)) {
5892     t = g_slice_new0 (MXFLocalTag);
5893     memcpy (&t->ul, MXF_UL (DATA_ESSENCE_CODING), 16);
5894     t->size = 16;
5895     t->data = g_slice_alloc (t->size);
5896     t->g_slice = TRUE;
5897     memcpy (t->data, &self->data_essence_coding, 16);
5898     mxf_primer_pack_add_mapping (primer, 0x3e01, &t->ul);
5899     ret = g_list_prepend (ret, t);
5900   }
5901
5902   return ret;
5903 }
5904
5905 static void
5906     mxf_metadata_generic_data_essence_descriptor_init
5907     (MXFMetadataGenericDataEssenceDescriptor * self)
5908 {
5909
5910 }
5911
5912 static void
5913     mxf_metadata_generic_data_essence_descriptor_class_init
5914     (MXFMetadataGenericDataEssenceDescriptorClass * klass)
5915 {
5916   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
5917   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
5918
5919   metadata_base_class->handle_tag =
5920       mxf_metadata_generic_data_essence_descriptor_handle_tag;
5921   metadata_base_class->name_quark = MXF_QUARK (GENERIC_DATA_ESSENCE_DESCRIPTOR);
5922   metadata_base_class->to_structure =
5923       mxf_metadata_generic_data_essence_descriptor_to_structure;
5924   metadata_base_class->write_tags =
5925       mxf_metadata_generic_data_essence_descriptor_write_tags;
5926   metadata_class->type = 0x0143;
5927 }
5928
5929 G_DEFINE_TYPE (MXFMetadataMultipleDescriptor, mxf_metadata_multiple_descriptor,
5930     MXF_TYPE_METADATA_FILE_DESCRIPTOR);
5931
5932 static void
5933 mxf_metadata_multiple_descriptor_finalize (GObject * object)
5934 {
5935   MXFMetadataMultipleDescriptor *self =
5936       MXF_METADATA_MULTIPLE_DESCRIPTOR (object);
5937
5938   g_free (self->sub_descriptors_uids);
5939   self->sub_descriptors_uids = NULL;
5940   g_free (self->sub_descriptors);
5941   self->sub_descriptors = NULL;
5942
5943   G_OBJECT_CLASS
5944       (mxf_metadata_multiple_descriptor_parent_class)->finalize (object);
5945 }
5946
5947 static gboolean
5948 mxf_metadata_multiple_descriptor_handle_tag (MXFMetadataBase * metadata,
5949     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
5950     guint tag_size)
5951 {
5952   MXFMetadataMultipleDescriptor *self =
5953       MXF_METADATA_MULTIPLE_DESCRIPTOR (metadata);
5954   gboolean ret = TRUE;
5955 #ifndef GST_DISABLE_GST_DEBUG
5956   gchar str[48];
5957 #endif
5958
5959   switch (tag) {
5960     case 0x3f01:
5961       if (!mxf_uuid_array_parse (&self->sub_descriptors_uids,
5962               &self->n_sub_descriptors, tag_data, tag_size))
5963         goto error;
5964
5965       GST_DEBUG ("  number of sub descriptors = %u", self->n_sub_descriptors);
5966 #ifndef GST_DISABLE_GST_DEBUG
5967       {
5968         guint i;
5969         for (i = 0; i < self->n_sub_descriptors; i++) {
5970           GST_DEBUG ("    sub descriptor %u = %s", i,
5971               mxf_uuid_to_string (&self->sub_descriptors_uids[i], str));
5972         }
5973       }
5974 #endif
5975
5976       break;
5977     default:
5978       ret =
5979           MXF_METADATA_BASE_CLASS
5980           (mxf_metadata_multiple_descriptor_parent_class)->handle_tag (metadata,
5981           primer, tag, tag_data, tag_size);
5982       break;
5983   }
5984
5985   return ret;
5986
5987 error:
5988
5989   GST_ERROR ("Invalid multiple descriptor local tag 0x%04x of size %u", tag,
5990       tag_size);
5991
5992   return FALSE;
5993 }
5994
5995 static gboolean
5996 mxf_metadata_multiple_descriptor_resolve (MXFMetadataBase * m,
5997     GHashTable * metadata)
5998 {
5999   MXFMetadataMultipleDescriptor *self = MXF_METADATA_MULTIPLE_DESCRIPTOR (m);
6000   MXFMetadataBase *current = NULL;
6001   guint i, have_subdescriptors = 0;
6002
6003   if (self->sub_descriptors)
6004     memset (self->sub_descriptors, 0,
6005         sizeof (gpointer) * self->n_sub_descriptors);
6006   else
6007     self->sub_descriptors =
6008         g_new0 (MXFMetadataGenericDescriptor *, self->n_sub_descriptors);
6009   for (i = 0; i < self->n_sub_descriptors; i++) {
6010     current = g_hash_table_lookup (metadata, &self->sub_descriptors_uids[i]);
6011     if (current && MXF_IS_METADATA_GENERIC_DESCRIPTOR (current)) {
6012       if (mxf_metadata_base_resolve (current, metadata)) {
6013         self->sub_descriptors[i] = MXF_METADATA_GENERIC_DESCRIPTOR (current);
6014         have_subdescriptors++;
6015       } else {
6016         GST_ERROR ("Couldn't resolve descriptor");
6017         return FALSE;
6018       }
6019     } else {
6020       GST_ERROR ("Descriptor not found");
6021       return FALSE;
6022     }
6023   }
6024
6025   return
6026       MXF_METADATA_BASE_CLASS
6027       (mxf_metadata_multiple_descriptor_parent_class)->resolve (m, metadata);
6028 }
6029
6030 static GstStructure *
6031 mxf_metadata_multiple_descriptor_to_structure (MXFMetadataBase * m)
6032 {
6033   GstStructure *ret =
6034       MXF_METADATA_BASE_CLASS
6035       (mxf_metadata_multiple_descriptor_parent_class)->to_structure (m);
6036   MXFMetadataMultipleDescriptor *self = MXF_METADATA_MULTIPLE_DESCRIPTOR (m);
6037   guint i;
6038
6039   if (self->n_sub_descriptors > 0) {
6040     GValue arr = { 0, }
6041     , val = {
6042     0,};
6043
6044     g_value_init (&arr, GST_TYPE_ARRAY);
6045
6046     for (i = 0; i < self->n_sub_descriptors; i++) {
6047       GstStructure *s;
6048
6049       if (self->sub_descriptors[i] == NULL)
6050         continue;
6051
6052       g_value_init (&val, GST_TYPE_STRUCTURE);
6053
6054       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE
6055           (self->sub_descriptors[i]));
6056       gst_value_set_structure (&val, s);
6057       gst_structure_free (s);
6058       gst_value_array_append_value (&arr, &val);
6059       g_value_unset (&val);
6060     }
6061
6062     if (gst_value_array_get_size (&arr) > 0)
6063       gst_structure_id_set_value (ret, MXF_QUARK (SUB_DESCRIPTORS), &arr);
6064
6065     g_value_unset (&arr);
6066   }
6067
6068   return ret;
6069 }
6070
6071 static GList *
6072 mxf_metadata_multiple_descriptor_write_tags (MXFMetadataBase * m,
6073     MXFPrimerPack * primer)
6074 {
6075   MXFMetadataMultipleDescriptor *self = MXF_METADATA_MULTIPLE_DESCRIPTOR (m);
6076   GList *ret =
6077       MXF_METADATA_BASE_CLASS
6078       (mxf_metadata_multiple_descriptor_parent_class)->write_tags (m, primer);
6079   MXFLocalTag *t;
6080
6081   if (self->sub_descriptors) {
6082     guint i;
6083
6084     t = g_slice_new0 (MXFLocalTag);
6085     memcpy (&t->ul, MXF_UL (SUB_DESCRIPTORS), 16);
6086     t->size = 8 + 16 * self->n_sub_descriptors;
6087     t->data = g_slice_alloc0 (t->size);
6088     t->g_slice = TRUE;
6089     GST_WRITE_UINT32_BE (t->data, self->n_sub_descriptors);
6090     GST_WRITE_UINT32_BE (t->data + 4, 16);
6091     for (i = 0; i < self->n_sub_descriptors; i++) {
6092       if (!self->sub_descriptors[i])
6093         continue;
6094
6095       memcpy (t->data + 8 + 16 * i,
6096           &MXF_METADATA_BASE (self->sub_descriptors[i])->instance_uid, 16);
6097     }
6098     mxf_primer_pack_add_mapping (primer, 0x3f01, &t->ul);
6099     ret = g_list_prepend (ret, t);
6100   }
6101
6102   return ret;
6103 }
6104
6105 static void
6106 mxf_metadata_multiple_descriptor_init (MXFMetadataMultipleDescriptor * self)
6107 {
6108
6109 }
6110
6111 static void
6112 mxf_metadata_multiple_descriptor_class_init (MXFMetadataMultipleDescriptorClass
6113     * klass)
6114 {
6115   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
6116   GObjectClass *object_class = (GObjectClass *) klass;
6117   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
6118
6119   object_class->finalize = mxf_metadata_multiple_descriptor_finalize;
6120   metadata_base_class->handle_tag = mxf_metadata_multiple_descriptor_handle_tag;
6121   metadata_base_class->resolve = mxf_metadata_multiple_descriptor_resolve;
6122   metadata_base_class->name_quark = MXF_QUARK (MULTIPLE_DESCRIPTOR);
6123   metadata_base_class->to_structure =
6124       mxf_metadata_multiple_descriptor_to_structure;
6125   metadata_base_class->write_tags = mxf_metadata_multiple_descriptor_write_tags;
6126   metadata_class->type = 0x0144;
6127 }
6128
6129 G_DEFINE_ABSTRACT_TYPE (MXFMetadataLocator, mxf_metadata_locator,
6130     MXF_TYPE_METADATA);
6131
6132 static void
6133 mxf_metadata_locator_init (MXFMetadataLocator * self)
6134 {
6135 }
6136
6137 static void
6138 mxf_metadata_locator_class_init (MXFMetadataLocatorClass * klass)
6139 {
6140 }
6141
6142 G_DEFINE_TYPE (MXFMetadataTextLocator, mxf_metadata_text_locator,
6143     MXF_TYPE_METADATA_LOCATOR);
6144
6145 static void
6146 mxf_metadata_text_locator_finalize (GObject * object)
6147 {
6148   MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (object);
6149
6150   g_free (self->locator_name);
6151   self->locator_name = NULL;
6152
6153   G_OBJECT_CLASS (mxf_metadata_text_locator_parent_class)->finalize (object);
6154 }
6155
6156 static gboolean
6157 mxf_metadata_text_locator_handle_tag (MXFMetadataBase * metadata,
6158     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
6159     guint tag_size)
6160 {
6161   MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (metadata);
6162   gboolean ret = TRUE;
6163
6164   switch (tag) {
6165     case 0x4101:
6166       self->locator_name = mxf_utf16_to_utf8 (tag_data, tag_size);
6167       GST_DEBUG ("  text locator = %s", GST_STR_NULL (self->locator_name));
6168       break;
6169     default:
6170       ret =
6171           MXF_METADATA_BASE_CLASS
6172           (mxf_metadata_text_locator_parent_class)->handle_tag (metadata,
6173           primer, tag, tag_data, tag_size);
6174       break;
6175   }
6176
6177   return ret;
6178 }
6179
6180 static GstStructure *
6181 mxf_metadata_text_locator_to_structure (MXFMetadataBase * m)
6182 {
6183   GstStructure *ret =
6184       MXF_METADATA_BASE_CLASS
6185       (mxf_metadata_text_locator_parent_class)->to_structure (m);
6186   MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (m);
6187
6188   gst_structure_id_set (ret, MXF_QUARK (LOCATOR_NAME), G_TYPE_STRING,
6189       self->locator_name, NULL);
6190
6191   return ret;
6192 }
6193
6194 static GList *
6195 mxf_metadata_text_locator_write_tags (MXFMetadataBase * m,
6196     MXFPrimerPack * primer)
6197 {
6198   MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (m);
6199   GList *ret =
6200       MXF_METADATA_BASE_CLASS
6201       (mxf_metadata_text_locator_parent_class)->write_tags (m, primer);
6202   MXFLocalTag *t;
6203
6204   if (self->locator_name) {
6205     t = g_slice_new0 (MXFLocalTag);
6206     memcpy (&t->ul, MXF_UL (LOCATOR_NAME), 16);
6207     t->data = mxf_utf8_to_utf16 (self->locator_name, &t->size);
6208     mxf_primer_pack_add_mapping (primer, 0x4101, &t->ul);
6209     ret = g_list_prepend (ret, t);
6210   }
6211
6212   return ret;
6213 }
6214
6215 static void
6216 mxf_metadata_text_locator_init (MXFMetadataTextLocator * self)
6217 {
6218
6219 }
6220
6221 static void
6222 mxf_metadata_text_locator_class_init (MXFMetadataTextLocatorClass * klass)
6223 {
6224   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
6225   GObjectClass *object_class = (GObjectClass *) klass;
6226   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
6227
6228   object_class->finalize = mxf_metadata_text_locator_finalize;
6229   metadata_base_class->handle_tag = mxf_metadata_text_locator_handle_tag;
6230   metadata_base_class->name_quark = MXF_QUARK (TEXT_LOCATOR);
6231   metadata_base_class->to_structure = mxf_metadata_text_locator_to_structure;
6232   metadata_base_class->write_tags = mxf_metadata_text_locator_write_tags;
6233   metadata_class->type = 0x0133;
6234 }
6235
6236 G_DEFINE_TYPE (MXFMetadataNetworkLocator, mxf_metadata_network_locator,
6237     MXF_TYPE_METADATA_LOCATOR);
6238
6239 static void
6240 mxf_metadata_network_locator_finalize (GObject * object)
6241 {
6242   MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (object);
6243
6244   g_free (self->url_string);
6245   self->url_string = NULL;
6246
6247   G_OBJECT_CLASS (mxf_metadata_network_locator_parent_class)->finalize (object);
6248 }
6249
6250 static gboolean
6251 mxf_metadata_network_locator_handle_tag (MXFMetadataBase * metadata,
6252     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
6253     guint tag_size)
6254 {
6255   MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (metadata);
6256   gboolean ret = TRUE;
6257
6258   switch (tag) {
6259     case 0x4101:
6260       self->url_string = mxf_utf16_to_utf8 (tag_data, tag_size);
6261       GST_DEBUG ("  url string = %s", GST_STR_NULL (self->url_string));
6262       break;
6263     default:
6264       ret =
6265           MXF_METADATA_BASE_CLASS
6266           (mxf_metadata_network_locator_parent_class)->handle_tag (metadata,
6267           primer, tag, tag_data, tag_size);
6268       break;
6269   }
6270
6271   return ret;
6272 }
6273
6274 static GstStructure *
6275 mxf_metadata_network_locator_to_structure (MXFMetadataBase * m)
6276 {
6277   GstStructure *ret =
6278       MXF_METADATA_BASE_CLASS
6279       (mxf_metadata_network_locator_parent_class)->to_structure (m);
6280   MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (m);
6281
6282   gst_structure_id_set (ret, MXF_QUARK (URL_STRING), G_TYPE_STRING,
6283       self->url_string, NULL);
6284
6285   return ret;
6286 }
6287
6288 static GList *
6289 mxf_metadata_network_locator_write_tags (MXFMetadataBase * m,
6290     MXFPrimerPack * primer)
6291 {
6292   MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (m);
6293   GList *ret =
6294       MXF_METADATA_BASE_CLASS
6295       (mxf_metadata_network_locator_parent_class)->write_tags (m, primer);
6296   MXFLocalTag *t;
6297
6298   if (self->url_string) {
6299     t = g_slice_new0 (MXFLocalTag);
6300     memcpy (&t->ul, MXF_UL (URL_STRING), 16);
6301     t->data = mxf_utf8_to_utf16 (self->url_string, &t->size);
6302     mxf_primer_pack_add_mapping (primer, 0x4001, &t->ul);
6303     ret = g_list_prepend (ret, t);
6304   }
6305
6306   return ret;
6307 }
6308
6309 static void
6310 mxf_metadata_network_locator_init (MXFMetadataNetworkLocator * self)
6311 {
6312 }
6313
6314 static void
6315 mxf_metadata_network_locator_class_init (MXFMetadataNetworkLocatorClass * klass)
6316 {
6317   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
6318   GObjectClass *object_class = (GObjectClass *) klass;
6319   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
6320
6321   object_class->finalize = mxf_metadata_network_locator_finalize;
6322   metadata_base_class->handle_tag = mxf_metadata_network_locator_handle_tag;
6323   metadata_base_class->name_quark = MXF_QUARK (NETWORK_LOCATOR);
6324   metadata_base_class->to_structure = mxf_metadata_network_locator_to_structure;
6325   metadata_base_class->write_tags = mxf_metadata_network_locator_write_tags;
6326   metadata_class->type = 0x0133;
6327 }
6328
6329 G_DEFINE_ABSTRACT_TYPE (MXFDescriptiveMetadata, mxf_descriptive_metadata,
6330     MXF_TYPE_METADATA_BASE);
6331
6332 static void
6333 mxf_descriptive_metadata_init (MXFDescriptiveMetadata * self)
6334 {
6335 }
6336
6337 static void
6338 mxf_descriptive_metadata_class_init (MXFDescriptiveMetadataClass * klass)
6339 {
6340 }
6341
6342 typedef struct
6343 {
6344   guint8 scheme;
6345   GType *types;
6346 } _MXFDescriptiveMetadataScheme;
6347
6348 static GArray *_dm_schemes = NULL;
6349
6350 void
6351 mxf_descriptive_metadata_register (guint8 scheme, GType * types)
6352 {
6353   _MXFDescriptiveMetadataScheme s;
6354
6355   if (!_dm_schemes)
6356     _dm_schemes =
6357         g_array_new (FALSE, TRUE, sizeof (_MXFDescriptiveMetadataScheme));
6358
6359   s.scheme = scheme;
6360   s.types = types;
6361
6362   g_array_append_val (_dm_schemes, s);
6363 }
6364
6365 MXFDescriptiveMetadata *
6366 mxf_descriptive_metadata_new (guint8 scheme, guint32 type,
6367     MXFPrimerPack * primer, guint64 offset, const guint8 * data, guint size)
6368 {
6369   guint i;
6370   GType t = G_TYPE_INVALID, *p;
6371   _MXFDescriptiveMetadataScheme *s = NULL;
6372   MXFDescriptiveMetadata *ret = NULL;
6373
6374   g_return_val_if_fail (primer != NULL, NULL);
6375
6376   if (G_UNLIKELY (type == 0)) {
6377     GST_WARNING ("Type 0 is invalid");
6378     return NULL;
6379   }
6380
6381   for (i = 0; i < _dm_schemes->len; i++) {
6382     _MXFDescriptiveMetadataScheme *data =
6383         &g_array_index (_dm_schemes, _MXFDescriptiveMetadataScheme, i);
6384
6385     if (data->scheme == scheme) {
6386       s = data;
6387       break;
6388     }
6389   }
6390
6391   if (s == NULL) {
6392     GST_WARNING ("Descriptive metadata scheme 0x%02x not supported", scheme);
6393     return NULL;
6394   }
6395
6396   p = s->types;
6397   while (*p) {
6398     GType tmp = *p;
6399     MXFDescriptiveMetadataClass *klass =
6400         MXF_DESCRIPTIVE_METADATA_CLASS (g_type_class_ref (tmp));
6401
6402     if (klass->type == type) {
6403       g_type_class_unref (klass);
6404       t = tmp;
6405       break;
6406     }
6407     g_type_class_unref (klass);
6408     p++;
6409   }
6410
6411   if (t == G_TYPE_INVALID) {
6412     GST_WARNING
6413         ("No handler for type 0x%06x of descriptive metadata scheme 0x%02x found",
6414         type, scheme);
6415     return NULL;
6416   }
6417
6418   GST_DEBUG ("DM scheme 0x%02x type 0x%06x is handled by type %s", scheme, type,
6419       g_type_name (t));
6420
6421   ret = (MXFDescriptiveMetadata *) g_type_create_instance (t);
6422   if (!mxf_metadata_base_parse (MXF_METADATA_BASE (ret), primer, data, size)) {
6423     GST_ERROR ("Parsing metadata failed");
6424     g_object_unref (ret);
6425     return NULL;
6426   }
6427
6428   ret->parent.offset = offset;
6429
6430   return ret;
6431 }
6432
6433 GType
6434 mxf_descriptive_metadata_framework_get_type (void)
6435 {
6436   static volatile gsize type = 0;
6437   if (g_once_init_enter (&type)) {
6438     GType _type = 0;
6439     static const GTypeInfo info = {
6440       sizeof (MXFDescriptiveMetadataFrameworkInterface),
6441       NULL,                     /* base_init */
6442       NULL,                     /* base_finalize */
6443       NULL,                     /* class_init */
6444       NULL,                     /* class_finalize */
6445       NULL,                     /* class_data */
6446       0,                        /* instance_size */
6447       0,                        /* n_preallocs */
6448       NULL                      /* instance_init */
6449     };
6450     _type = g_type_register_static (G_TYPE_INTERFACE,
6451         "MXFDescriptiveMetadataFrameworkInterface", &info, 0);
6452
6453     g_type_interface_add_prerequisite (_type, MXF_TYPE_DESCRIPTIVE_METADATA);
6454
6455     g_once_init_leave (&type, (gsize) _type);
6456   }
6457
6458   return (GType) type;
6459 }
6460
6461 GHashTable *
6462 mxf_metadata_hash_table_new (void)
6463 {
6464   return g_hash_table_new_full ((GHashFunc) mxf_uuid_hash,
6465       (GEqualFunc) mxf_uuid_is_equal, (GDestroyNotify) NULL,
6466       (GDestroyNotify) g_object_unref);
6467 }