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