gst/mxf/: Convert the structural metadata to GstMiniObjects to make a lot of code...
authorSebastian Dröge <slomo@circular-chaos.org>
Mon, 15 Dec 2008 17:27:00 +0000 (17:27 +0000)
committerSebastian Dröge <slomo@circular-chaos.org>
Mon, 15 Dec 2008 17:27:00 +0000 (17:27 +0000)
Original commit message from CVS:
* gst/mxf/Makefile.am:
* gst/mxf/mxf.c: (plugin_init):
* gst/mxf/mxfaes-bwf.c:
(mxf_metadata_wave_audio_essence_descriptor_handle_tag),
(mxf_metadata_wave_audio_essence_descriptor_init),
(mxf_metadata_wave_audio_essence_descriptor_class_init),
(mxf_metadata_aes3_audio_essence_descriptor_finalize),
(mxf_metadata_aes3_audio_essence_descriptor_handle_tag),
(mxf_metadata_aes3_audio_essence_descriptor_init),
(mxf_metadata_aes3_audio_essence_descriptor_class_init),
(mxf_is_aes_bwf_essence_track), (mxf_bwf_create_caps),
(mxf_aes3_create_caps), (mxf_aes_bwf_create_caps),
(mxf_aes_bwf_init):
* gst/mxf/mxfaes-bwf.h:
* gst/mxf/mxfalaw.c: (mxf_is_alaw_essence_track),
(mxf_alaw_create_caps), (mxf_alaw_init):
* gst/mxf/mxfalaw.h:
* gst/mxf/mxfd10.c: (mxf_is_d10_essence_track),
(mxf_d10_create_caps), (mxf_d10_init):
* gst/mxf/mxfd10.h:
* gst/mxf/mxfdemux.c: (gst_mxf_demux_reset_metadata),
(gst_mxf_demux_handle_header_metadata_resolve_references),
(gst_mxf_demux_find_package), (gst_mxf_demux_choose_package),
(gst_mxf_demux_handle_header_metadata_update_streams),
(gst_mxf_demux_handle_metadata),
(gst_mxf_demux_handle_generic_container_essence_element),
(gst_mxf_demux_handle_klv_packet), (gst_mxf_demux_src_query):
* gst/mxf/mxfdemux.h:
* gst/mxf/mxfdv-dif.c: (mxf_is_dv_dif_essence_track),
(mxf_dv_dif_create_caps), (mxf_dv_dif_init):
* gst/mxf/mxfdv-dif.h:
* gst/mxf/mxfjpeg2000.c: (mxf_is_jpeg2000_essence_track),
(mxf_jpeg2000_create_caps), (mxf_jpeg2000_init):
* gst/mxf/mxfjpeg2000.h:
* gst/mxf/mxfmetadata.c: (mxf_metadata_base_finalize),
(mxf_metadata_base_handle_tag), (mxf_metadata_base_resolve),
(mxf_metadata_base_init), (mxf_metadata_base_class_init),
(mxf_metadata_parse), (mxf_metadata_resolve),
(mxf_metadata_handle_tag), (mxf_metadata_class_init),
(mxf_metadata_init), (mxf_metadata_init_types),
(mxf_metadata_register), (mxf_metadata_new),
(mxf_metadata_preface_finalize), (mxf_metadata_preface_handle_tag),
(mxf_metadata_preface_resolve), (mxf_metadata_preface_init),
(mxf_metadata_preface_class_init),
(mxf_metadata_identification_finalize),
(mxf_metadata_identification_handle_tag),
(mxf_metadata_identification_init),
(mxf_metadata_identification_class_init),
(mxf_metadata_content_storage_finalize),
(mxf_metadata_content_storage_handle_tag),
(mxf_metadata_content_storage_resolve),
(mxf_metadata_content_storage_init),
(mxf_metadata_content_storage_class_init),
(mxf_metadata_essence_container_data_handle_tag),
(mxf_metadata_essence_container_data_resolve),
(mxf_metadata_essence_container_data_init),
(mxf_metadata_essence_container_data_class_init),
(mxf_metadata_generic_package_finalize),
(mxf_metadata_generic_package_handle_tag),
(mxf_metadata_generic_package_resolve),
(mxf_metadata_generic_package_init),
(mxf_metadata_generic_package_class_init),
(mxf_metadata_material_package_resolve),
(mxf_metadata_material_package_init),
(mxf_metadata_material_package_class_init),
(mxf_metadata_source_package_finalize),
(mxf_metadata_source_package_handle_tag),
(mxf_metadata_source_package_resolve),
(mxf_metadata_source_package_init),
(mxf_metadata_source_package_class_init),
(mxf_metadata_track_finalize), (mxf_metadata_track_handle_tag),
(mxf_metadata_track_resolve), (mxf_metadata_track_init),
(mxf_metadata_track_class_init),
(mxf_metadata_track_identifier_parse),
(mxf_metadata_timeline_track_handle_tag),
(mxf_metadata_timeline_track_init),
(mxf_metadata_timeline_track_class_init),
(mxf_metadata_event_track_handle_tag),
(mxf_metadata_event_track_init),
(mxf_metadata_event_track_class_init),
(mxf_metadata_static_track_init),
(mxf_metadata_static_track_class_init),
(mxf_metadata_sequence_finalize),
(mxf_metadata_sequence_handle_tag),
(mxf_metadata_sequence_resolve), (mxf_metadata_sequence_init),
(mxf_metadata_sequence_class_init),
(mxf_metadata_structural_component_handle_tag),
(mxf_metadata_structural_component_init),
(mxf_metadata_structural_component_class_init),
(mxf_metadata_timecode_component_handle_tag),
(mxf_metadata_timecode_component_init),
(mxf_metadata_timecode_component_class_init),
(mxf_metadata_source_clip_handle_tag),
(mxf_metadata_source_clip_resolve),
(mxf_metadata_source_clip_init),
(mxf_metadata_source_clip_class_init),
(mxf_metadata_dm_source_clip_finalize),
(mxf_metadata_dm_source_clip_handle_tag),
(mxf_metadata_dm_source_clip_init),
(mxf_metadata_dm_source_clip_class_init),
(mxf_metadata_dm_segment_finalize),
(mxf_metadata_dm_segment_handle_tag),
(mxf_metadata_dm_segment_resolve), (mxf_metadata_dm_segment_init),
(mxf_metadata_dm_segment_class_init),
(mxf_metadata_generic_descriptor_finalize),
(mxf_metadata_generic_descriptor_handle_tag),
(mxf_metadata_generic_descriptor_resolve),
(mxf_metadata_generic_descriptor_init),
(mxf_metadata_generic_descriptor_class_init),
(mxf_metadata_file_descriptor_handle_tag),
(mxf_metadata_file_descriptor_init),
(mxf_metadata_file_descriptor_class_init),
(mxf_metadata_generic_picture_essence_descriptor_handle_tag),
(mxf_metadata_generic_picture_essence_descriptor_init),
(mxf_metadata_generic_picture_essence_descriptor_class_init),
(mxf_metadata_generic_picture_essence_descriptor_set_caps),
(mxf_metadata_generic_sound_essence_descriptor_handle_tag),
(mxf_metadata_generic_sound_essence_descriptor_init),
(mxf_metadata_generic_sound_essence_descriptor_class_init),
(mxf_metadata_cdci_picture_essence_descriptor_handle_tag),
(mxf_metadata_cdci_picture_essence_descriptor_init),
(mxf_metadata_cdci_picture_essence_descriptor_class_init),
(mxf_metadata_rgba_picture_essence_descriptor_finalize),
(mxf_metadata_rgba_picture_essence_descriptor_handle_tag),
(mxf_metadata_rgba_picture_essence_descriptor_init),
(mxf_metadata_rgba_picture_essence_descriptor_class_init),
(mxf_metadata_generic_data_essence_descriptor_handle_tag),
(mxf_metadata_generic_data_essence_descriptor_init),
(mxf_metadata_generic_data_essence_descriptor_class_init),
(mxf_metadata_multiple_descriptor_finalize),
(mxf_metadata_multiple_descriptor_handle_tag),
(mxf_metadata_multiple_descriptor_resolve),
(mxf_metadata_multiple_descriptor_init),
(mxf_metadata_multiple_descriptor_class_init),
(mxf_metadata_locator_init), (mxf_metadata_locator_class_init),
(mxf_metadata_text_locator_finalize),
(mxf_metadata_text_locator_handle_tag),
(mxf_metadata_text_locator_init),
(mxf_metadata_text_locator_class_init),
(mxf_metadata_network_locator_finalize),
(mxf_metadata_network_locator_handle_tag),
(mxf_metadata_network_locator_init),
(mxf_metadata_network_locator_class_init):
* gst/mxf/mxfmetadata.h:
* gst/mxf/mxfmpeg.c:
(mxf_metadata_mpeg_video_descriptor_handle_tag),
(mxf_metadata_mpeg_video_descriptor_init),
(mxf_metadata_mpeg_video_descriptor_class_init),
(mxf_is_mpeg_essence_track), (mxf_mpeg_es_create_caps),
(mxf_mpeg_create_caps), (mxf_mpeg_init):
* gst/mxf/mxfmpeg.h:
* gst/mxf/mxfparse.c: (mxf_index_table_segment_parse),
(mxf_local_tag_add_to_hash_table):
* gst/mxf/mxfparse.h:
* gst/mxf/mxftypes.h:
* gst/mxf/mxfup.c: (mxf_is_up_essence_track), (mxf_up_create_caps),
(mxf_up_init):
* gst/mxf/mxfup.h:
Convert the structural metadata to GstMiniObjects to make a lot of
code easier and to make everything better extensible.
Add a "registry" for metadata handlers to improve extensibility even
more and to remove metadata type specifics from mxfdemux.
Clean up a lot of parts and add some more NULL checks.

24 files changed:
ChangeLog
gst/mxf/Makefile.am
gst/mxf/mxf.c
gst/mxf/mxfaes-bwf.c
gst/mxf/mxfaes-bwf.h
gst/mxf/mxfalaw.c
gst/mxf/mxfalaw.h
gst/mxf/mxfd10.c
gst/mxf/mxfd10.h
gst/mxf/mxfdemux.c
gst/mxf/mxfdemux.h
gst/mxf/mxfdv-dif.c
gst/mxf/mxfdv-dif.h
gst/mxf/mxfjpeg2000.c
gst/mxf/mxfjpeg2000.h
gst/mxf/mxfmetadata.c [new file with mode: 0644]
gst/mxf/mxfmetadata.h [new file with mode: 0644]
gst/mxf/mxfmpeg.c
gst/mxf/mxfmpeg.h
gst/mxf/mxfparse.c
gst/mxf/mxfparse.h
gst/mxf/mxftypes.h
gst/mxf/mxfup.c
gst/mxf/mxfup.h

index d93eaa2..f547b21 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,170 @@
+2008-12-15  Sebastian Dröge  <sebastian.droege@collabora.co.uk>
+
+       * gst/mxf/Makefile.am:
+       * gst/mxf/mxf.c: (plugin_init):
+       * gst/mxf/mxfaes-bwf.c:
+       (mxf_metadata_wave_audio_essence_descriptor_handle_tag),
+       (mxf_metadata_wave_audio_essence_descriptor_init),
+       (mxf_metadata_wave_audio_essence_descriptor_class_init),
+       (mxf_metadata_aes3_audio_essence_descriptor_finalize),
+       (mxf_metadata_aes3_audio_essence_descriptor_handle_tag),
+       (mxf_metadata_aes3_audio_essence_descriptor_init),
+       (mxf_metadata_aes3_audio_essence_descriptor_class_init),
+       (mxf_is_aes_bwf_essence_track), (mxf_bwf_create_caps),
+       (mxf_aes3_create_caps), (mxf_aes_bwf_create_caps),
+       (mxf_aes_bwf_init):
+       * gst/mxf/mxfaes-bwf.h:
+       * gst/mxf/mxfalaw.c: (mxf_is_alaw_essence_track),
+       (mxf_alaw_create_caps), (mxf_alaw_init):
+       * gst/mxf/mxfalaw.h:
+       * gst/mxf/mxfd10.c: (mxf_is_d10_essence_track),
+       (mxf_d10_create_caps), (mxf_d10_init):
+       * gst/mxf/mxfd10.h:
+       * gst/mxf/mxfdemux.c: (gst_mxf_demux_reset_metadata),
+       (gst_mxf_demux_handle_header_metadata_resolve_references),
+       (gst_mxf_demux_find_package), (gst_mxf_demux_choose_package),
+       (gst_mxf_demux_handle_header_metadata_update_streams),
+       (gst_mxf_demux_handle_metadata),
+       (gst_mxf_demux_handle_generic_container_essence_element),
+       (gst_mxf_demux_handle_klv_packet), (gst_mxf_demux_src_query):
+       * gst/mxf/mxfdemux.h:
+       * gst/mxf/mxfdv-dif.c: (mxf_is_dv_dif_essence_track),
+       (mxf_dv_dif_create_caps), (mxf_dv_dif_init):
+       * gst/mxf/mxfdv-dif.h:
+       * gst/mxf/mxfjpeg2000.c: (mxf_is_jpeg2000_essence_track),
+       (mxf_jpeg2000_create_caps), (mxf_jpeg2000_init):
+       * gst/mxf/mxfjpeg2000.h:
+       * gst/mxf/mxfmetadata.c: (mxf_metadata_base_finalize),
+       (mxf_metadata_base_handle_tag), (mxf_metadata_base_resolve),
+       (mxf_metadata_base_init), (mxf_metadata_base_class_init),
+       (mxf_metadata_parse), (mxf_metadata_resolve),
+       (mxf_metadata_handle_tag), (mxf_metadata_class_init),
+       (mxf_metadata_init), (mxf_metadata_init_types),
+       (mxf_metadata_register), (mxf_metadata_new),
+       (mxf_metadata_preface_finalize), (mxf_metadata_preface_handle_tag),
+       (mxf_metadata_preface_resolve), (mxf_metadata_preface_init),
+       (mxf_metadata_preface_class_init),
+       (mxf_metadata_identification_finalize),
+       (mxf_metadata_identification_handle_tag),
+       (mxf_metadata_identification_init),
+       (mxf_metadata_identification_class_init),
+       (mxf_metadata_content_storage_finalize),
+       (mxf_metadata_content_storage_handle_tag),
+       (mxf_metadata_content_storage_resolve),
+       (mxf_metadata_content_storage_init),
+       (mxf_metadata_content_storage_class_init),
+       (mxf_metadata_essence_container_data_handle_tag),
+       (mxf_metadata_essence_container_data_resolve),
+       (mxf_metadata_essence_container_data_init),
+       (mxf_metadata_essence_container_data_class_init),
+       (mxf_metadata_generic_package_finalize),
+       (mxf_metadata_generic_package_handle_tag),
+       (mxf_metadata_generic_package_resolve),
+       (mxf_metadata_generic_package_init),
+       (mxf_metadata_generic_package_class_init),
+       (mxf_metadata_material_package_resolve),
+       (mxf_metadata_material_package_init),
+       (mxf_metadata_material_package_class_init),
+       (mxf_metadata_source_package_finalize),
+       (mxf_metadata_source_package_handle_tag),
+       (mxf_metadata_source_package_resolve),
+       (mxf_metadata_source_package_init),
+       (mxf_metadata_source_package_class_init),
+       (mxf_metadata_track_finalize), (mxf_metadata_track_handle_tag),
+       (mxf_metadata_track_resolve), (mxf_metadata_track_init),
+       (mxf_metadata_track_class_init),
+       (mxf_metadata_track_identifier_parse),
+       (mxf_metadata_timeline_track_handle_tag),
+       (mxf_metadata_timeline_track_init),
+       (mxf_metadata_timeline_track_class_init),
+       (mxf_metadata_event_track_handle_tag),
+       (mxf_metadata_event_track_init),
+       (mxf_metadata_event_track_class_init),
+       (mxf_metadata_static_track_init),
+       (mxf_metadata_static_track_class_init),
+       (mxf_metadata_sequence_finalize),
+       (mxf_metadata_sequence_handle_tag),
+       (mxf_metadata_sequence_resolve), (mxf_metadata_sequence_init),
+       (mxf_metadata_sequence_class_init),
+       (mxf_metadata_structural_component_handle_tag),
+       (mxf_metadata_structural_component_init),
+       (mxf_metadata_structural_component_class_init),
+       (mxf_metadata_timecode_component_handle_tag),
+       (mxf_metadata_timecode_component_init),
+       (mxf_metadata_timecode_component_class_init),
+       (mxf_metadata_source_clip_handle_tag),
+       (mxf_metadata_source_clip_resolve),
+       (mxf_metadata_source_clip_init),
+       (mxf_metadata_source_clip_class_init),
+       (mxf_metadata_dm_source_clip_finalize),
+       (mxf_metadata_dm_source_clip_handle_tag),
+       (mxf_metadata_dm_source_clip_init),
+       (mxf_metadata_dm_source_clip_class_init),
+       (mxf_metadata_dm_segment_finalize),
+       (mxf_metadata_dm_segment_handle_tag),
+       (mxf_metadata_dm_segment_resolve), (mxf_metadata_dm_segment_init),
+       (mxf_metadata_dm_segment_class_init),
+       (mxf_metadata_generic_descriptor_finalize),
+       (mxf_metadata_generic_descriptor_handle_tag),
+       (mxf_metadata_generic_descriptor_resolve),
+       (mxf_metadata_generic_descriptor_init),
+       (mxf_metadata_generic_descriptor_class_init),
+       (mxf_metadata_file_descriptor_handle_tag),
+       (mxf_metadata_file_descriptor_init),
+       (mxf_metadata_file_descriptor_class_init),
+       (mxf_metadata_generic_picture_essence_descriptor_handle_tag),
+       (mxf_metadata_generic_picture_essence_descriptor_init),
+       (mxf_metadata_generic_picture_essence_descriptor_class_init),
+       (mxf_metadata_generic_picture_essence_descriptor_set_caps),
+       (mxf_metadata_generic_sound_essence_descriptor_handle_tag),
+       (mxf_metadata_generic_sound_essence_descriptor_init),
+       (mxf_metadata_generic_sound_essence_descriptor_class_init),
+       (mxf_metadata_cdci_picture_essence_descriptor_handle_tag),
+       (mxf_metadata_cdci_picture_essence_descriptor_init),
+       (mxf_metadata_cdci_picture_essence_descriptor_class_init),
+       (mxf_metadata_rgba_picture_essence_descriptor_finalize),
+       (mxf_metadata_rgba_picture_essence_descriptor_handle_tag),
+       (mxf_metadata_rgba_picture_essence_descriptor_init),
+       (mxf_metadata_rgba_picture_essence_descriptor_class_init),
+       (mxf_metadata_generic_data_essence_descriptor_handle_tag),
+       (mxf_metadata_generic_data_essence_descriptor_init),
+       (mxf_metadata_generic_data_essence_descriptor_class_init),
+       (mxf_metadata_multiple_descriptor_finalize),
+       (mxf_metadata_multiple_descriptor_handle_tag),
+       (mxf_metadata_multiple_descriptor_resolve),
+       (mxf_metadata_multiple_descriptor_init),
+       (mxf_metadata_multiple_descriptor_class_init),
+       (mxf_metadata_locator_init), (mxf_metadata_locator_class_init),
+       (mxf_metadata_text_locator_finalize),
+       (mxf_metadata_text_locator_handle_tag),
+       (mxf_metadata_text_locator_init),
+       (mxf_metadata_text_locator_class_init),
+       (mxf_metadata_network_locator_finalize),
+       (mxf_metadata_network_locator_handle_tag),
+       (mxf_metadata_network_locator_init),
+       (mxf_metadata_network_locator_class_init):
+       * gst/mxf/mxfmetadata.h:
+       * gst/mxf/mxfmpeg.c:
+       (mxf_metadata_mpeg_video_descriptor_handle_tag),
+       (mxf_metadata_mpeg_video_descriptor_init),
+       (mxf_metadata_mpeg_video_descriptor_class_init),
+       (mxf_is_mpeg_essence_track), (mxf_mpeg_es_create_caps),
+       (mxf_mpeg_create_caps), (mxf_mpeg_init):
+       * gst/mxf/mxfmpeg.h:
+       * gst/mxf/mxfparse.c: (mxf_index_table_segment_parse),
+       (mxf_local_tag_add_to_hash_table):
+       * gst/mxf/mxfparse.h:
+       * gst/mxf/mxftypes.h:
+       * gst/mxf/mxfup.c: (mxf_is_up_essence_track), (mxf_up_create_caps),
+       (mxf_up_init):
+       * gst/mxf/mxfup.h:
+       Convert the structural metadata to GstMiniObjects to make a lot of
+       code easier and to make everything better extensible.
+       Add a "registry" for metadata handlers to improve extensibility even
+       more and to remove metadata type specifics from mxfdemux.
+
+       Clean up a lot of parts and add some more NULL checks.
+
 2008-12-15  Stefan Kost  <ensonic@users.sf.net>
 
        * ext/faac/gstfaac.c:
index 16e2e85..96e5720 100644 (file)
@@ -10,7 +10,8 @@ libgstmxf_la_SOURCES = \
        mxfalaw.c \
        mxfjpeg2000.c \
        mxfd10.c \
-       mxfup.c
+       mxfup.c \
+       mxfmetadata.c
 
 libgstmxf_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS)
 libgstmxf_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \
@@ -27,5 +28,6 @@ noinst_HEADERS = \
        mxfjpeg2000.h \
        mxfd10.h \
        mxfup.h \
-       mxftypes.h
+       mxftypes.h \
+       mxfmetadata.h
 
index 655ac31..8506f43 100644 (file)
 #include <gst/gst.h>
 
 #include "mxfdemux.h"
+#include "mxfmetadata.h"
+#include "mxfaes-bwf.h"
+#include "mxfmpeg.h"
+#include "mxfdv-dif.h"
+#include "mxfalaw.h"
+#include "mxfjpeg2000.h"
+#include "mxfd10.h"
+#include "mxfup.h"
 
 GST_DEBUG_CATEGORY (mxf_debug);
 #define GST_CAT_DEFAULT mxf_debug
@@ -30,6 +38,15 @@ GST_DEBUG_CATEGORY (mxf_debug);
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
+  mxf_metadata_init_types ();
+  mxf_aes_bwf_init ();
+  mxf_mpeg_init ();
+  mxf_dv_dif_init ();
+  mxf_alaw_init ();
+  mxf_jpeg2000_init ();
+  mxf_d10_init ();
+  mxf_up_init ();
+
   if (!gst_element_register (plugin, "mxfdemux", GST_RANK_PRIMARY,
           GST_TYPE_MXF_DEMUX))
     return FALSE;
index 98e0f72..6b297ef 100644 (file)
@@ -41,180 +41,199 @@ GST_DEBUG_CATEGORY_EXTERN (mxf_debug);
 #define GST_CAT_DEFAULT mxf_debug
 
 /* SMPTE 382M Annex 1 */
-gboolean
-    mxf_metadata_wave_audio_essence_descriptor_handle_tag
-    (MXFMetadataGenericDescriptor * d, const MXFPrimerPack * primer,
-    guint16 tag, const guint8 * tag_data, guint16 tag_size)
+G_DEFINE_TYPE (MXFMetadataWaveAudioEssenceDescriptor,
+    mxf_metadata_wave_audio_essence_descriptor,
+    MXF_TYPE_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR);
+
+static gboolean
+mxf_metadata_wave_audio_essence_descriptor_handle_tag (MXFMetadataBase *
+    metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
 {
-  MXFMetadataWaveAudioEssenceDescriptor *descriptor =
-      (MXFMetadataWaveAudioEssenceDescriptor *) d;
-  gboolean ret = FALSE;
+  MXFMetadataWaveAudioEssenceDescriptor *self =
+      MXF_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR (metadata);
+  gboolean ret = TRUE;
   gchar str[48];
 
   switch (tag) {
     case 0x3d0a:
       if (tag_size != 2)
         goto error;
-      descriptor->block_align = GST_READ_UINT16_BE (tag_data);
-      GST_DEBUG ("  block align = %u", descriptor->block_align);
-      ret = TRUE;
+      self->block_align = GST_READ_UINT16_BE (tag_data);
+      GST_DEBUG ("  block align = %u", self->block_align);
       break;
     case 0x3d0b:
       if (tag_size != 1)
         goto error;
-      descriptor->sequence_offset = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  sequence offset = %u", descriptor->sequence_offset);
-      ret = TRUE;
+      self->sequence_offset = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  sequence offset = %u", self->sequence_offset);
       break;
     case 0x3d09:
       if (tag_size != 4)
         goto error;
-      descriptor->avg_bps = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  average bps = %u", descriptor->avg_bps);
-      ret = TRUE;
+      self->avg_bps = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  average bps = %u", self->avg_bps);
       break;
     case 0x3d32:
       if (tag_size != 16)
         goto error;
-      memcpy (&descriptor->channel_assignment, tag_data, 16);
+      memcpy (&self->channel_assignment, tag_data, 16);
       GST_DEBUG ("  channel assignment = %s",
-          mxf_ul_to_string (&descriptor->channel_assignment, str));
-      ret = TRUE;
+          mxf_ul_to_string (&self->channel_assignment, str));
       break;
     case 0x3d29:
       if (tag_size != 4)
         goto error;
-      descriptor->peak_envelope_version = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  peak envelope version = %u",
-          descriptor->peak_envelope_version);
-      ret = TRUE;
+      self->peak_envelope_version = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  peak envelope version = %u", self->peak_envelope_version);
       break;
     case 0x3d2a:
       if (tag_size != 4)
         goto error;
-      descriptor->peak_envelope_format = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  peak envelope format = %u",
-          descriptor->peak_envelope_format);
-      ret = TRUE;
+      self->peak_envelope_format = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  peak envelope format = %u", self->peak_envelope_format);
       break;
     case 0x3d2b:
       if (tag_size != 4)
         goto error;
-      descriptor->points_per_peak_value = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  points per peak value = %u",
-          descriptor->points_per_peak_value);
-      ret = TRUE;
+      self->points_per_peak_value = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  points per peak value = %u", self->points_per_peak_value);
       break;
     case 0x3d2c:
       if (tag_size != 4)
         goto error;
-      descriptor->peak_envelope_block_size = GST_READ_UINT32_BE (tag_data);
+      self->peak_envelope_block_size = GST_READ_UINT32_BE (tag_data);
       GST_DEBUG ("  peak envelope block size = %u",
-          descriptor->peak_envelope_block_size);
-      ret = TRUE;
+          self->peak_envelope_block_size);
       break;
     case 0x3d2d:
       if (tag_size != 4)
         goto error;
-      descriptor->peak_channels = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  peak channels = %u", descriptor->peak_channels);
-      ret = TRUE;
+      self->peak_channels = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  peak channels = %u", self->peak_channels);
       break;
     case 0x3d2e:
       if (tag_size != 4)
         goto error;
-      descriptor->peak_frames = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  peak frames = %u", descriptor->peak_frames);
-      ret = TRUE;
+      self->peak_frames = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  peak frames = %u", self->peak_frames);
       break;
     case 0x3d2f:
       if (tag_size != 8)
         goto error;
-      descriptor->peak_of_peaks_position = GST_READ_UINT64_BE (tag_data);
+      self->peak_of_peaks_position = GST_READ_UINT64_BE (tag_data);
       GST_DEBUG ("  peak of peaks position = %" G_GINT64_FORMAT,
-          descriptor->peak_of_peaks_position);
-      ret = TRUE;
+          self->peak_of_peaks_position);
       break;
     case 0x3d30:
-      if (!mxf_timestamp_parse (&descriptor->peak_envelope_timestamp,
+      if (!mxf_timestamp_parse (&self->peak_envelope_timestamp,
               tag_data, tag_size))
         goto error;
       GST_DEBUG ("  peak envelope timestamp = %d/%u/%u %u:%u:%u.%u",
-          descriptor->peak_envelope_timestamp.year,
-          descriptor->peak_envelope_timestamp.month,
-          descriptor->peak_envelope_timestamp.day,
-          descriptor->peak_envelope_timestamp.hour,
-          descriptor->peak_envelope_timestamp.minute,
-          descriptor->peak_envelope_timestamp.second,
-          (descriptor->peak_envelope_timestamp.quarter_msecond * 1000) / 256);
-      ret = TRUE;
+          self->peak_envelope_timestamp.year,
+          self->peak_envelope_timestamp.month,
+          self->peak_envelope_timestamp.day,
+          self->peak_envelope_timestamp.hour,
+          self->peak_envelope_timestamp.minute,
+          self->peak_envelope_timestamp.second,
+          (self->peak_envelope_timestamp.quarter_msecond * 1000) / 256);
       break;
     case 0x3d31:
-      descriptor->peak_envelope_data = g_memdup (tag_data, tag_size);
-      descriptor->peak_envelope_data_length = tag_size;
+      self->peak_envelope_data = g_memdup (tag_data, tag_size);
+      self->peak_envelope_data_length = tag_size;
       GST_DEBUG ("  peak evelope data size = %u",
-          descriptor->peak_envelope_data_length);
-      ret = TRUE;
+          self->peak_envelope_data_length);
       break;
     default:
       ret =
-          mxf_metadata_generic_sound_essence_descriptor_handle_tag (d, primer,
-          tag, tag_data, tag_size);
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_wave_audio_essence_descriptor_parent_class)->
+          handle_tag (metadata, primer, tag, tag_data, tag_size);
       break;
   }
 
   return ret;
 
 error:
-  GST_ERROR ("Invalid wave audio essence descriptor tag 0x%04x of size %u", tag,
+
+  GST_ERROR
+      ("Invalid wave audio essence descriptor local tag 0x%04x of size %u", tag,
       tag_size);
 
   return TRUE;
 }
 
-void mxf_metadata_wave_audio_essence_descriptor_reset
-    (MXFMetadataWaveAudioEssenceDescriptor * descriptor)
+static void
+    mxf_metadata_wave_audio_essence_descriptor_init
+    (MXFMetadataWaveAudioEssenceDescriptor * self)
 {
-  g_return_if_fail (descriptor != NULL);
 
-  mxf_metadata_generic_sound_essence_descriptor_reset (
-      (MXFMetadataGenericSoundEssenceDescriptor *) descriptor);
+}
+
+static void
+    mxf_metadata_wave_audio_essence_descriptor_class_init
+    (MXFMetadataWaveAudioEssenceDescriptorClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
 
-  MXF_METADATA_DESCRIPTOR_CLEAR (descriptor,
-      MXFMetadataWaveAudioEssenceDescriptor,
-      MXFMetadataGenericSoundEssenceDescriptor);
+  metadata_base_class->handle_tag =
+      mxf_metadata_wave_audio_essence_descriptor_handle_tag;
 }
 
 /* SMPTE 382M Annex 2 */
-gboolean
-    mxf_metadata_aes3_audio_essence_descriptor_handle_tag
-    (MXFMetadataGenericDescriptor * d, const MXFPrimerPack * primer,
-    guint16 tag, const guint8 * tag_data, guint16 tag_size)
+G_DEFINE_TYPE (MXFMetadataAES3AudioEssenceDescriptor,
+    mxf_metadata_aes3_audio_essence_descriptor,
+    MXF_TYPE_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR);
+
+static void
+mxf_metadata_aes3_audio_essence_descriptor_finalize (GstMiniObject * object)
+{
+  MXFMetadataAES3AudioEssenceDescriptor *self =
+      MXF_METADATA_AES3_AUDIO_ESSENCE_DESCRIPTOR (object);
+
+  g_free (self->channel_status_mode);
+  self->channel_status_mode = NULL;
+  g_free (self->fixed_channel_status_data);
+  self->fixed_channel_status_data = NULL;
+  g_free (self->user_data_mode);
+  self->user_data_mode = NULL;
+  g_free (self->fixed_user_data);
+  self->fixed_user_data = NULL;
+
+  GST_MINI_OBJECT_CLASS
+      (mxf_metadata_aes3_audio_essence_descriptor_parent_class)->
+      finalize (object);
+}
+
+static gboolean
+mxf_metadata_aes3_audio_essence_descriptor_handle_tag (MXFMetadataBase *
+    metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
 {
-  MXFMetadataAES3AudioEssenceDescriptor *descriptor =
-      (MXFMetadataAES3AudioEssenceDescriptor *) d;
-  gboolean ret = FALSE;
+  MXFMetadataAES3AudioEssenceDescriptor *self =
+      MXF_METADATA_AES3_AUDIO_ESSENCE_DESCRIPTOR (metadata);
+  gboolean ret = TRUE;
 
   switch (tag) {
     case 0x3d0d:
       if (tag_size != 1)
         goto error;
-      descriptor->emphasis = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  emphasis = %u", descriptor->emphasis);
+      self->emphasis = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  emphasis = %u", self->emphasis);
       ret = TRUE;
       break;
     case 0x3d0f:
       if (tag_size != 2)
         goto error;
-      descriptor->block_start_offset = GST_READ_UINT16_BE (tag_data);
-      GST_DEBUG ("  block start offset = %u", descriptor->block_start_offset);
+      self->block_start_offset = GST_READ_UINT16_BE (tag_data);
+      GST_DEBUG ("  block start offset = %u", self->block_start_offset);
       ret = TRUE;
       break;
     case 0x3d08:
       if (tag_size != 1)
         goto error;
-      descriptor->auxiliary_bits_mode = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  auxiliary bits mode = %u", descriptor->auxiliary_bits_mode);
+      self->auxiliary_bits_mode = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  auxiliary bits mode = %u", self->auxiliary_bits_mode);
       ret = TRUE;
       break;
     case 0x3d10:{
@@ -225,7 +244,7 @@ gboolean
         goto error;
       len = GST_READ_UINT32_BE (tag_data);
       GST_DEBUG ("  number of channel status mode = %u", len);
-      descriptor->n_channel_status_mode = len;
+      self->n_channel_status_mode = len;
       if (len == 0)
         return TRUE;
 
@@ -238,12 +257,12 @@ gboolean
       if (tag_size != len)
         goto error;
 
-      descriptor->channel_status_mode = g_new0 (guint8, len);
+      self->channel_status_mode = g_new0 (guint8, len);
 
       for (i = 0; i < len; i++) {
-        descriptor->channel_status_mode[i] = GST_READ_UINT8 (tag_data);
+        self->channel_status_mode[i] = GST_READ_UINT8 (tag_data);
         GST_DEBUG ("    channel status mode %u = %u", i,
-            descriptor->channel_status_mode[i]);
+            self->channel_status_mode[i]);
         tag_data++;
         tag_size--;
       }
@@ -259,7 +278,7 @@ gboolean
         goto error;
       len = GST_READ_UINT32_BE (tag_data);
       GST_DEBUG ("  number of fixed channel status data = %u", len);
-      descriptor->n_fixed_channel_status_data = len;
+      self->n_fixed_channel_status_data = len;
       if (len == 0)
         return TRUE;
 
@@ -272,41 +291,41 @@ gboolean
       if (tag_size != len * 24)
         goto error;
 
-      descriptor->fixed_channel_status_data =
+      self->fixed_channel_status_data =
           g_malloc0 (len * sizeof (guint8 *) + len * 24);
 
       for (i = 0; i < len; i++) {
-        descriptor->fixed_channel_status_data[i] =
-            ((guint8 *) descriptor->fixed_channel_status_data) +
+        self->fixed_channel_status_data[i] =
+            ((guint8 *) self->fixed_channel_status_data) +
             len * sizeof (guint8 *) + i * 24;
 
-        memcpy (descriptor->fixed_channel_status_data[i], tag_data, 24);
+        memcpy (self->fixed_channel_status_data[i], tag_data, 24);
         GST_DEBUG
             ("    fixed channel status data %u = 0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x",
-            i, descriptor->fixed_channel_status_data[i][0],
-            descriptor->fixed_channel_status_data[i][1],
-            descriptor->fixed_channel_status_data[i][2],
-            descriptor->fixed_channel_status_data[i][3],
-            descriptor->fixed_channel_status_data[i][4],
-            descriptor->fixed_channel_status_data[i][5],
-            descriptor->fixed_channel_status_data[i][6],
-            descriptor->fixed_channel_status_data[i][7],
-            descriptor->fixed_channel_status_data[i][8],
-            descriptor->fixed_channel_status_data[i][9],
-            descriptor->fixed_channel_status_data[i][10],
-            descriptor->fixed_channel_status_data[i][11],
-            descriptor->fixed_channel_status_data[i][12],
-            descriptor->fixed_channel_status_data[i][13],
-            descriptor->fixed_channel_status_data[i][14],
-            descriptor->fixed_channel_status_data[i][15],
-            descriptor->fixed_channel_status_data[i][16],
-            descriptor->fixed_channel_status_data[i][17],
-            descriptor->fixed_channel_status_data[i][18],
-            descriptor->fixed_channel_status_data[i][19],
-            descriptor->fixed_channel_status_data[i][20],
-            descriptor->fixed_channel_status_data[i][21],
-            descriptor->fixed_channel_status_data[i][22],
-            descriptor->fixed_channel_status_data[i][23]
+            i, self->fixed_channel_status_data[i][0],
+            self->fixed_channel_status_data[i][1],
+            self->fixed_channel_status_data[i][2],
+            self->fixed_channel_status_data[i][3],
+            self->fixed_channel_status_data[i][4],
+            self->fixed_channel_status_data[i][5],
+            self->fixed_channel_status_data[i][6],
+            self->fixed_channel_status_data[i][7],
+            self->fixed_channel_status_data[i][8],
+            self->fixed_channel_status_data[i][9],
+            self->fixed_channel_status_data[i][10],
+            self->fixed_channel_status_data[i][11],
+            self->fixed_channel_status_data[i][12],
+            self->fixed_channel_status_data[i][13],
+            self->fixed_channel_status_data[i][14],
+            self->fixed_channel_status_data[i][15],
+            self->fixed_channel_status_data[i][16],
+            self->fixed_channel_status_data[i][17],
+            self->fixed_channel_status_data[i][18],
+            self->fixed_channel_status_data[i][19],
+            self->fixed_channel_status_data[i][20],
+            self->fixed_channel_status_data[i][21],
+            self->fixed_channel_status_data[i][22],
+            self->fixed_channel_status_data[i][23]
             );
         tag_data += 24;
         tag_size -= 24;
@@ -323,7 +342,7 @@ gboolean
         goto error;
       len = GST_READ_UINT32_BE (tag_data);
       GST_DEBUG ("  number of user data mode = %u", len);
-      descriptor->n_user_data_mode = len;
+      self->n_user_data_mode = len;
       if (len == 0)
         return TRUE;
 
@@ -336,12 +355,11 @@ gboolean
       if (tag_size != len)
         goto error;
 
-      descriptor->user_data_mode = g_new0 (guint8, len);
+      self->user_data_mode = g_new0 (guint8, len);
 
       for (i = 0; i < len; i++) {
-        descriptor->user_data_mode[i] = GST_READ_UINT8 (tag_data);
-        GST_DEBUG ("    user data mode %u = %u", i,
-            descriptor->user_data_mode[i]);
+        self->user_data_mode[i] = GST_READ_UINT8 (tag_data);
+        GST_DEBUG ("    user data mode %u = %u", i, self->user_data_mode[i]);
         tag_data++;
         tag_size--;
       }
@@ -357,7 +375,7 @@ gboolean
         goto error;
       len = GST_READ_UINT32_BE (tag_data);
       GST_DEBUG ("  number of fixed user data = %u", len);
-      descriptor->n_fixed_user_data = len;
+      self->n_fixed_user_data = len;
       if (len == 0)
         return TRUE;
 
@@ -370,41 +388,39 @@ gboolean
       if (tag_size != len * 24)
         goto error;
 
-      descriptor->fixed_user_data =
-          g_malloc0 (len * sizeof (guint8 *) + len * 24);
+      self->fixed_user_data = g_malloc0 (len * sizeof (guint8 *) + len * 24);
 
       for (i = 0; i < len; i++) {
-        descriptor->fixed_user_data[i] =
-            ((guint8 *) descriptor->fixed_user_data) + len * sizeof (guint8 *) +
+        self->fixed_user_data[i] =
+            ((guint8 *) self->fixed_user_data) + len * sizeof (guint8 *) +
             i * 24;
 
-        memcpy (descriptor->fixed_user_data[i], tag_data, 24);
+        memcpy (self->fixed_user_data[i], tag_data, 24);
         GST_DEBUG
             ("    fixed user data %u = 0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x.0x%02x",
-            i, descriptor->fixed_user_data[i][0],
-            descriptor->fixed_user_data[i][1],
-            descriptor->fixed_user_data[i][2],
-            descriptor->fixed_user_data[i][3],
-            descriptor->fixed_user_data[i][4],
-            descriptor->fixed_user_data[i][5],
-            descriptor->fixed_user_data[i][6],
-            descriptor->fixed_user_data[i][7],
-            descriptor->fixed_user_data[i][8],
-            descriptor->fixed_user_data[i][9],
-            descriptor->fixed_user_data[i][10],
-            descriptor->fixed_user_data[i][11],
-            descriptor->fixed_user_data[i][12],
-            descriptor->fixed_user_data[i][13],
-            descriptor->fixed_user_data[i][14],
-            descriptor->fixed_user_data[i][15],
-            descriptor->fixed_user_data[i][16],
-            descriptor->fixed_user_data[i][17],
-            descriptor->fixed_user_data[i][18],
-            descriptor->fixed_user_data[i][19],
-            descriptor->fixed_user_data[i][20],
-            descriptor->fixed_user_data[i][21],
-            descriptor->fixed_user_data[i][22],
-            descriptor->fixed_user_data[i][23]
+            i, self->fixed_user_data[i][0],
+            self->fixed_user_data[i][1],
+            self->fixed_user_data[i][2],
+            self->fixed_user_data[i][3],
+            self->fixed_user_data[i][4],
+            self->fixed_user_data[i][5],
+            self->fixed_user_data[i][6],
+            self->fixed_user_data[i][7],
+            self->fixed_user_data[i][8],
+            self->fixed_user_data[i][9],
+            self->fixed_user_data[i][10],
+            self->fixed_user_data[i][11],
+            self->fixed_user_data[i][12],
+            self->fixed_user_data[i][13],
+            self->fixed_user_data[i][14],
+            self->fixed_user_data[i][15],
+            self->fixed_user_data[i][16],
+            self->fixed_user_data[i][17],
+            self->fixed_user_data[i][18],
+            self->fixed_user_data[i][19],
+            self->fixed_user_data[i][20],
+            self->fixed_user_data[i][21],
+            self->fixed_user_data[i][22], self->fixed_user_data[i][23]
             );
         tag_data += 24;
         tag_size -= 24;
@@ -417,39 +433,42 @@ gboolean
        * SMPTE 382M Annex 2 */
     default:
       ret =
-          mxf_metadata_wave_audio_essence_descriptor_handle_tag (d, primer,
-          tag, tag_data, tag_size);
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_aes3_audio_essence_descriptor_parent_class)->
+          handle_tag (metadata, primer, tag, tag_data, tag_size);
       break;
   }
 
   return ret;
 
 error:
-  GST_ERROR ("Invalid AES3 audio essence descriptor tag 0x%04x of size %u", tag,
+
+  GST_ERROR
+      ("Invalid AES3 audio essence descriptor local tag 0x%04x of size %u", tag,
       tag_size);
 
   return TRUE;
 }
 
-void mxf_metadata_aes3_audio_essence_descriptor_reset
-    (MXFMetadataAES3AudioEssenceDescriptor * descriptor)
+static void
+    mxf_metadata_aes3_audio_essence_descriptor_init
+    (MXFMetadataAES3AudioEssenceDescriptor * self)
 {
-  g_return_if_fail (descriptor != NULL);
-
-  mxf_metadata_wave_audio_essence_descriptor_reset (
-      (MXFMetadataWaveAudioEssenceDescriptor *) descriptor);
-
-  g_free (descriptor->channel_status_mode);
-  g_free (descriptor->fixed_channel_status_data);
-  g_free (descriptor->user_data_mode);
-  g_free (descriptor->fixed_user_data);
 
-  MXF_METADATA_DESCRIPTOR_CLEAR (descriptor,
-      MXFMetadataAES3AudioEssenceDescriptor,
-      MXFMetadataWaveAudioEssenceDescriptor);
 }
 
+static void
+    mxf_metadata_aes3_audio_essence_descriptor_class_init
+    (MXFMetadataAES3AudioEssenceDescriptorClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
 
+  miniobject_class->finalize =
+      mxf_metadata_aes3_audio_essence_descriptor_finalize;
+  metadata_base_class->handle_tag =
+      mxf_metadata_aes3_audio_essence_descriptor_handle_tag;
+}
 
 gboolean
 mxf_is_aes_bwf_essence_track (const MXFMetadataTrack * track)
@@ -465,7 +484,12 @@ mxf_is_aes_bwf_essence_track (const MXFMetadataTrack * track)
 
   for (i = 0; i < track->n_descriptor; i++) {
     MXFMetadataFileDescriptor *d = track->descriptor[i];
-    MXFUL *key = &d->essence_container;
+    MXFUL *key;
+
+    if (!d)
+      continue;
+
+    key = &d->essence_container;
     /* SMPTE 382M 9 */
     if (mxf_is_generic_container_essence_container_label (key) &&
         key->u[12] == 0x02 &&
@@ -548,8 +572,7 @@ mxf_bwf_create_caps (MXFMetadataGenericPackage * package,
   gchar str[48];
   gchar *codec_name = NULL;
 
-  if (((MXFMetadataGenericDescriptor *) descriptor)->type ==
-      MXF_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR)
+  if (MXF_IS_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR (descriptor))
     wa_descriptor = (MXFMetadataWaveAudioEssenceDescriptor *) descriptor;
 
   /* TODO: Handle width=!depth, needs shifting of samples */
@@ -666,10 +689,7 @@ mxf_aes3_create_caps (MXFMetadataGenericPackage * package,
   gchar *codec_name = NULL;
   guint block_align;
 
-  if (((MXFMetadataGenericDescriptor *) descriptor)->type ==
-      MXF_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR ||
-      ((MXFMetadataGenericDescriptor *) descriptor)->type ==
-      MXF_METADATA_AES3_AUDIO_ESSENCE_DESCRIPTOR)
+  if (MXF_IS_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR (descriptor))
     wa_descriptor = (MXFMetadataWaveAudioEssenceDescriptor *) descriptor;
 
   /* FIXME: set a channel layout */
@@ -731,22 +751,18 @@ mxf_aes_bwf_create_caps (MXFMetadataGenericPackage * package,
   }
 
   for (i = 0; i < track->n_descriptor; i++) {
-    if ((track->descriptor[i]->parent.type ==
-            MXF_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR
-            || track->descriptor[i]->parent.type ==
-            MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR)
+    if (!track->descriptor[i])
+      continue;
+
+    if (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (track->descriptor[i])
         && (track->descriptor[i]->essence_container.u[14] == 0x01
             || track->descriptor[i]->essence_container.u[14] == 0x02
             || track->descriptor[i]->essence_container.u[14] == 0x08)) {
       s = (MXFMetadataGenericSoundEssenceDescriptor *) track->descriptor[i];
       bwf = TRUE;
       break;
-    } else if ((track->descriptor[i]->parent.type ==
-            MXF_METADATA_AES3_AUDIO_ESSENCE_DESCRIPTOR
-            || track->descriptor[i]->parent.type ==
-            MXF_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR
-            || track->descriptor[i]->parent.type ==
-            MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR)
+    } else if (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (track->
+            descriptor[i])
         && (track->descriptor[i]->essence_container.u[14] == 0x03
             || track->descriptor[i]->essence_container.u[14] == 0x04
             || track->descriptor[i]->essence_container.u[14] == 0x09)) {
@@ -769,3 +785,12 @@ mxf_aes_bwf_create_caps (MXFMetadataGenericPackage * package,
 
   return NULL;
 }
+
+void
+mxf_aes_bwf_init (void)
+{
+  mxf_metadata_register (0x0148,
+      MXF_TYPE_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR);
+  mxf_metadata_register (0x0147,
+      MXF_TYPE_METADATA_AES3_AUDIO_ESSENCE_DESCRIPTOR);
+}
index e158a8b..7783a2d 100644 (file)
 #include <gst/gst.h>
 
 #include "mxfparse.h"
+#include "mxfmetadata.h"
 
 /* SMPTE 382M Annex 1 */
-#define MXF_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR 0x0148
-/* SMPTE 382M Annex 2 */
-#define MXF_METADATA_AES3_AUDIO_ESSENCE_DESCRIPTOR 0x0147
-
-/* SMPTE 382M Annex 1 */
-typedef struct {
+#define MXF_TYPE_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR \
+  (mxf_metadata_wave_audio_essence_descriptor_get_type())
+#define MXF_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR, MXFMetadataWaveAudioEssenceDescriptor))
+#define MXF_IS_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR))
+typedef struct _MXFMetadataWaveAudioEssenceDescriptor MXFMetadataWaveAudioEssenceDescriptor;
+typedef MXFMetadataBaseClass MXFMetadataWaveAudioEssenceDescriptorClass;
+GType mxf_metadata_wave_audio_essence_descriptor_get_type (void);
+
+struct _MXFMetadataWaveAudioEssenceDescriptor {
   MXFMetadataGenericSoundEssenceDescriptor parent;
 
   guint16 block_align;
@@ -55,10 +61,20 @@ typedef struct {
 
   guint8 *peak_envelope_data;
   guint16 peak_envelope_data_length;
-} MXFMetadataWaveAudioEssenceDescriptor;
+};
 
 /* SMPTE 382M Annex 2 */
-typedef struct {
+#define MXF_TYPE_METADATA_AES3_AUDIO_ESSENCE_DESCRIPTOR \
+  (mxf_metadata_aes3_audio_essence_descriptor_get_type())
+#define MXF_METADATA_AES3_AUDIO_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_AES3_AUDIO_ESSENCE_DESCRIPTOR, MXFMetadataAES3AudioEssenceDescriptor))
+#define MXF_IS_METADATA_AES3_AUDIO_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_AES3_AUDIO_ESSENCE_DESCRIPTOR))
+typedef struct _MXFMetadataAES3AudioEssenceDescriptor MXFMetadataAES3AudioEssenceDescriptor;
+typedef MXFMetadataBaseClass MXFMetadataAES3AudioEssenceDescriptorClass;
+GType mxf_metadata_aes3_audio_essence_descriptor_get_type (void);
+
+struct _MXFMetadataAES3AudioEssenceDescriptor {
   MXFMetadataWaveAudioEssenceDescriptor parent;
 
   guint8 emphasis;
@@ -79,19 +95,13 @@ typedef struct {
 
   guint32 linked_timecode_track_id;
   guint8 stream_number;
-} MXFMetadataAES3AudioEssenceDescriptor;
-
-gboolean mxf_metadata_wave_audio_essence_descriptor_handle_tag (MXFMetadataGenericDescriptor *descriptor,
-    const MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint16 tag_size);
-void mxf_metadata_wave_audio_essence_descriptor_reset (MXFMetadataWaveAudioEssenceDescriptor *descriptor);
-
-gboolean mxf_metadata_aes3_audio_essence_descriptor_handle_tag (MXFMetadataGenericDescriptor *descriptor,
-    const MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint16 tag_size);
-void mxf_metadata_aes3_audio_essence_descriptor_reset (MXFMetadataAES3AudioEssenceDescriptor *descriptor);
+};
 
 gboolean mxf_is_aes_bwf_essence_track (const MXFMetadataTrack *track);
 
 GstCaps *
 mxf_aes_bwf_create_caps (MXFMetadataGenericPackage *package, MXFMetadataTrack *track, GstTagList **tags, MXFEssenceElementHandler *handler, gpointer *mapping_data);
 
+void mxf_aes_bwf_init (void);
+
 #endif /* __MXF_AES_BWF_H__ */
index 847eb90..6b7e419 100644 (file)
@@ -45,7 +45,12 @@ mxf_is_alaw_essence_track (const MXFMetadataTrack * track)
 
   for (i = 0; i < track->n_descriptor; i++) {
     MXFMetadataFileDescriptor *d = track->descriptor[i];
-    MXFUL *key = &d->essence_container;
+    MXFUL *key;
+
+    if (!d)
+      continue;
+
+    key = &d->essence_container;
     /* SMPTE 388M 6.1 */
     if (mxf_is_generic_container_essence_container_label (key) &&
         key->u[12] == 0x02 && key->u[13] == 0x0a &&
@@ -93,8 +98,10 @@ mxf_alaw_create_caps (MXFMetadataGenericPackage * package,
   }
 
   for (i = 0; i < track->n_descriptor; i++) {
-    if (((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR) {
+    if (!track->descriptor[i])
+      continue;
+
+    if (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (track->descriptor[i])) {
       s = (MXFMetadataGenericSoundEssenceDescriptor *) track->descriptor[i];
       break;
     }
@@ -127,3 +134,8 @@ mxf_alaw_create_caps (MXFMetadataGenericPackage * package,
 
   return caps;
 }
+
+void
+mxf_alaw_init (void)
+{
+}
index 20883fd..2a1279c 100644 (file)
@@ -33,4 +33,6 @@ gboolean mxf_is_alaw_essence_track (const MXFMetadataTrack *track);
 GstCaps *
 mxf_alaw_create_caps (MXFMetadataGenericPackage *package, MXFMetadataTrack *track, GstTagList **tags, MXFEssenceElementHandler *handler, gpointer *mapping_data);
 
+void mxf_alaw_init (void);
+
 #endif /* __MXF_ALAW_H__ */
index bbeb858..f7d2914 100644 (file)
@@ -52,7 +52,12 @@ mxf_is_d10_essence_track (const MXFMetadataTrack * track)
 
   for (i = 0; i < track->n_descriptor; i++) {
     MXFMetadataFileDescriptor *d = track->descriptor[i];
-    MXFUL *key = &d->essence_container;
+    MXFUL *key;
+
+    if (!d)
+      continue;
+
+    key = &d->essence_container;
     /* SMPTE 386M 5.1 */
     if (mxf_is_generic_container_essence_container_label (key) &&
         key->u[12] == 0x02 && key->u[13] == 0x01 &&
@@ -167,20 +172,15 @@ mxf_d10_create_caps (MXFMetadataGenericPackage * package,
   }
 
   for (i = 0; i < track->n_descriptor; i++) {
-    if (((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR ||
-        ((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_MPEG_VIDEO_DESCRIPTOR ||
-        ((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR) {
+    if (!track->descriptor[i])
+      continue;
+
+    if (MXF_IS_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (track->
+            descriptor[i])) {
       p = (MXFMetadataGenericPictureEssenceDescriptor *) track->descriptor[i];
       break;
-    } else if (((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR ||
-        ((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR ||
-        ((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_AES3_AUDIO_ESSENCE_DESCRIPTOR) {
+    } else if (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (track->
+            descriptor[i])) {
       s = (MXFMetadataGenericSoundEssenceDescriptor *) track->descriptor[i];
       break;
     }
@@ -242,3 +242,8 @@ mxf_d10_create_caps (MXFMetadataGenericPackage * package,
 
   return caps;
 }
+
+void
+mxf_d10_init (void)
+{
+}
index 2fca77b..e3167d1 100644 (file)
@@ -33,4 +33,6 @@ gboolean mxf_is_d10_essence_track (const MXFMetadataTrack *track);
 GstCaps *
 mxf_d10_create_caps (MXFMetadataGenericPackage *package, MXFMetadataTrack *track, GstTagList **tags, MXFEssenceElementHandler *handler, gpointer *mapping_data);
 
+void mxf_d10_init (void);
+
 #endif /* __MXF_D10_H__ */
index f8a2b3b..b0c0d17 100644 (file)
@@ -18,7 +18,6 @@
  */
 
 /* TODO:
- *   - GObjectify structural metadata to get rid of the current inheritance mess
  *   - Implement support for DMS-1 and descriptive metadata tracks
  *   - Differentiate UL and UUIDs, the former can define an object system
  *     (i.e. mxf_ul_is_a() and friends could be implemented), see SMPTE S336M.
@@ -56,6 +55,7 @@
 
 #include "mxfdemux.h"
 #include "mxfparse.h"
+#include "mxfmetadata.h"
 #include "mxfaes-bwf.h"
 #include "mxfmpeg.h"
 #include "mxfdv-dif.h"
@@ -91,7 +91,6 @@ typedef struct
   GstPad parent;
 
   guint32 track_id;
-  MXFMetadataTrackType track_type;
   gboolean need_segment;
 
   GstFlowReturn last_flow;
@@ -104,11 +103,11 @@ typedef struct
 
   guint current_material_component;
   MXFMetadataGenericPackage *material_package;
-  MXFMetadataTrack *material_track;
+  MXFMetadataTimelineTrack *material_track;
   MXFMetadataStructuralComponent *component;
 
-  MXFMetadataGenericPackage *source_package;
-  MXFMetadataTrack *source_track;
+  MXFMetadataSourcePackage *source_package;
+  MXFMetadataTimelineTrack *source_track;
 
   GstCaps *caps;
 } GstMXFDemuxPad;
@@ -231,177 +230,19 @@ gst_mxf_demux_reset_metadata (GstMXFDemux * demux)
     }
   }
 
-  mxf_metadata_preface_reset (&demux->preface);
+  demux->preface = NULL;
 
-  if (demux->identification) {
-    for (i = 0; i < demux->identification->len; i++)
-      mxf_metadata_identification_reset (&g_array_index (demux->identification,
-              MXFMetadataIdentification, i));
-    g_array_free (demux->identification, TRUE);
-    demux->identification = NULL;
-  }
-
-  mxf_metadata_content_storage_reset (&demux->content_storage);
-
-  if (demux->essence_container_data) {
-    for (i = 0; i < demux->essence_container_data->len; i++)
-      mxf_metadata_essence_container_data_reset (&g_array_index
-          (demux->essence_container_data, MXFMetadataEssenceContainerData, i));
-    g_array_free (demux->essence_container_data, TRUE);
-    demux->essence_container_data = NULL;
-  }
-
-  if (demux->material_package) {
-    for (i = 0; i < demux->material_package->len; i++)
-      mxf_metadata_generic_package_reset (&g_array_index
-          (demux->material_package, MXFMetadataGenericPackage, i));
-    g_array_free (demux->material_package, TRUE);
-    demux->material_package = NULL;
-  }
-
-  if (demux->source_package) {
-    for (i = 0; i < demux->source_package->len; i++)
-      mxf_metadata_generic_package_reset (&g_array_index (demux->source_package,
-              MXFMetadataGenericPackage, i));
-    g_array_free (demux->source_package, TRUE);
-    demux->source_package = NULL;
-  }
-
-  if (demux->package) {
-    g_ptr_array_free (demux->package, TRUE);
-    demux->package = NULL;
-  }
-
-  if (demux->track) {
-    for (i = 0; i < demux->track->len; i++)
-      mxf_metadata_track_reset (&g_array_index (demux->track,
-              MXFMetadataTrack, i));
-    g_array_free (demux->track, TRUE);
-    demux->track = NULL;
-  }
-
-  if (demux->sequence) {
-    for (i = 0; i < demux->sequence->len; i++)
-      mxf_metadata_sequence_reset (&g_array_index (demux->sequence,
-              MXFMetadataSequence, i));
-    g_array_free (demux->sequence, TRUE);
-    demux->sequence = NULL;
-  }
-
-  if (demux->structural_component) {
-    for (i = 0; i < demux->structural_component->len; i++)
-      mxf_metadata_structural_component_reset (&g_array_index
-          (demux->structural_component, MXFMetadataStructuralComponent, i));
-    g_array_free (demux->structural_component, TRUE);
-    demux->structural_component = NULL;
-  }
-
-  if (demux->generic_descriptor) {
-    for (i = 0; i < demux->generic_descriptor->len; i++)
-      mxf_metadata_generic_descriptor_reset (&g_array_index
-          (demux->generic_descriptor, MXFMetadataGenericDescriptor, i));
-    g_array_free (demux->generic_descriptor, TRUE);
-    demux->generic_descriptor = NULL;
-  }
-
-  if (demux->file_descriptor) {
-    for (i = 0; i < demux->file_descriptor->len; i++)
-      mxf_metadata_file_descriptor_reset (&g_array_index
-          (demux->file_descriptor, MXFMetadataFileDescriptor, i));
-    g_array_free (demux->file_descriptor, TRUE);
-    demux->file_descriptor = NULL;
-  }
-
-  if (demux->multiple_descriptor) {
-    for (i = 0; i < demux->multiple_descriptor->len; i++)
-      mxf_metadata_multiple_descriptor_reset (&g_array_index
-          (demux->multiple_descriptor, MXFMetadataMultipleDescriptor, i));
-    g_array_free (demux->multiple_descriptor, TRUE);
-    demux->multiple_descriptor = NULL;
-  }
-
-  if (demux->generic_data_essence_descriptor) {
-    for (i = 0; i < demux->generic_data_essence_descriptor->len; i++)
-      mxf_metadata_generic_data_essence_descriptor_reset (&g_array_index
-          (demux->generic_data_essence_descriptor,
-              MXFMetadataGenericDataEssenceDescriptor, i));
-    g_array_free (demux->generic_data_essence_descriptor, TRUE);
-    demux->generic_data_essence_descriptor = NULL;
-  }
-
-  if (demux->generic_picture_essence_descriptor) {
-    for (i = 0; i < demux->generic_picture_essence_descriptor->len; i++)
-      mxf_metadata_generic_picture_essence_descriptor_reset (&g_array_index
-          (demux->generic_picture_essence_descriptor,
-              MXFMetadataGenericPictureEssenceDescriptor, i));
-    g_array_free (demux->generic_picture_essence_descriptor, TRUE);
-    demux->generic_picture_essence_descriptor = NULL;
-  }
-
-  if (demux->cdci_picture_essence_descriptor) {
-    for (i = 0; i < demux->cdci_picture_essence_descriptor->len; i++)
-      mxf_metadata_cdci_picture_essence_descriptor_reset (&g_array_index
-          (demux->cdci_picture_essence_descriptor,
-              MXFMetadataCDCIPictureEssenceDescriptor, i));
-    g_array_free (demux->cdci_picture_essence_descriptor, TRUE);
-    demux->cdci_picture_essence_descriptor = NULL;
-  }
-
-  if (demux->rgba_picture_essence_descriptor) {
-    for (i = 0; i < demux->rgba_picture_essence_descriptor->len; i++)
-      mxf_metadata_rgba_picture_essence_descriptor_reset (&g_array_index
-          (demux->rgba_picture_essence_descriptor,
-              MXFMetadataRGBAPictureEssenceDescriptor, i));
-    g_array_free (demux->rgba_picture_essence_descriptor, TRUE);
-    demux->rgba_picture_essence_descriptor = NULL;
-  }
+  if (demux->metadata) {
+    guint i;
 
-  if (demux->mpeg_video_descriptor) {
-    for (i = 0; i < demux->mpeg_video_descriptor->len; i++)
-      mxf_metadata_mpeg_video_descriptor_reset (&g_array_index
-          (demux->mpeg_video_descriptor, MXFMetadataMPEGVideoDescriptor, i));
-    g_array_free (demux->mpeg_video_descriptor, TRUE);
-    demux->mpeg_video_descriptor = NULL;
-  }
+    for (i = 0; i < demux->metadata->len; i++) {
+      GstMiniObject *o = g_ptr_array_index (demux->metadata, i);
 
-  if (demux->generic_sound_essence_descriptor) {
-    for (i = 0; i < demux->generic_sound_essence_descriptor->len; i++)
-      mxf_metadata_generic_sound_essence_descriptor_reset (&g_array_index
-          (demux->generic_sound_essence_descriptor,
-              MXFMetadataGenericSoundEssenceDescriptor, i));
-    g_array_free (demux->generic_sound_essence_descriptor, TRUE);
-    demux->generic_sound_essence_descriptor = NULL;
-  }
-
-  if (demux->wave_audio_essence_descriptor) {
-    for (i = 0; i < demux->wave_audio_essence_descriptor->len; i++)
-      mxf_metadata_wave_audio_essence_descriptor_reset (&g_array_index
-          (demux->wave_audio_essence_descriptor,
-              MXFMetadataWaveAudioEssenceDescriptor, i));
-    g_array_free (demux->wave_audio_essence_descriptor, TRUE);
-    demux->wave_audio_essence_descriptor = NULL;
-  }
-
-  if (demux->aes3_audio_essence_descriptor) {
-    for (i = 0; i < demux->aes3_audio_essence_descriptor->len; i++)
-      mxf_metadata_aes3_audio_essence_descriptor_reset (&g_array_index
-          (demux->aes3_audio_essence_descriptor,
-              MXFMetadataAES3AudioEssenceDescriptor, i));
-    g_array_free (demux->aes3_audio_essence_descriptor, TRUE);
-    demux->aes3_audio_essence_descriptor = NULL;
-  }
-
-  if (demux->descriptor) {
-    g_ptr_array_free (demux->descriptor, TRUE);
-    demux->descriptor = NULL;
-  }
-
-  if (demux->locator) {
-    for (i = 0; i < demux->locator->len; i++)
-      mxf_metadata_locator_reset (&g_array_index (demux->locator,
-              MXFMetadataLocator, i));
-    g_array_free (demux->locator, TRUE);
-    demux->locator = NULL;
+      if (o)
+        gst_mini_object_unref (o);
+    }
+    g_ptr_array_free (demux->metadata, TRUE);
+    demux->metadata = NULL;
   }
 }
 
@@ -430,1236 +271,199 @@ gst_mxf_demux_reset (GstMXFDemux * demux)
   if (demux->close_seg_event) {
     gst_event_unref (demux->close_seg_event);
     demux->close_seg_event = NULL;
-  }
-
-  gst_adapter_clear (demux->adapter);
-
-  gst_mxf_demux_remove_pads (demux);
-
-  if (demux->partition_index) {
-    g_array_free (demux->partition_index, TRUE);
-    demux->partition_index = NULL;
-  }
-
-  if (demux->index_table) {
-    guint i;
-
-    for (i = 0; i < demux->index_table->len; i++)
-      mxf_index_table_segment_reset (&g_array_index (demux->index_table,
-              MXFIndexTableSegment, i));
-
-    g_array_free (demux->index_table, TRUE);
-    demux->index_table = NULL;
-  }
-
-  gst_mxf_demux_reset_mxf_state (demux);
-  gst_mxf_demux_reset_metadata (demux);
-}
-
-static GstFlowReturn
-gst_mxf_demux_combine_flows (GstMXFDemux * demux,
-    GstMXFDemuxPad * pad, GstFlowReturn ret)
-{
-  guint i;
-
-  /* store the value */
-  pad->last_flow = ret;
-
-  /* any other error that is not-linked can be returned right away */
-  if (ret != GST_FLOW_NOT_LINKED)
-    goto done;
-
-  /* only return NOT_LINKED if all other pads returned NOT_LINKED */
-  g_assert (demux->src->len != 0);
-  for (i = 0; i < demux->src->len; i++) {
-    GstMXFDemuxPad *opad = g_ptr_array_index (demux->src, i);
-
-    if (opad == NULL)
-      continue;
-
-    ret = opad->last_flow;
-    /* some other return value (must be SUCCESS but we can return
-     * other values as well) */
-    if (ret != GST_FLOW_NOT_LINKED)
-      goto done;
-  }
-  /* if we get here, all other pads were unlinked and we return
-   * NOT_LINKED then */
-done:
-  GST_LOG_OBJECT (demux, "combined return %s", gst_flow_get_name (ret));
-  return ret;
-}
-
-static GstFlowReturn
-gst_mxf_demux_pull_range (GstMXFDemux * demux, guint64 offset,
-    guint size, GstBuffer ** buffer)
-{
-  GstFlowReturn ret;
-
-  ret = gst_pad_pull_range (demux->sinkpad, offset, size, buffer);
-  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
-    GST_WARNING_OBJECT (demux,
-        "failed when pulling %u bytes from offset %" G_GUINT64_FORMAT ": %s",
-        size, offset, gst_flow_get_name (ret));
-    *buffer = NULL;
-    return ret;
-  }
-
-  if (G_UNLIKELY (*buffer && GST_BUFFER_SIZE (*buffer) != size)) {
-    GST_WARNING_OBJECT (demux,
-        "partial pull got %u when expecting %u from offset %" G_GUINT64_FORMAT,
-        GST_BUFFER_SIZE (*buffer), size, offset);
-    gst_buffer_unref (*buffer);
-    ret = GST_FLOW_UNEXPECTED;
-    *buffer = NULL;
-    return ret;
-  }
-
-  return ret;
-}
-
-static gboolean
-gst_mxf_demux_push_src_event (GstMXFDemux * demux, GstEvent * event)
-{
-  gboolean ret = TRUE;
-  guint i;
-
-  GST_DEBUG_OBJECT (demux, "Pushing '%s' event downstream",
-      GST_EVENT_TYPE_NAME (event));
-
-  if (!demux->src)
-    return ret;
-
-  for (i = 0; i < demux->src->len; i++) {
-    GstPad *pad = GST_PAD (g_ptr_array_index (demux->src, i));
-
-    ret |= gst_pad_push_event (pad, gst_event_ref (event));
-  }
-
-  gst_event_unref (event);
-
-  return ret;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_partition_pack (GstMXFDemux * demux, const MXFUL * key,
-    GstBuffer * buffer)
-{
-  if (demux->partition.valid) {
-    mxf_partition_pack_reset (&demux->partition);
-    mxf_primer_pack_reset (&demux->primer);
-  }
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling partition pack of size %u at offset %"
-      G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
-
-  if (!mxf_partition_pack_parse (key, &demux->partition,
-          GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
-    GST_ERROR_OBJECT (demux, "Parsing partition pack failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (demux->partition.type == MXF_PARTITION_PACK_HEADER)
-    demux->footer_partition_pack_offset = demux->partition.footer_partition;
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_primer_pack (GstMXFDemux * demux, const MXFUL * key,
-    GstBuffer * buffer)
-{
-  GST_DEBUG_OBJECT (demux,
-      "Handling primer pack of size %u at offset %"
-      G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
-
-  if (G_UNLIKELY (!demux->partition.valid)) {
-    GST_ERROR_OBJECT (demux, "Primer pack before partition pack");
-    return GST_FLOW_ERROR;
-  }
-
-  if (G_UNLIKELY (demux->primer.valid)) {
-    GST_ERROR_OBJECT (demux, "Primer pack already exists");
-    return GST_FLOW_OK;
-  }
-
-  if (!mxf_primer_pack_parse (key, &demux->primer,
-          GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
-    GST_ERROR_OBJECT (demux, "Parsing primer pack failed");
-    return GST_FLOW_ERROR;
-  }
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_preface (GstMXFDemux * demux,
-    const MXFUL * key, GstBuffer * buffer)
-{
-  MXFMetadataPreface preface;
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata preface of size %u"
-      " at offset %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
-
-  if (!mxf_metadata_preface_parse (key, &preface, &demux->primer,
-          GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
-    GST_ERROR_OBJECT (demux, "Parsing metadata preface failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (mxf_timestamp_is_unknown (&demux->preface.last_modified_date)
-      || (!mxf_timestamp_is_unknown (&preface.last_modified_date)
-          && mxf_timestamp_compare (&demux->preface.last_modified_date,
-              &preface.last_modified_date) < 0)) {
-    GST_DEBUG_OBJECT (demux,
-        "Timestamp of new preface is newer than old, updating metadata");
-    gst_mxf_demux_reset_metadata (demux);
-    memcpy (&demux->preface, &preface, sizeof (MXFMetadataPreface));
-  } else {
-    GST_DEBUG_OBJECT (demux, "Preface is older than already parsed preface");
-  }
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_identification (GstMXFDemux * demux,
-    const MXFUL * key, GstBuffer * buffer)
-{
-  MXFMetadataIdentification identification;
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata identification of size %u"
-      " at offset %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
-
-  if (!mxf_metadata_identification_parse (key, &identification,
-          &demux->primer, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
-    GST_ERROR_OBJECT (demux, "Parsing metadata identification failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->identification)
-    demux->identification =
-        g_array_new (FALSE, FALSE, sizeof (MXFMetadataIdentification));
-
-  g_array_append_val (demux->identification, identification);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_content_storage (GstMXFDemux * demux,
-    const MXFUL * key, GstBuffer * buffer)
-{
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata content storage of size %u"
-      " at offset %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
-
-  if (!mxf_metadata_content_storage_parse (key,
-          &demux->content_storage, &demux->primer, GST_BUFFER_DATA (buffer),
-          GST_BUFFER_SIZE (buffer))) {
-    GST_ERROR_OBJECT (demux, "Parsing metadata content storage failed");
-    return GST_FLOW_ERROR;
-  }
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_essence_container_data (GstMXFDemux *
-    demux, const MXFUL * key, GstBuffer * buffer)
-{
-  MXFMetadataEssenceContainerData essence_container_data;
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata essence container data of size %u"
-      " at offset %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
-
-  if (!mxf_metadata_essence_container_data_parse (key,
-          &essence_container_data, &demux->primer, GST_BUFFER_DATA (buffer),
-          GST_BUFFER_SIZE (buffer))) {
-    GST_ERROR_OBJECT (demux, "Parsing metadata essence container data failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->essence_container_data)
-    demux->essence_container_data =
-        g_array_new (FALSE, FALSE, sizeof (MXFMetadataEssenceContainerData));
-
-  g_array_append_val (demux->essence_container_data, essence_container_data);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_material_package (GstMXFDemux * demux,
-    const MXFUL * key, GstBuffer * buffer)
-{
-  MXFMetadataGenericPackage material_package;
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata material package of size %u"
-      " at offset %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
-
-  if (!mxf_metadata_generic_package_parse (key, &material_package,
-          &demux->primer, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
-    GST_ERROR_OBJECT (demux, "Parsing metadata material package failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->material_package)
-    demux->material_package =
-        g_array_new (FALSE, FALSE, sizeof (MXFMetadataMaterialPackage));
-
-  g_array_append_val (demux->material_package, material_package);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_source_package (GstMXFDemux * demux,
-    const MXFUL * key, GstBuffer * buffer)
-{
-  MXFMetadataGenericPackage source_package;
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata source package of size %u"
-      " at offset %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
-
-  if (!mxf_metadata_generic_package_parse (key, &source_package,
-          &demux->primer, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
-    GST_ERROR_OBJECT (demux, "Parsing metadata source package failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->source_package)
-    demux->source_package =
-        g_array_new (FALSE, FALSE, sizeof (MXFMetadataSourcePackage));
-
-  g_array_append_val (demux->source_package, source_package);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_track (GstMXFDemux * demux,
-    const MXFUL * key, guint16 type, GstBuffer * buffer)
-{
-  MXFMetadataTrack track;
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata track with type 0x%04x of size %u"
-      " at offset %" G_GUINT64_FORMAT, type, GST_BUFFER_SIZE (buffer),
-      demux->offset);
-
-  if (!mxf_metadata_track_parse (key, &track, &demux->primer,
-          type, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
-    GST_ERROR_OBJECT (demux, "Parsing metadata track failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->track)
-    demux->track = g_array_new (FALSE, FALSE, sizeof (MXFMetadataTrack));
-
-  g_array_append_val (demux->track, track);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_sequence (GstMXFDemux * demux,
-    const MXFUL * key, GstBuffer * buffer)
-{
-  MXFMetadataSequence sequence;
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata sequence of size %u"
-      " at offset %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
-
-  if (!mxf_metadata_sequence_parse (key, &sequence,
-          &demux->primer, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
-    GST_ERROR_OBJECT (demux, "Parsing metadata sequence failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->sequence)
-    demux->sequence = g_array_new (FALSE, FALSE, sizeof (MXFMetadataSequence));
-
-  g_array_append_val (demux->sequence, sequence);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_structural_component (GstMXFDemux * demux,
-    const MXFUL * key, guint16 type, GstBuffer * buffer)
-{
-  MXFMetadataStructuralComponent component;
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata structural component of size %u"
-      " at offset %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
-
-  if (!mxf_metadata_structural_component_parse (key, &component,
-          &demux->primer, type, GST_BUFFER_DATA (buffer),
-          GST_BUFFER_SIZE (buffer))) {
-    GST_ERROR_OBJECT (demux, "Parsing metadata structural component failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->structural_component)
-    demux->structural_component =
-        g_array_new (FALSE, FALSE, sizeof (MXFMetadataStructuralComponent));
-
-  g_array_append_val (demux->structural_component, component);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_file_descriptor (GstMXFDemux * demux,
-    const MXFUL * key, guint16 type, GstBuffer * buffer)
-{
-  MXFMetadataFileDescriptor descriptor;
-
-  memset (&descriptor, 0, sizeof (descriptor));
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata file descriptor of size %u"
-      " at offset %" G_GUINT64_FORMAT " with type 0x%04d",
-      GST_BUFFER_SIZE (buffer), demux->offset, type);
-
-  if (!mxf_metadata_descriptor_parse (key,
-          (MXFMetadataGenericDescriptor *) & descriptor, &demux->primer,
-          type, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer),
-          (MXFMetadataDescriptorHandleTag)
-          mxf_metadata_file_descriptor_handle_tag,
-          (MXFMetadataDescriptorReset) mxf_metadata_file_descriptor_reset)) {
-    GST_ERROR_OBJECT (demux, "Parsing metadata file descriptor failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->file_descriptor)
-    demux->file_descriptor =
-        g_array_new (FALSE, FALSE, sizeof (MXFMetadataFileDescriptor));
-
-  g_array_append_val (demux->file_descriptor, descriptor);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_multiple_descriptor (GstMXFDemux * demux,
-    const MXFUL * key, guint16 type, GstBuffer * buffer)
-{
-  MXFMetadataMultipleDescriptor descriptor;
-
-  memset (&descriptor, 0, sizeof (descriptor));
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata multiple descriptor of size %u"
-      " at offset %" G_GUINT64_FORMAT " with type 0x%04d",
-      GST_BUFFER_SIZE (buffer), demux->offset, type);
-
-  if (!mxf_metadata_descriptor_parse (key,
-          (MXFMetadataGenericDescriptor *) & descriptor, &demux->primer,
-          type, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer),
-          (MXFMetadataDescriptorHandleTag)
-          mxf_metadata_multiple_descriptor_handle_tag,
-          (MXFMetadataDescriptorReset) mxf_metadata_multiple_descriptor_reset))
-  {
-    GST_ERROR_OBJECT (demux, "Parsing metadata multiple descriptor failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->multiple_descriptor)
-    demux->multiple_descriptor =
-        g_array_new (FALSE, FALSE, sizeof (MXFMetadataMultipleDescriptor));
-
-  g_array_append_val (demux->multiple_descriptor, descriptor);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_generic_data_essence_descriptor (GstMXFDemux *
-    demux, const MXFUL * key, guint16 type, GstBuffer * buffer)
-{
-  MXFMetadataGenericDataEssenceDescriptor descriptor;
-
-  memset (&descriptor, 0, sizeof (descriptor));
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata generic data essence descriptor of size %u"
-      " at offset %" G_GUINT64_FORMAT " with type 0x%04d",
-      GST_BUFFER_SIZE (buffer), demux->offset, type);
-
-  if (!mxf_metadata_descriptor_parse (key,
-          (MXFMetadataGenericDescriptor *) & descriptor, &demux->primer,
-          type, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer),
-          (MXFMetadataDescriptorHandleTag)
-          mxf_metadata_generic_data_essence_descriptor_handle_tag,
-          (MXFMetadataDescriptorReset)
-          mxf_metadata_generic_data_essence_descriptor_reset)) {
-    GST_ERROR_OBJECT (demux,
-        "Parsing metadata generic data essence descriptor failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->generic_data_essence_descriptor)
-    demux->generic_data_essence_descriptor =
-        g_array_new (FALSE, FALSE,
-        sizeof (MXFMetadataGenericDataEssenceDescriptor));
-
-  g_array_append_val (demux->generic_data_essence_descriptor, descriptor);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_generic_picture_essence_descriptor (GstMXFDemux *
-    demux, const MXFUL * key, guint16 type, GstBuffer * buffer)
-{
-  MXFMetadataGenericPictureEssenceDescriptor descriptor;
-
-  memset (&descriptor, 0, sizeof (descriptor));
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata generic picture essence descriptor of size %u"
-      " at offset %" G_GUINT64_FORMAT " with type 0x%04d",
-      GST_BUFFER_SIZE (buffer), demux->offset, type);
-
-  if (!mxf_metadata_descriptor_parse (key,
-          (MXFMetadataGenericDescriptor *) & descriptor, &demux->primer,
-          type, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer),
-          (MXFMetadataDescriptorHandleTag)
-          mxf_metadata_generic_picture_essence_descriptor_handle_tag,
-          (MXFMetadataDescriptorReset)
-          mxf_metadata_generic_picture_essence_descriptor_reset)) {
-    GST_ERROR_OBJECT (demux,
-        "Parsing metadata generic picture essence descriptor failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->generic_picture_essence_descriptor)
-    demux->generic_picture_essence_descriptor =
-        g_array_new (FALSE, FALSE,
-        sizeof (MXFMetadataGenericPictureEssenceDescriptor));
-
-  g_array_append_val (demux->generic_picture_essence_descriptor, descriptor);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_cdci_picture_essence_descriptor (GstMXFDemux *
-    demux, const MXFUL * key, guint16 type, GstBuffer * buffer)
-{
-  MXFMetadataCDCIPictureEssenceDescriptor descriptor;
-
-  memset (&descriptor, 0, sizeof (descriptor));
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata CDCI picture essence descriptor of size %u"
-      " at offset %" G_GUINT64_FORMAT " with type 0x%04d",
-      GST_BUFFER_SIZE (buffer), demux->offset, type);
-
-  if (!mxf_metadata_descriptor_parse (key,
-          (MXFMetadataGenericDescriptor *) & descriptor, &demux->primer,
-          type, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer),
-          (MXFMetadataDescriptorHandleTag)
-          mxf_metadata_cdci_picture_essence_descriptor_handle_tag,
-          (MXFMetadataDescriptorReset)
-          mxf_metadata_cdci_picture_essence_descriptor_reset)) {
-    GST_ERROR_OBJECT (demux,
-        "Parsing metadata CDCI picture essence descriptor failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->cdci_picture_essence_descriptor)
-    demux->cdci_picture_essence_descriptor =
-        g_array_new (FALSE, FALSE,
-        sizeof (MXFMetadataCDCIPictureEssenceDescriptor));
-
-  g_array_append_val (demux->cdci_picture_essence_descriptor, descriptor);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_rgba_picture_essence_descriptor (GstMXFDemux *
-    demux, const MXFUL * key, guint16 type, GstBuffer * buffer)
-{
-  MXFMetadataRGBAPictureEssenceDescriptor descriptor;
-
-  memset (&descriptor, 0, sizeof (descriptor));
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata RGBA picture essence descriptor of size %u"
-      " at offset %" G_GUINT64_FORMAT " with type 0x%04d",
-      GST_BUFFER_SIZE (buffer), demux->offset, type);
-
-  if (!mxf_metadata_descriptor_parse (key,
-          (MXFMetadataGenericDescriptor *) & descriptor, &demux->primer,
-          type, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer),
-          (MXFMetadataDescriptorHandleTag)
-          mxf_metadata_rgba_picture_essence_descriptor_handle_tag,
-          (MXFMetadataDescriptorReset)
-          mxf_metadata_rgba_picture_essence_descriptor_reset)) {
-    GST_ERROR_OBJECT (demux,
-        "Parsing metadata RGBA picture essence descriptor failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->rgba_picture_essence_descriptor)
-    demux->rgba_picture_essence_descriptor =
-        g_array_new (FALSE, FALSE,
-        sizeof (MXFMetadataRGBAPictureEssenceDescriptor));
-
-  g_array_append_val (demux->rgba_picture_essence_descriptor, descriptor);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_mpeg_video_descriptor (GstMXFDemux * demux,
-    const MXFUL * key, guint16 type, GstBuffer * buffer)
-{
-  MXFMetadataMPEGVideoDescriptor descriptor;
-
-  memset (&descriptor, 0, sizeof (descriptor));
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata MPEG video descriptor of size %u"
-      " at offset %" G_GUINT64_FORMAT " with type 0x%04d",
-      GST_BUFFER_SIZE (buffer), demux->offset, type);
-
-  if (!mxf_metadata_descriptor_parse (key,
-          (MXFMetadataGenericDescriptor *) & descriptor, &demux->primer,
-          type, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer),
-          (MXFMetadataDescriptorHandleTag)
-          mxf_metadata_mpeg_video_descriptor_handle_tag,
-          (MXFMetadataDescriptorReset)
-          mxf_metadata_mpeg_video_descriptor_reset)) {
-    GST_ERROR_OBJECT (demux, "Parsing metadata MPEG video descriptor failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->mpeg_video_descriptor)
-    demux->mpeg_video_descriptor =
-        g_array_new (FALSE, FALSE, sizeof (MXFMetadataMPEGVideoDescriptor));
-
-  g_array_append_val (demux->mpeg_video_descriptor, descriptor);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_generic_sound_essence_descriptor (GstMXFDemux *
-    demux, const MXFUL * key, guint16 type, GstBuffer * buffer)
-{
-  MXFMetadataGenericSoundEssenceDescriptor descriptor;
-
-  memset (&descriptor, 0, sizeof (descriptor));
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata generic sound essence descriptor of size %u"
-      " at offset %" G_GUINT64_FORMAT " with type 0x%04d",
-      GST_BUFFER_SIZE (buffer), demux->offset, type);
-
-  if (!mxf_metadata_descriptor_parse (key,
-          (MXFMetadataGenericDescriptor *) & descriptor, &demux->primer,
-          type, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer),
-          (MXFMetadataDescriptorHandleTag)
-          mxf_metadata_generic_sound_essence_descriptor_handle_tag,
-          (MXFMetadataDescriptorReset)
-          mxf_metadata_generic_sound_essence_descriptor_reset)) {
-    GST_ERROR_OBJECT (demux,
-        "Parsing metadata generic sound essence descriptor failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->generic_sound_essence_descriptor)
-    demux->generic_sound_essence_descriptor =
-        g_array_new (FALSE, FALSE,
-        sizeof (MXFMetadataGenericSoundEssenceDescriptor));
-
-  g_array_append_val (demux->generic_sound_essence_descriptor, descriptor);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_wave_audio_essence_descriptor (GstMXFDemux *
-    demux, const MXFUL * key, guint16 type, GstBuffer * buffer)
-{
-  MXFMetadataWaveAudioEssenceDescriptor descriptor;
-
-  memset (&descriptor, 0, sizeof (descriptor));
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata wave sound essence descriptor of size %u"
-      " at offset %" G_GUINT64_FORMAT " with type 0x%04d",
-      GST_BUFFER_SIZE (buffer), demux->offset, type);
-
-  if (!mxf_metadata_descriptor_parse (key,
-          (MXFMetadataGenericDescriptor *) & descriptor, &demux->primer,
-          type, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer),
-          (MXFMetadataDescriptorHandleTag)
-          mxf_metadata_wave_audio_essence_descriptor_handle_tag,
-          (MXFMetadataDescriptorReset)
-          mxf_metadata_wave_audio_essence_descriptor_reset)) {
-    GST_ERROR_OBJECT (demux,
-        "Parsing metadata wave sound essence descriptor failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->wave_audio_essence_descriptor)
-    demux->wave_audio_essence_descriptor =
-        g_array_new (FALSE, FALSE,
-        sizeof (MXFMetadataWaveAudioEssenceDescriptor));
-
-  g_array_append_val (demux->wave_audio_essence_descriptor, descriptor);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_aes3_audio_essence_descriptor (GstMXFDemux *
-    demux, const MXFUL * key, guint16 type, GstBuffer * buffer)
-{
-  MXFMetadataAES3AudioEssenceDescriptor descriptor;
-
-  memset (&descriptor, 0, sizeof (descriptor));
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata AES3 audio essence descriptor of size %u"
-      " at offset %" G_GUINT64_FORMAT " with type 0x%04d",
-      GST_BUFFER_SIZE (buffer), demux->offset, type);
-
-  if (!mxf_metadata_descriptor_parse (key,
-          (MXFMetadataGenericDescriptor *) & descriptor, &demux->primer,
-          type, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer),
-          (MXFMetadataDescriptorHandleTag)
-          mxf_metadata_aes3_audio_essence_descriptor_handle_tag,
-          (MXFMetadataDescriptorReset)
-          mxf_metadata_aes3_audio_essence_descriptor_reset)) {
-    GST_ERROR_OBJECT (demux,
-        "Parsing metadata AES3 audio essence descriptor failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->aes3_audio_essence_descriptor)
-    demux->aes3_audio_essence_descriptor =
-        g_array_new (FALSE, FALSE,
-        sizeof (MXFMetadataAES3AudioEssenceDescriptor));
-
-  g_array_append_val (demux->aes3_audio_essence_descriptor, descriptor);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_metadata_locator (GstMXFDemux * demux,
-    const MXFUL * key, guint16 type, GstBuffer * buffer)
-{
-  MXFMetadataLocator locator;
-
-  GST_DEBUG_OBJECT (demux,
-      "Handling metadata locator of size %u"
-      " at offset %" G_GUINT64_FORMAT " with type 0x%04d",
-      GST_BUFFER_SIZE (buffer), demux->offset, type);
-
-  if (!mxf_metadata_locator_parse (key, &locator, &demux->primer,
-          type, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
-    GST_ERROR_OBJECT (demux, "Parsing metadata locator failed");
-    return GST_FLOW_ERROR;
-  }
-
-  if (!demux->locator)
-    demux->locator = g_array_new (FALSE, FALSE, sizeof (MXFMetadataLocator));
-
-  g_array_append_val (demux->locator, locator);
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_mxf_demux_handle_header_metadata_resolve_references (GstMXFDemux * demux)
-{
-  guint i, j, k;
-  GstFlowReturn ret = GST_FLOW_OK;
-
-  GST_DEBUG_OBJECT (demux, "Resolve metadata references");
-  demux->update_metadata = FALSE;
-
-  /* Fill in demux->descriptor */
-  demux->descriptor = g_ptr_array_new ();
-
-#define FILL_DESCRIPTOR_ARRAY(desc_array, TYPE) \
-  G_STMT_START { \
-    if (desc_array) { \
-      for (i = 0; i < desc_array->len; i++) { \
-        g_ptr_array_add (demux->descriptor, \
-           &g_array_index (desc_array, TYPE, i)); \
-      } \
-    } \
-  } G_STMT_END
-
-  FILL_DESCRIPTOR_ARRAY (demux->generic_descriptor,
-      MXFMetadataGenericDescriptor);
-  FILL_DESCRIPTOR_ARRAY (demux->file_descriptor, MXFMetadataFileDescriptor);
-  FILL_DESCRIPTOR_ARRAY (demux->generic_data_essence_descriptor,
-      MXFMetadataGenericDataEssenceDescriptor);
-  FILL_DESCRIPTOR_ARRAY (demux->generic_picture_essence_descriptor,
-      MXFMetadataGenericPictureEssenceDescriptor);
-  FILL_DESCRIPTOR_ARRAY (demux->cdci_picture_essence_descriptor,
-      MXFMetadataCDCIPictureEssenceDescriptor);
-  FILL_DESCRIPTOR_ARRAY (demux->rgba_picture_essence_descriptor,
-      MXFMetadataRGBAPictureEssenceDescriptor);
-  FILL_DESCRIPTOR_ARRAY (demux->mpeg_video_descriptor,
-      MXFMetadataMPEGVideoDescriptor);
-  FILL_DESCRIPTOR_ARRAY (demux->generic_sound_essence_descriptor,
-      MXFMetadataGenericSoundEssenceDescriptor);
-  FILL_DESCRIPTOR_ARRAY (demux->wave_audio_essence_descriptor,
-      MXFMetadataWaveAudioEssenceDescriptor);
-  FILL_DESCRIPTOR_ARRAY (demux->aes3_audio_essence_descriptor,
-      MXFMetadataAES3AudioEssenceDescriptor);
-  FILL_DESCRIPTOR_ARRAY (demux->multiple_descriptor,
-      MXFMetadataMultipleDescriptor);
-
-#undef FILL_DESCRIPTOR_ARRAY
-
-  /* Fill in demux->package */
-  demux->package = g_ptr_array_new ();
-  if (demux->material_package) {
-    for (i = 0; i < demux->material_package->len; i++) {
-      g_ptr_array_add (demux->package, &g_array_index (demux->material_package,
-              MXFMetadataGenericPackage, i));
-    }
-  }
-  if (demux->source_package) {
-    for (i = 0; i < demux->source_package->len; i++) {
-      g_ptr_array_add (demux->package, &g_array_index (demux->source_package,
-              MXFMetadataGenericPackage, i));
-    }
-  }
-
-  /* Multiple descriptor */
-  if (demux->multiple_descriptor && demux->descriptor) {
-    for (i = 0; i < demux->multiple_descriptor->len; i++) {
-      MXFMetadataMultipleDescriptor *d =
-          &g_array_index (demux->multiple_descriptor,
-          MXFMetadataMultipleDescriptor, i);
-
-      d->sub_descriptors =
-          g_new0 (MXFMetadataGenericDescriptor *, d->n_sub_descriptors);
-      for (j = 0; j < d->n_sub_descriptors; j++) {
-        for (k = 0; k < demux->descriptor->len; k++) {
-          MXFMetadataGenericDescriptor *e =
-              g_ptr_array_index (demux->descriptor, k);
-
-          if (mxf_ul_is_equal (&d->sub_descriptors_uids[j], &e->instance_uid)) {
-            d->sub_descriptors[j] = e;
-            break;
-          }
-        }
-      }
-    }
-  }
-
-  /* See SMPTE 377M 8.4 */
-
-  /* Preface */
-  if (demux->package) {
-    for (i = 0; i < demux->package->len; i++) {
-      MXFMetadataGenericPackage *package =
-          g_ptr_array_index (demux->package, i);
-
-      if (mxf_ul_is_equal (&demux->preface.primary_package_uid,
-              &package->instance_uid)) {
-        demux->preface.primary_package = package;
-        break;
-      }
-    }
-  }
-
-  demux->preface.identifications =
-      g_new0 (MXFMetadataIdentification *, demux->preface.n_identifications);
-  if (demux->identification) {
-    for (i = 0; i < demux->identification->len; i++) {
-      MXFMetadataIdentification *identification =
-          &g_array_index (demux->identification,
-          MXFMetadataIdentification, i);
-
-      for (j = 0; j < demux->preface.n_identifications; j++) {
-        if (mxf_ul_is_equal (&demux->preface.identifications_uids[j],
-                &identification->instance_uid)) {
-          demux->preface.identifications[j] = identification;
-          break;
-        }
-      }
-    }
-  }
-
-  if (!mxf_ul_is_equal (&demux->preface.content_storage_uid,
-          &demux->content_storage.instance_uid)) {
-    GST_ERROR_OBJECT (demux,
-        "Preface content storage UID not equal to actual content storage instance uid");
-    ret = GST_FLOW_ERROR;
-    goto error;
-  }
-  demux->preface.content_storage = &demux->content_storage;
-
-  /* Content storage */
-  demux->content_storage.packages =
-      g_new0 (MXFMetadataGenericPackage *, demux->content_storage.n_packages);
-  if (demux->package) {
-    for (i = 0; i < demux->package->len; i++) {
-      MXFMetadataGenericPackage *package =
-          g_ptr_array_index (demux->package, i);
-
-      for (j = 0; j < demux->content_storage.n_packages; j++) {
-        if (mxf_ul_is_equal (&demux->content_storage.packages_uids[j],
-                &package->instance_uid)) {
-          demux->content_storage.packages[j] = package;
-          break;
-        }
-      }
-    }
-  }
-
-  demux->content_storage.essence_container_data =
-      g_new0 (MXFMetadataEssenceContainerData *,
-      demux->content_storage.n_essence_container_data);
-  if (demux->essence_container_data) {
-    for (i = 0; i < demux->essence_container_data->len; i++) {
-      MXFMetadataEssenceContainerData *data =
-          &g_array_index (demux->essence_container_data,
-          MXFMetadataEssenceContainerData, i);
-
-      for (j = 0; j < demux->content_storage.n_essence_container_data; j++) {
-        if (mxf_ul_is_equal (&demux->
-                content_storage.essence_container_data_uids[j],
-                &data->instance_uid)) {
-          demux->content_storage.essence_container_data[j] = data;
-          break;
-        }
-      }
-    }
-  }
-
-  /* Essence container data */
-  if (demux->package && demux->essence_container_data) {
-    for (i = 0; i < demux->package->len; i++) {
-      MXFMetadataGenericPackage *package =
-          g_ptr_array_index (demux->package, i);
-
-      for (j = 0; j < demux->essence_container_data->len; j++) {
-        MXFMetadataEssenceContainerData *data =
-            &g_array_index (demux->essence_container_data,
-            MXFMetadataEssenceContainerData, j);
-
-        if (mxf_umid_is_equal (&data->linked_package_uid,
-                &package->package_uid)) {
-          data->linked_package = package;
-          break;
-        }
-      }
-    }
-  }
-
-  /* Generic package */
-  if (demux->package) {
-    for (i = 0; i < demux->package->len; i++) {
-      MXFMetadataGenericPackage *package =
-          g_ptr_array_index (demux->package, i);
-
-      package->tracks = g_new0 (MXFMetadataTrack *, package->n_tracks);
-      if (demux->track) {
-        for (j = 0; j < package->n_tracks; j++) {
-          for (k = 0; k < demux->track->len; k++) {
-            MXFMetadataTrack *track =
-                &g_array_index (demux->track, MXFMetadataTrack, k);
-
-            if (mxf_ul_is_equal (&package->tracks_uids[j],
-                    &track->instance_uid)) {
-              package->tracks[j] = track;
-              break;
-            }
-          }
-        }
-      }
-
-      /* Resolve descriptors */
-      if (package->n_descriptors > 0 && demux->descriptor) {
-        MXFMetadataGenericDescriptor *d = NULL;
-
-        for (j = 0; j < demux->descriptor->len; j++) {
-          MXFMetadataGenericDescriptor *descriptor =
-              g_ptr_array_index (demux->descriptor, j);
-
-          if (mxf_ul_is_equal (&package->descriptors_uid,
-                  &descriptor->instance_uid)) {
-            d = descriptor;
-            break;
-          }
-        }
-
-        if (d && d->type == MXF_METADATA_MULTIPLE_DESCRIPTOR) {
-          MXFMetadataMultipleDescriptor *e =
-              (MXFMetadataMultipleDescriptor *) d;
+  }
 
-          package->n_descriptors = e->n_sub_descriptors;
-          package->descriptors =
-              g_new0 (MXFMetadataGenericDescriptor *, e->n_sub_descriptors);
+  gst_adapter_clear (demux->adapter);
 
-          /* These are already resolved */
-          for (j = 0; j < e->n_sub_descriptors; j++)
-            package->descriptors[j] = e->sub_descriptors[j];
-        } else {
-          package->n_descriptors = 1;
-          package->descriptors = g_new0 (MXFMetadataGenericDescriptor *, 1);
-          package->descriptors[0] = d;
-        }
-      }
+  gst_mxf_demux_remove_pads (demux);
 
-      if (package->tracks && package->descriptors) {
-        for (j = 0; j < package->n_tracks; j++) {
-          MXFMetadataTrack *track = package->tracks[j];
-          guint i, n_descriptor = 0;
+  if (demux->partition_index) {
+    g_array_free (demux->partition_index, TRUE);
+    demux->partition_index = NULL;
+  }
 
-          if (!track)
-            continue;
+  if (demux->index_table) {
+    guint i;
 
-          for (k = 0; k < package->n_descriptors; k++) {
-            MXFMetadataGenericDescriptor *d = package->descriptors[k];
-            MXFMetadataFileDescriptor *e;
+    for (i = 0; i < demux->index_table->len; i++)
+      mxf_index_table_segment_reset (&g_array_index (demux->index_table,
+              MXFIndexTableSegment, i));
 
-            if (!d || !d->is_file_descriptor)
-              continue;
+    g_array_free (demux->index_table, TRUE);
+    demux->index_table = NULL;
+  }
 
-            e = (MXFMetadataFileDescriptor *) d;
+  gst_mxf_demux_reset_mxf_state (demux);
+  gst_mxf_demux_reset_metadata (demux);
+}
 
-            if (e->linked_track_id == track->track_id ||
-                e->linked_track_id == 0)
-              n_descriptor++;
-          }
+static GstFlowReturn
+gst_mxf_demux_combine_flows (GstMXFDemux * demux,
+    GstMXFDemuxPad * pad, GstFlowReturn ret)
+{
+  guint i;
 
-          track->n_descriptor = n_descriptor;
-          track->descriptor =
-              g_new0 (MXFMetadataFileDescriptor *, n_descriptor);
-          i = 0;
+  /* store the value */
+  pad->last_flow = ret;
 
-          for (k = 0; k < package->n_descriptors; k++) {
-            MXFMetadataGenericDescriptor *d = package->descriptors[k];
-            MXFMetadataFileDescriptor *e;
+  /* any other error that is not-linked can be returned right away */
+  if (ret != GST_FLOW_NOT_LINKED)
+    goto done;
 
-            if (!d || !d->is_file_descriptor)
-              continue;
+  /* only return NOT_LINKED if all other pads returned NOT_LINKED */
+  g_assert (demux->src->len != 0);
+  for (i = 0; i < demux->src->len; i++) {
+    GstMXFDemuxPad *opad = g_ptr_array_index (demux->src, i);
 
-            e = (MXFMetadataFileDescriptor *) d;
+    if (opad == NULL)
+      continue;
 
-            if (e->linked_track_id == track->track_id ||
-                (e->linked_track_id == 0 && n_descriptor == 1))
-              track->descriptor[i++] = e;
-          }
-        }
-      }
-    }
+    ret = opad->last_flow;
+    /* some other return value (must be SUCCESS but we can return
+     * other values as well) */
+    if (ret != GST_FLOW_NOT_LINKED)
+      goto done;
   }
+  /* if we get here, all other pads were unlinked and we return
+   * NOT_LINKED then */
+done:
+  GST_LOG_OBJECT (demux, "combined return %s", gst_flow_get_name (ret));
+  return ret;
+}
 
-  /* Tracks */
-  if (demux->track && demux->sequence) {
-    for (i = 0; i < demux->track->len; i++) {
-      MXFMetadataTrack *track =
-          &g_array_index (demux->track, MXFMetadataTrack, i);
-
-      for (j = 0; j < demux->sequence->len; j++) {
-        MXFMetadataSequence *sequence =
-            &g_array_index (demux->sequence, MXFMetadataSequence,
-            i);
+static GstFlowReturn
+gst_mxf_demux_pull_range (GstMXFDemux * demux, guint64 offset,
+    guint size, GstBuffer ** buffer)
+{
+  GstFlowReturn ret;
 
-        if (mxf_ul_is_equal (&track->sequence_uid, &sequence->instance_uid)) {
-          track->sequence = sequence;
-          break;
-        }
-      }
-    }
+  ret = gst_pad_pull_range (demux->sinkpad, offset, size, buffer);
+  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
+    GST_WARNING_OBJECT (demux,
+        "failed when pulling %u bytes from offset %" G_GUINT64_FORMAT ": %s",
+        size, offset, gst_flow_get_name (ret));
+    *buffer = NULL;
+    return ret;
   }
 
-  /* Sequences */
-  if (demux->sequence) {
-    for (i = 0; i < demux->sequence->len; i++) {
-      MXFMetadataSequence *sequence =
-          &g_array_index (demux->sequence, MXFMetadataSequence, i);
-
-      sequence->structural_components =
-          g_new0 (MXFMetadataStructuralComponent *,
-          sequence->n_structural_components);
+  if (G_UNLIKELY (*buffer && GST_BUFFER_SIZE (*buffer) != size)) {
+    GST_WARNING_OBJECT (demux,
+        "partial pull got %u when expecting %u from offset %" G_GUINT64_FORMAT,
+        GST_BUFFER_SIZE (*buffer), size, offset);
+    gst_buffer_unref (*buffer);
+    ret = GST_FLOW_UNEXPECTED;
+    *buffer = NULL;
+    return ret;
+  }
 
-      if (demux->structural_component) {
-        for (j = 0; j < sequence->n_structural_components; j++) {
-          for (k = 0; k < demux->structural_component->len; k++) {
-            MXFMetadataStructuralComponent *component =
-                &g_array_index (demux->structural_component,
-                MXFMetadataStructuralComponent, k);
+  return ret;
+}
 
-            if (mxf_ul_is_equal (&sequence->structural_components_uids[j],
-                    &component->instance_uid)) {
-              sequence->structural_components[j] = component;
-              break;
-            }
-          }
-        }
-      }
-    }
-  }
+static gboolean
+gst_mxf_demux_push_src_event (GstMXFDemux * demux, GstEvent * event)
+{
+  gboolean ret = TRUE;
+  guint i;
 
-  /* Source clips */
-  if (demux->structural_component && demux->source_package) {
-    for (i = 0; i < demux->structural_component->len; i++) {
-      MXFMetadataStructuralComponent *component =
-          &g_array_index (demux->structural_component,
-          MXFMetadataStructuralComponent, i);
+  GST_DEBUG_OBJECT (demux, "Pushing '%s' event downstream",
+      GST_EVENT_TYPE_NAME (event));
 
-      if (component->type != MXF_METADATA_SOURCE_CLIP
-          && component->type != MXF_METADATA_DM_SOURCE_CLIP)
-        continue;
+  if (!demux->src)
+    return ret;
 
-      for (j = 0; j < demux->source_package->len; j++) {
-        MXFMetadataGenericPackage *package =
-            &g_array_index (demux->source_package, MXFMetadataGenericPackage,
-            j);
+  for (i = 0; i < demux->src->len; i++) {
+    GstPad *pad = GST_PAD (g_ptr_array_index (demux->src, i));
 
-        if (component->type == MXF_METADATA_SOURCE_CLIP &&
-            mxf_umid_is_equal (&component->source_clip.source_package_id,
-                &package->package_uid)) {
-          component->source_clip.source_package = package;
-          break;
-        } else if (component->type == MXF_METADATA_DM_SOURCE_CLIP &&
-            mxf_umid_is_equal (&component->dm_source_clip.source_package_id,
-                &package->package_uid)) {
-          component->dm_source_clip.source_package = package;
-          break;
-        }
-      }
-    }
+    ret |= gst_pad_push_event (pad, gst_event_ref (event));
   }
 
-  /* Generic descriptors */
-  if (demux->descriptor) {
-    for (i = 0; i < demux->descriptor->len; i++) {
-      MXFMetadataGenericDescriptor *descriptor =
-          g_ptr_array_index (demux->descriptor, i);
-
-      descriptor->locators =
-          g_new0 (MXFMetadataLocator *, descriptor->n_locators);
+  gst_event_unref (event);
 
-      if (demux->locator) {
-        for (j = 0; j < descriptor->n_locators; j++) {
-          for (k = 0; k < demux->locator->len; k++) {
-            MXFMetadataLocator *locator =
-                &g_array_index (demux->locator, MXFMetadataLocator,
-                k);
+  return ret;
+}
 
-            if (mxf_ul_is_equal (&descriptor->locators_uids[j],
-                    &locator->instance_uid)) {
-              descriptor->locators[j] = locator;
-              break;
-            }
-          }
-        }
-      }
-    }
+static GstFlowReturn
+gst_mxf_demux_handle_partition_pack (GstMXFDemux * demux, const MXFUL * key,
+    GstBuffer * buffer)
+{
+  if (demux->partition.valid) {
+    mxf_partition_pack_reset (&demux->partition);
+    mxf_primer_pack_reset (&demux->primer);
   }
 
-  /* Mark packages as material, top-level source and source */
-  if (demux->material_package) {
-    for (i = 0; i < demux->material_package->len; i++) {
-      MXFMetadataGenericPackage *package =
-          &g_array_index (demux->material_package, MXFMetadataGenericPackage,
-          i);
+  GST_DEBUG_OBJECT (demux,
+      "Handling partition pack of size %u at offset %"
+      G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
 
-      package->type = MXF_METADATA_GENERIC_PACKAGE_MATERIAL;
+  if (!mxf_partition_pack_parse (key, &demux->partition,
+          GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
+    GST_ERROR_OBJECT (demux, "Parsing partition pack failed");
+    return GST_FLOW_ERROR;
+  }
 
-      for (j = 0; j < package->n_tracks; j++) {
-        MXFMetadataTrack *track = package->tracks[j];
-        MXFMetadataSequence *sequence;
+  if (demux->partition.type == MXF_PARTITION_PACK_HEADER)
+    demux->footer_partition_pack_offset = demux->partition.footer_partition;
 
-        if (!track || !track->sequence)
-          continue;
+  return GST_FLOW_OK;
+}
 
-        sequence = track->sequence;
+static GstFlowReturn
+gst_mxf_demux_handle_primer_pack (GstMXFDemux * demux, const MXFUL * key,
+    GstBuffer * buffer)
+{
+  GST_DEBUG_OBJECT (demux,
+      "Handling primer pack of size %u at offset %"
+      G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
 
-        for (k = 0; k < sequence->n_structural_components; k++) {
-          MXFMetadataStructuralComponent *component =
-              sequence->structural_components[k];
+  if (G_UNLIKELY (!demux->partition.valid)) {
+    GST_ERROR_OBJECT (demux, "Primer pack before partition pack");
+    return GST_FLOW_ERROR;
+  }
 
-          if (!component || component->type != MXF_METADATA_SOURCE_CLIP
-              || !component->source_clip.source_package)
-            continue;
+  if (G_UNLIKELY (demux->primer.valid)) {
+    GST_ERROR_OBJECT (demux, "Primer pack already exists");
+    return GST_FLOW_OK;
+  }
 
-          component->source_clip.source_package->type =
-              MXF_METADATA_GENERIC_PACKAGE_TOP_LEVEL_SOURCE;
-        }
-      }
-    }
+  if (!mxf_primer_pack_parse (key, &demux->primer,
+          GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
+    GST_ERROR_OBJECT (demux, "Parsing primer pack failed");
+    return GST_FLOW_ERROR;
   }
 
-  /* Store, for every package, the number of timestamp, metadata, essence and other tracks 
-   * and also store for every track the type */
-  if (demux->package) {
-    for (i = 0; i < demux->package->len; i++) {
-      MXFMetadataGenericPackage *package =
-          g_ptr_array_index (demux->package, i);
+  return GST_FLOW_OK;
+}
 
-      if (!package->tracks || package->n_tracks == 0)
-        continue;
+static GstFlowReturn
+gst_mxf_demux_handle_header_metadata_resolve_references (GstMXFDemux * demux)
+{
+  guint i;
+  GstFlowReturn ret = GST_FLOW_OK;
 
-      for (j = 0; j < package->n_tracks; j++) {
-        MXFMetadataTrack *track = package->tracks[j];
-        MXFMetadataSequence *sequence;
-        MXFMetadataTrackType type = MXF_METADATA_TRACK_UNKNOWN;
+  GST_DEBUG_OBJECT (demux, "Resolve metadata references");
+  demux->update_metadata = FALSE;
 
-        if (!track || !track->sequence)
-          continue;
+  if (!demux->metadata) {
+    GST_ERROR_OBJECT (demux, "No metadata yet");
+    return GST_FLOW_ERROR;
+  }
 
-        sequence = track->sequence;
+  /* Append NULL terminator */
+  g_ptr_array_add (demux->metadata, NULL);
 
-        if (mxf_ul_is_zero (&sequence->data_definition)
-            && sequence->structural_components) {
-          for (k = 0; k < sequence->n_structural_components; k++) {
-            MXFMetadataStructuralComponent *component =
-                sequence->structural_components[k];
-            if (!component || mxf_ul_is_zero (&component->data_definition))
-              continue;
+  for (i = 0; i < demux->metadata->len - 1; i++) {
+    MXFMetadataBase *m =
+        MXF_METADATA_BASE (g_ptr_array_index (demux->metadata, i));
+    gboolean resolved;
 
-            type =
-                mxf_metadata_track_identifier_parse
-                (&component->data_definition);
-            break;
-          }
-        } else {
-          type =
-              mxf_metadata_track_identifier_parse (&sequence->data_definition);
-        }
+    resolved =
+        mxf_metadata_resolve (m, (MXFMetadataBase **) demux->metadata->pdata);
 
-        track->type = type;
-
-        if (type == MXF_METADATA_TRACK_UNKNOWN)
-          continue;
-        else if ((type & 0xf0) == 0x10)
-          package->n_timecode_tracks++;
-        else if ((type & 0xf0) == 0x20)
-          package->n_metadata_tracks++;
-        else if ((type & 0xf0) == 0x30)
-          package->n_essence_tracks++;
-        else if ((type & 0xf0) == 0x40)
-          package->n_other_tracks++;
-      }
+    /* Resolving can fail for anything but the preface, as the preface
+     * will resolve everything required */
+    if (!resolved && MXF_IS_METADATA_PREFACE (m)) {
+      ret = GST_FLOW_ERROR;
+      goto error;
     }
   }
 
@@ -1679,9 +483,14 @@ gst_mxf_demux_find_package (GstMXFDemux * demux, const MXFUMID * umid)
   MXFMetadataGenericPackage *ret = NULL;
   guint i;
 
-  if (demux->package) {
-    for (i = 0; i < demux->package->len; i++) {
-      MXFMetadataGenericPackage *p = g_ptr_array_index (demux->package, i);
+  if (demux->preface->content_storage
+      && demux->preface->content_storage->packages) {
+    for (i = 0; i < demux->preface->content_storage->n_packages; i++) {
+      MXFMetadataGenericPackage *p =
+          demux->preface->content_storage->packages[i];
+
+      if (!p)
+        continue;
 
       if (mxf_umid_is_equal (&p->package_uid, umid)) {
         ret = p;
@@ -1697,6 +506,7 @@ static MXFMetadataGenericPackage *
 gst_mxf_demux_choose_package (GstMXFDemux * demux)
 {
   MXFMetadataGenericPackage *ret = NULL;
+  guint i;
 
   if (demux->requested_package_string) {
     MXFUMID umid;
@@ -1715,33 +525,42 @@ gst_mxf_demux_choose_package (GstMXFDemux * demux)
 
   if (!mxf_umid_is_zero (&demux->current_package_uid))
     ret = gst_mxf_demux_find_package (demux, &demux->current_package_uid);
-  if (ret && (ret->type == MXF_METADATA_GENERIC_PACKAGE_TOP_LEVEL_SOURCE
-          || ret->type == MXF_METADATA_GENERIC_PACKAGE_MATERIAL))
+  if (ret && (MXF_IS_METADATA_MATERIAL_PACKAGE (ret)
+          || (MXF_IS_METADATA_SOURCE_PACKAGE (ret)
+              && MXF_METADATA_SOURCE_PACKAGE (ret)->top_level)))
     return ret;
-  else if (ret && ret->type == MXF_METADATA_GENERIC_PACKAGE_SOURCE)
+  else if (ret)
     GST_WARNING_OBJECT (demux,
         "Current package is not a material package or top-level source package, choosing the first best");
   else if (!mxf_umid_is_zero (&demux->current_package_uid))
     GST_WARNING_OBJECT (demux,
         "Current package not found, choosing the first best");
 
-  if (demux->preface.primary_package)
-    ret = demux->preface.primary_package;
-  if (ret && (ret->type == MXF_METADATA_GENERIC_PACKAGE_TOP_LEVEL_SOURCE
-          || ret->type == MXF_METADATA_GENERIC_PACKAGE_MATERIAL))
+  if (demux->preface->primary_package)
+    ret = demux->preface->primary_package;
+  if (ret && (MXF_IS_METADATA_MATERIAL_PACKAGE (ret)
+          || (MXF_IS_METADATA_SOURCE_PACKAGE (ret)
+              && MXF_METADATA_SOURCE_PACKAGE (ret)->top_level)))
     return ret;
 
-  if (!demux->material_package) {
+  for (i = 0; i < demux->preface->content_storage->n_packages; i++) {
+    if (demux->preface->content_storage->packages[i] &&
+        MXF_IS_METADATA_MATERIAL_PACKAGE (demux->preface->content_storage->
+            packages[i])) {
+      ret =
+          MXF_METADATA_GENERIC_PACKAGE (demux->preface->content_storage->
+          packages[i]);
+      break;
+    }
+  }
+
+  if (!ret) {
     GST_ERROR_OBJECT (demux, "No material package");
     return NULL;
-  } else {
-    MXFMetadataGenericPackage *p =
-        (MXFMetadataGenericPackage *) demux->material_package->data;
-    memcpy (&demux->current_package_uid, &p->package_uid, 32);
-
-    ret = gst_mxf_demux_find_package (demux, &demux->current_package_uid);
   }
 
+  memcpy (&demux->current_package_uid, &ret->package_uid, 32);
+
   if (!ret)
     GST_ERROR_OBJECT (demux, "No suitable package found");
 
@@ -1774,67 +593,72 @@ gst_mxf_demux_handle_header_metadata_update_streams (GstMXFDemux * demux)
   demux->current_package = current_package;
 
   for (i = 0; i < current_package->n_tracks; i++) {
-    MXFMetadataTrack *track = current_package->tracks[i];
-    MXFMetadataTrackType track_type = MXF_METADATA_TRACK_UNKNOWN;
+    MXFMetadataTimelineTrack *track = NULL;
     MXFMetadataSequence *sequence;
     MXFMetadataStructuralComponent *component = NULL;
-    MXFMetadataGenericPackage *source_package = NULL;
-    MXFMetadataTrack *source_track = NULL;
+    MXFMetadataSourcePackage *source_package = NULL;
+    MXFMetadataTimelineTrack *source_track = NULL;
     GstMXFDemuxPad *pad = NULL;
     GstCaps *caps = NULL;
 
     GST_DEBUG_OBJECT (demux, "Handling track %u", i);
 
-    if (!track) {
+    if (!current_package->tracks[i]) {
       GST_WARNING_OBJECT (demux, "Unresolved track");
       continue;
-    } else if (!track->sequence) {
+    }
+
+    if (!MXF_IS_METADATA_TIMELINE_TRACK (current_package->tracks[i])) {
+      GST_DEBUG_OBJECT (demux, "No timeline track");
+      continue;
+    }
+
+    track = MXF_METADATA_TIMELINE_TRACK (current_package->tracks[i]);
+
+    if (!track->parent.sequence) {
       GST_WARNING_OBJECT (demux, "Track with no sequence");
       continue;
     }
 
-    sequence = track->sequence;
+    sequence = track->parent.sequence;
 
-    if (current_package->type == MXF_METADATA_GENERIC_PACKAGE_TOP_LEVEL_SOURCE) {
-      source_package = current_package;
+    if (MXF_IS_METADATA_SOURCE_PACKAGE (current_package)) {
+      source_package = MXF_METADATA_SOURCE_PACKAGE (current_package);
       source_track = track;
     }
 
-    track_type =
-        mxf_metadata_track_identifier_parse (&sequence->data_definition);
-
     /* TODO: handle multiple components, see SMPTE 377M page 37 */
     if (sequence->structural_components && sequence->structural_components[0]) {
       component = sequence->structural_components[0];
 
-      if (track_type == MXF_METADATA_TRACK_UNKNOWN)
-        track_type =
-            mxf_metadata_track_identifier_parse (&component->data_definition);
+      if (!source_package && MXF_IS_METADATA_SOURCE_CLIP (component)) {
+        MXFMetadataSourceClip *clip = MXF_METADATA_SOURCE_CLIP (component);
 
-      if (!source_package && component->type == MXF_METADATA_SOURCE_CLIP
-          && component->source_clip.source_package
-          && component->source_clip.source_package->type ==
-          MXF_METADATA_GENERIC_PACKAGE_TOP_LEVEL_SOURCE
-          && component->source_clip.source_package->tracks) {
-        source_package = component->source_clip.source_package;
+        if (clip->source_package && clip->source_package->top_level &&
+            MXF_METADATA_GENERIC_PACKAGE (clip->source_package)->tracks) {
+          MXFMetadataGenericPackage *tmp_pkg =
+              MXF_METADATA_GENERIC_PACKAGE (clip->source_package);
 
-        for (k = 0; k < source_package->n_tracks; k++) {
-          MXFMetadataTrack *tmp = source_package->tracks[k];
+          source_package = clip->source_package;
 
-          if (tmp->track_id == component->source_clip.source_track_id) {
-            source_track = tmp;
-            break;
+          for (k = 0; k < tmp_pkg->n_tracks; k++) {
+            MXFMetadataTrack *tmp = tmp_pkg->tracks[k];
+
+            if (tmp->track_id == clip->source_track_id) {
+              source_track = MXF_METADATA_TIMELINE_TRACK (tmp);
+              break;
+            }
           }
         }
       }
     }
 
-    if (track_type && (track_type & 0xf0) != 0x30) {
+    if (track->parent.type && (track->parent.type & 0xf0) != 0x30) {
       GST_DEBUG_OBJECT (demux, "No essence track");
       continue;
     }
 
-    if (!source_package || track_type == MXF_METADATA_TRACK_UNKNOWN
+    if (!source_package || track->parent.type == MXF_METADATA_TRACK_UNKNOWN
         || !source_track || !component) {
       GST_WARNING_OBJECT (demux,
           "No source package or track type for track found");
@@ -1846,7 +670,7 @@ gst_mxf_demux_handle_header_metadata_update_streams (GstMXFDemux * demux)
       continue;
     }
 
-    if (!source_track->descriptor) {
+    if (!source_track->parent.descriptor) {
       GST_WARNING_OBJECT (demux, "No descriptor found for track");
       continue;
     }
@@ -1856,7 +680,7 @@ gst_mxf_demux_handle_header_metadata_update_streams (GstMXFDemux * demux)
       for (j = 0; j < demux->src->len; j++) {
         GstMXFDemuxPad *tmp = g_ptr_array_index (demux->src, j);
 
-        if (tmp->track_id == track->track_id) {
+        if (tmp->track_id == track->parent.track_id) {
           pad = tmp;
           break;
         }
@@ -1870,7 +694,7 @@ gst_mxf_demux_handle_header_metadata_update_streams (GstMXFDemux * demux)
       templ =
           gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (demux),
           "track_%u");
-      pad_name = g_strdup_printf ("track_%u", track->track_id);
+      pad_name = g_strdup_printf ("track_%u", track->parent.track_id);
 
       g_assert (templ != NULL);
 
@@ -1888,8 +712,7 @@ gst_mxf_demux_handle_header_metadata_update_streams (GstMXFDemux * demux)
     }
 
     /* Update pad */
-    pad->track_id = track->track_id;
-    pad->track_type = track_type;
+    pad->track_id = track->parent.track_id;
 
     pad->material_package = current_package;
     pad->material_track = track;
@@ -1903,64 +726,80 @@ gst_mxf_demux_handle_header_metadata_update_streams (GstMXFDemux * demux)
     g_free (pad->mapping_data);
     pad->mapping_data = NULL;
 
-    switch (track_type) {
+    switch (track->parent.type) {
       case MXF_METADATA_TRACK_PICTURE_ESSENCE:
-        if (mxf_is_mpeg_essence_track (source_track))
+        if (mxf_is_mpeg_essence_track ((MXFMetadataTrack *) source_track))
           caps =
-              mxf_mpeg_create_caps (source_package, source_track,
-              &pad->tags, &pad->handle_essence_element, &pad->mapping_data);
-        else if (mxf_is_dv_dif_essence_track (source_track))
+              mxf_mpeg_create_caps (MXF_METADATA_GENERIC_PACKAGE
+              (source_package), (MXFMetadataTrack *) source_track, &pad->tags,
+              &pad->handle_essence_element, &pad->mapping_data);
+        else if (mxf_is_dv_dif_essence_track ((MXFMetadataTrack *)
+                source_track))
           caps =
-              mxf_dv_dif_create_caps (source_package, source_track,
-              &pad->tags, &pad->handle_essence_element, &pad->mapping_data);
-        else if (mxf_is_jpeg2000_essence_track (source_track))
+              mxf_dv_dif_create_caps (MXF_METADATA_GENERIC_PACKAGE
+              (source_package), (MXFMetadataTrack *) source_track, &pad->tags,
+              &pad->handle_essence_element, &pad->mapping_data);
+        else if (mxf_is_jpeg2000_essence_track ((MXFMetadataTrack *)
+                source_track))
           caps =
-              mxf_jpeg2000_create_caps (source_package, source_track,
-              &pad->tags, &pad->handle_essence_element, &pad->mapping_data);
-        else if (mxf_is_d10_essence_track (source_track))
+              mxf_jpeg2000_create_caps (MXF_METADATA_GENERIC_PACKAGE
+              (source_package), (MXFMetadataTrack *) source_track, &pad->tags,
+              &pad->handle_essence_element, &pad->mapping_data);
+        else if (mxf_is_d10_essence_track ((MXFMetadataTrack *) source_track))
           caps =
-              mxf_d10_create_caps (source_package, source_track,
-              &pad->tags, &pad->handle_essence_element, &pad->mapping_data);
-        else if (mxf_is_up_essence_track (source_track))
+              mxf_d10_create_caps (MXF_METADATA_GENERIC_PACKAGE
+              (source_package), (MXFMetadataTrack *) source_track, &pad->tags,
+              &pad->handle_essence_element, &pad->mapping_data);
+        else if (mxf_is_up_essence_track ((MXFMetadataTrack *) source_track))
           caps =
-              mxf_up_create_caps (source_package, source_track,
-              &pad->tags, &pad->handle_essence_element, &pad->mapping_data);
+              mxf_up_create_caps (MXF_METADATA_GENERIC_PACKAGE (source_package),
+              (MXFMetadataTrack *) source_track, &pad->tags,
+              &pad->handle_essence_element, &pad->mapping_data);
         break;
       case MXF_METADATA_TRACK_SOUND_ESSENCE:
-        if (mxf_is_aes_bwf_essence_track (source_track))
+        if (mxf_is_aes_bwf_essence_track ((MXFMetadataTrack *) source_track))
           caps =
-              mxf_aes_bwf_create_caps (source_package, source_track, &pad->tags,
+              mxf_aes_bwf_create_caps (MXF_METADATA_GENERIC_PACKAGE
+              (source_package), (MXFMetadataTrack *) source_track, &pad->tags,
               &pad->handle_essence_element, &pad->mapping_data);
-        else if (mxf_is_dv_dif_essence_track (source_track))
+        else if (mxf_is_dv_dif_essence_track ((MXFMetadataTrack *)
+                source_track))
           caps =
-              mxf_dv_dif_create_caps (source_package, source_track,
-              &pad->tags, &pad->handle_essence_element, &pad->mapping_data);
-        else if (mxf_is_alaw_essence_track (source_track))
+              mxf_dv_dif_create_caps (MXF_METADATA_GENERIC_PACKAGE
+              (source_package), (MXFMetadataTrack *) source_track, &pad->tags,
+              &pad->handle_essence_element, &pad->mapping_data);
+        else if (mxf_is_alaw_essence_track ((MXFMetadataTrack *) source_track))
           caps =
-              mxf_alaw_create_caps (source_package, source_track,
-              &pad->tags, &pad->handle_essence_element, &pad->mapping_data);
-        else if (mxf_is_mpeg_essence_track (source_track))
+              mxf_alaw_create_caps (MXF_METADATA_GENERIC_PACKAGE
+              (source_package), (MXFMetadataTrack *) source_track, &pad->tags,
+              &pad->handle_essence_element, &pad->mapping_data);
+        else if (mxf_is_mpeg_essence_track ((MXFMetadataTrack *) source_track))
           caps =
-              mxf_mpeg_create_caps (source_package, source_track,
-              &pad->tags, &pad->handle_essence_element, &pad->mapping_data);
-        else if (mxf_is_d10_essence_track (source_track))
+              mxf_mpeg_create_caps (MXF_METADATA_GENERIC_PACKAGE
+              (source_package), (MXFMetadataTrack *) source_track, &pad->tags,
+              &pad->handle_essence_element, &pad->mapping_data);
+        else if (mxf_is_d10_essence_track ((MXFMetadataTrack *) source_track))
           caps =
-              mxf_d10_create_caps (source_package, source_track,
-              &pad->tags, &pad->handle_essence_element, &pad->mapping_data);
+              mxf_d10_create_caps (MXF_METADATA_GENERIC_PACKAGE
+              (source_package), (MXFMetadataTrack *) source_track, &pad->tags,
+              &pad->handle_essence_element, &pad->mapping_data);
         break;
       case MXF_METADATA_TRACK_DATA_ESSENCE:
-        if (mxf_is_dv_dif_essence_track (source_track))
+        if (mxf_is_dv_dif_essence_track ((MXFMetadataTrack *) source_track))
           caps =
-              mxf_dv_dif_create_caps (source_package, source_track,
-              &pad->tags, &pad->handle_essence_element, &pad->mapping_data);
-        else if (mxf_is_mpeg_essence_track (source_track))
+              mxf_dv_dif_create_caps (MXF_METADATA_GENERIC_PACKAGE
+              (source_package), (MXFMetadataTrack *) source_track, &pad->tags,
+              &pad->handle_essence_element, &pad->mapping_data);
+        else if (mxf_is_mpeg_essence_track ((MXFMetadataTrack *) source_track))
           caps =
-              mxf_mpeg_create_caps (source_package, source_track,
-              &pad->tags, &pad->handle_essence_element, &pad->mapping_data);
-        else if (mxf_is_d10_essence_track (source_track))
+              mxf_mpeg_create_caps (MXF_METADATA_GENERIC_PACKAGE
+              (source_package), (MXFMetadataTrack *) source_track, &pad->tags,
+              &pad->handle_essence_element, &pad->mapping_data);
+        else if (mxf_is_d10_essence_track ((MXFMetadataTrack *) source_track))
           caps =
-              mxf_d10_create_caps (source_package, source_track,
-              &pad->tags, &pad->handle_essence_element, &pad->mapping_data);
+              mxf_d10_create_caps (MXF_METADATA_GENERIC_PACKAGE
+              (source_package), (MXFMetadataTrack *) source_track, &pad->tags,
+              &pad->handle_essence_element, &pad->mapping_data);
         break;
       default:
         g_assert_not_reached ();
@@ -2012,6 +851,7 @@ gst_mxf_demux_handle_metadata (GstMXFDemux * demux, const MXFUL * key,
     GstBuffer * buffer)
 {
   guint16 type;
+  MXFMetadata *metadata = NULL;
   GstFlowReturn ret = GST_FLOW_OK;
 
   type = GST_READ_UINT16_BE (key->u + 13);
@@ -2031,109 +871,46 @@ gst_mxf_demux_handle_metadata (GstMXFDemux * demux, const MXFUL * key,
     return GST_FLOW_ERROR;
   }
 
-  if (type != MXF_METADATA_PREFACE && !demux->update_metadata) {
+  metadata =
+      mxf_metadata_new (type, &demux->primer, GST_BUFFER_DATA (buffer),
+      GST_BUFFER_SIZE (buffer));
+
+  if (metadata && !MXF_IS_METADATA_PREFACE (metadata)
+      && !demux->update_metadata) {
     GST_DEBUG_OBJECT (demux,
         "Skipping parsing of metadata because it's older than what we have");
+    gst_mini_object_unref ((GstMiniObject *) metadata);
     return GST_FLOW_OK;
   }
 
-  switch (type) {
-    case MXF_METADATA_PREFACE:
-      ret = gst_mxf_demux_handle_metadata_preface (demux, key, buffer);
-      break;
-    case MXF_METADATA_IDENTIFICATION:
-      ret = gst_mxf_demux_handle_metadata_identification (demux, key, buffer);
-      break;
-    case MXF_METADATA_CONTENT_STORAGE:
-      ret = gst_mxf_demux_handle_metadata_content_storage (demux, key, buffer);
-      break;
-    case MXF_METADATA_ESSENCE_CONTAINER_DATA:
-      ret =
-          gst_mxf_demux_handle_metadata_essence_container_data (demux,
-          key, buffer);
-      break;
-    case MXF_METADATA_MATERIAL_PACKAGE:
-      ret = gst_mxf_demux_handle_metadata_material_package (demux, key, buffer);
-      break;
-    case MXF_METADATA_SOURCE_PACKAGE:
-      ret = gst_mxf_demux_handle_metadata_source_package (demux, key, buffer);
-      break;
-    case MXF_METADATA_TRACK:
-    case MXF_METADATA_EVENT_TRACK:
-    case MXF_METADATA_STATIC_TRACK:
-      ret = gst_mxf_demux_handle_metadata_track (demux, key, type, buffer);
-      break;
-    case MXF_METADATA_SEQUENCE:
-      ret = gst_mxf_demux_handle_metadata_sequence (demux, key, buffer);
-      break;
-    case MXF_METADATA_TIMECODE_COMPONENT:
-    case MXF_METADATA_SOURCE_CLIP:
-    case MXF_METADATA_DM_SEGMENT:
-    case MXF_METADATA_DM_SOURCE_CLIP:
-      ret =
-          gst_mxf_demux_handle_metadata_structural_component (demux,
-          key, type, buffer);
-      break;
-    case MXF_METADATA_FILE_DESCRIPTOR:
-      ret =
-          gst_mxf_demux_handle_metadata_file_descriptor (demux,
-          key, type, buffer);
-      break;
-    case MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR:
-      ret =
-          gst_mxf_demux_handle_metadata_generic_data_essence_descriptor
-          (demux, key, type, buffer);
-      break;
-    case MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR:
-      ret =
-          gst_mxf_demux_handle_metadata_generic_picture_essence_descriptor
-          (demux, key, type, buffer);
-      break;
-    case MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR:
-      ret =
-          gst_mxf_demux_handle_metadata_cdci_picture_essence_descriptor (demux,
-          key, type, buffer);
-      break;
-    case MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR:
-      ret =
-          gst_mxf_demux_handle_metadata_rgba_picture_essence_descriptor (demux,
-          key, type, buffer);
-      break;
-    case MXF_METADATA_MPEG_VIDEO_DESCRIPTOR:
-      ret =
-          gst_mxf_demux_handle_metadata_mpeg_video_descriptor (demux,
-          key, type, buffer);
-      break;
-    case MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR:
-      ret =
-          gst_mxf_demux_handle_metadata_generic_sound_essence_descriptor (demux,
-          key, type, buffer);
-      break;
-    case MXF_METADATA_MULTIPLE_DESCRIPTOR:
-      ret =
-          gst_mxf_demux_handle_metadata_multiple_descriptor (demux,
-          key, type, buffer);
-      break;
-    case MXF_METADATA_WAVE_AUDIO_ESSENCE_DESCRIPTOR:
-      ret =
-          gst_mxf_demux_handle_metadata_wave_audio_essence_descriptor (demux,
-          key, type, buffer);
-      break;
-    case MXF_METADATA_AES3_AUDIO_ESSENCE_DESCRIPTOR:
-      ret =
-          gst_mxf_demux_handle_metadata_aes3_audio_essence_descriptor (demux,
-          key, type, buffer);
-      break;
-    case MXF_METADATA_NETWORK_LOCATOR:
-    case MXF_METADATA_TEXT_LOCATOR:
-      ret = gst_mxf_demux_handle_metadata_locator (demux, key, type, buffer);
-      break;
-    default:
-      GST_WARNING_OBJECT (demux,
-          "Unknown or unhandled metadata type 0x%04x", type);
-      break;
+  if (!metadata) {
+    GST_ERROR_OBJECT (demux, "Parsing metadata failed");
+    return GST_FLOW_ERROR;
+  }
+
+  if (MXF_IS_METADATA_PREFACE (metadata)) {
+    MXFMetadataPreface *preface = MXF_METADATA_PREFACE (metadata);
+
+    if (!demux->preface
+        || (!mxf_timestamp_is_unknown (&preface->last_modified_date)
+            && mxf_timestamp_compare (&demux->preface->last_modified_date,
+                &preface->last_modified_date) < 0)) {
+      GST_DEBUG_OBJECT (demux,
+          "Timestamp of new preface is newer than old, updating metadata");
+      gst_mxf_demux_reset_metadata (demux);
+      demux->preface = preface;
+    } else {
+      GST_DEBUG_OBJECT (demux, "Preface is older than already parsed preface");
+      gst_mini_object_unref ((GstMiniObject *) metadata);
+      return GST_FLOW_OK;
+    }
   }
 
+  if (!demux->metadata)
+    demux->metadata = g_ptr_array_new ();
+
+  g_ptr_array_add (demux->metadata, metadata);
+
   return ret;
 }
 
@@ -2231,18 +1008,19 @@ gst_mxf_demux_handle_generic_container_essence_element (GstMXFDemux * demux,
 
   for (i = 0; i < demux->src->len; i++) {
     GstMXFDemuxPad *p = g_ptr_array_index (demux->src, i);
+    MXFMetadataContentStorage *content_storage =
+        demux->preface->content_storage;
 
-    if (p->source_track->track_number == track_number ||
-        (p->source_track->track_number == 0 &&
+    if (p->source_track->parent.track_number == track_number ||
+        (p->source_track->parent.track_number == 0 &&
             demux->src->len == 1 &&
             demux->current_package->n_essence_tracks == 1)) {
-      if (demux->essence_container_data) {
-        for (j = 0; j < demux->essence_container_data->len; j++) {
+      if (content_storage->essence_container_data) {
+        for (j = 0; j < content_storage->n_essence_container_data; j++) {
           MXFMetadataEssenceContainerData *edata =
-              &g_array_index (demux->essence_container_data,
-              MXFMetadataEssenceContainerData, j);
+              content_storage->essence_container_data[j];
 
-          if (p->source_package == edata->linked_package
+          if (edata && p->source_package == edata->linked_package
               && demux->partition.body_sid == edata->body_sid) {
             pad = p;
             break;
@@ -2292,8 +1070,10 @@ gst_mxf_demux_handle_generic_container_essence_element (GstMXFDemux * demux,
   if (pad->handle_essence_element) {
     /* Takes ownership of inbuf */
     ret =
-        pad->handle_essence_element (key, inbuf, pad->caps, pad->source_package,
-        pad->source_track, pad->component, pad->mapping_data, &outbuf);
+        pad->handle_essence_element (key, inbuf, pad->caps,
+        (MXFMetadataGenericPackage *) pad->source_package,
+        (MXFMetadataTrack *) pad->source_track, pad->component,
+        pad->mapping_data, &outbuf);
     inbuf = NULL;
   } else {
     outbuf = inbuf;
@@ -2316,14 +1096,14 @@ gst_mxf_demux_handle_generic_container_essence_element (GstMXFDemux * demux,
     GST_DEBUG_OBJECT (demux,
         "Pushing buffer of size %u for track %u: timestamp %" GST_TIME_FORMAT
         " duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (outbuf),
-        pad->material_track->track_id,
+        pad->material_track->parent.track_id,
         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
         GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
     ret = gst_pad_push (GST_PAD_CAST (pad), outbuf);
     ret = gst_mxf_demux_combine_flows (demux, pad, ret);
   } else {
     GST_DEBUG_OBJECT (demux, "Dropping buffer for track %u",
-        pad->material_track->track_id);
+        pad->material_track->parent.track_id);
   }
 
   return ret;
@@ -2685,7 +1465,7 @@ gst_mxf_demux_handle_klv_packet (GstMXFDemux * demux, const MXFUL * key,
   GstFlowReturn ret = GST_FLOW_OK;
 
   if (demux->update_metadata
-      && !mxf_timestamp_is_unknown (&demux->preface.last_modified_date)
+      && demux->preface
       && !mxf_is_metadata (key) && !mxf_is_descriptive_metadata (key)
       && !mxf_is_fill (key)) {
     if ((ret =
@@ -3112,10 +1892,10 @@ gst_mxf_demux_src_query (GstPad * pad, GstQuery * query)
       if (format != GST_FORMAT_TIME && format != GST_FORMAT_DEFAULT)
         goto error;
 
-      if (!mxfpad->material_track || !mxfpad->material_track->sequence)
+      if (!mxfpad->material_track || !mxfpad->material_track->parent.sequence)
         goto error;
 
-      duration = mxfpad->material_track->sequence->duration;
+      duration = mxfpad->material_track->parent.sequence->duration;
       if (format == GST_FORMAT_TIME) {
         if (mxfpad->material_track->edit_rate.n == 0 ||
             mxfpad->material_track->edit_rate.d == 0)
index 82b82c2..bb9d593 100644 (file)
@@ -23,7 +23,9 @@
 #include <gst/gst.h>
 #include <gst/base/gstadapter.h>
 
+#include "mxftypes.h"
 #include "mxfparse.h"
+#include "mxfmetadata.h"
 
 G_BEGIN_DECLS
 #define GST_TYPE_MXF_DEMUX \
@@ -75,31 +77,9 @@ struct _GstMXFDemux
   gboolean pull_footer_metadata;
 
   gboolean metadata_resolved;
-  MXFMetadataPreface preface;
-  GArray *identification;
-  MXFMetadataContentStorage content_storage;
-  GArray *essence_container_data;
-  GArray *material_package;
-  GArray *source_package;
-  GPtrArray *package;
-  GArray *track;
-  GArray *sequence;
-  GArray *structural_component;
-  GArray *locator;
-
-  GPtrArray *descriptor;
-  GArray *generic_descriptor;
-  GArray *file_descriptor;
-  GArray *generic_sound_essence_descriptor;
-  GArray *generic_picture_essence_descriptor;
-  GArray *generic_data_essence_descriptor;
-  GArray *cdci_picture_essence_descriptor;
-  GArray *rgba_picture_essence_descriptor;
-  GArray *mpeg_video_descriptor;
-  GArray *wave_audio_essence_descriptor;
-  GArray *aes3_audio_essence_descriptor;
-  GArray *multiple_descriptor;
-  
+  MXFMetadataPreface *preface;
+  GPtrArray *metadata;
+
   MXFUMID current_package_uid;
   MXFMetadataGenericPackage *current_package;
   gchar *current_package_string;
index 79512f4..25bd2a9 100644 (file)
@@ -51,7 +51,12 @@ mxf_is_dv_dif_essence_track (const MXFMetadataTrack * track)
 
   for (i = 0; i < track->n_descriptor; i++) {
     MXFMetadataFileDescriptor *d = track->descriptor[i];
-    MXFUL *key = &d->essence_container;
+    MXFUL *key;
+
+    if (!d)
+      continue;
+
+    key = &d->essence_container;
     /* SMPTE 383M 8 */
     if (mxf_is_generic_container_essence_container_label (key) &&
         key->u[12] == 0x02 && key->u[13] == 0x02)
@@ -97,10 +102,11 @@ mxf_dv_dif_create_caps (MXFMetadataGenericPackage * package,
   }
 
   for (i = 0; i < track->n_descriptor; i++) {
-    if (((MXFMetadataGenericDescriptor *) track->descriptor[i])->
-        is_file_descriptor
-        && ((MXFMetadataGenericDescriptor *) track->descriptor[i])->type !=
-        MXF_METADATA_MULTIPLE_DESCRIPTOR) {
+    if (!track->descriptor[i])
+      continue;
+
+    if (MXF_IS_METADATA_FILE_DESCRIPTOR (track->descriptor[i]) &&
+        !MXF_IS_METADATA_MULTIPLE_DESCRIPTOR (track->descriptor[i])) {
       f = track->descriptor[i];
     }
   }
@@ -131,3 +137,9 @@ mxf_dv_dif_create_caps (MXFMetadataGenericPackage * package,
 
   return caps;
 }
+
+void
+mxf_dv_dif_init (void)
+{
+
+}
index a4d39f0..2e59e5e 100644 (file)
@@ -33,4 +33,6 @@ gboolean mxf_is_dv_dif_essence_track (const MXFMetadataTrack *track);
 GstCaps *
 mxf_dv_dif_create_caps (MXFMetadataGenericPackage *package, MXFMetadataTrack *track, GstTagList **tags, MXFEssenceElementHandler *handler, gpointer *mapping_data);
 
+void mxf_dv_dif_init (void);
+
 #endif /* __MXF_DV_DIF_H__ */
index 7ccb481..818f6b2 100644 (file)
@@ -50,7 +50,12 @@ mxf_is_jpeg2000_essence_track (const MXFMetadataTrack * track)
 
   for (i = 0; i < track->n_descriptor; i++) {
     MXFMetadataFileDescriptor *d = track->descriptor[i];
-    MXFUL *key = &d->essence_container;
+    MXFUL *key;
+
+    if (!d)
+      continue;
+
+    key = &d->essence_container;
     /* SMPTE 422M 5.4 */
     if (mxf_is_generic_container_essence_container_label (key) &&
         key->u[12] == 0x02 && key->u[13] == 0x0c &&
@@ -99,19 +104,16 @@ mxf_jpeg2000_create_caps (MXFMetadataGenericPackage * package,
   }
 
   for (i = 0; i < track->n_descriptor; i++) {
-    if (((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR ||
-        ((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR ||
-        ((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR) {
+    if (!track->descriptor[i])
+      continue;
+
+    if (MXF_IS_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (track->
+            descriptor[i])) {
       p = (MXFMetadataGenericPictureEssenceDescriptor *) track->descriptor[i];
       f = track->descriptor[i];
       break;
-    } else if (((MXFMetadataGenericDescriptor *) track->descriptor[i])->
-        is_file_descriptor
-        && ((MXFMetadataGenericDescriptor *) track->descriptor[i])->type !=
-        MXF_METADATA_MULTIPLE_DESCRIPTOR) {
+    } else if (MXF_IS_METADATA_FILE_DESCRIPTOR (track->descriptor[i]) &&
+        !MXF_IS_METADATA_MULTIPLE_DESCRIPTOR (track->descriptor[i])) {
       f = track->descriptor[i];
     }
   }
@@ -122,13 +124,9 @@ mxf_jpeg2000_create_caps (MXFMetadataGenericPackage * package,
   }
 
   fourcc = GST_MAKE_FOURCC ('s', 'R', 'G', 'B');
-  if (p
-      && ((MXFMetadataGenericDescriptor *) p)->type ==
-      MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR) {
+  if (p && MXF_IS_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR (p)) {
     fourcc = GST_MAKE_FOURCC ('s', 'Y', 'U', 'V');
-  } else if (p
-      && ((MXFMetadataGenericDescriptor *) p)->type ==
-      MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR) {
+  } else if (p && MXF_IS_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (p)) {
     MXFMetadataRGBAPictureEssenceDescriptor *r =
         (MXFMetadataRGBAPictureEssenceDescriptor *) p;
     gboolean rgb = TRUE;
@@ -199,3 +197,8 @@ mxf_jpeg2000_create_caps (MXFMetadataGenericPackage * package,
 
   return caps;
 }
+
+void
+mxf_jpeg2000_init (void)
+{
+}
index 784c19e..d3cda75 100644 (file)
@@ -33,4 +33,6 @@ gboolean mxf_is_jpeg2000_essence_track (const MXFMetadataTrack *track);
 GstCaps *
 mxf_jpeg2000_create_caps (MXFMetadataGenericPackage *package, MXFMetadataTrack *track, GstTagList **tags, MXFEssenceElementHandler *handler, gpointer *mapping_data);
 
+void mxf_jpeg2000_init (void);
+
 #endif /* __MXF_JPEG2000_H__ */
diff --git a/gst/mxf/mxfmetadata.c b/gst/mxf/mxfmetadata.c
new file mode 100644 (file)
index 0000000..54df52d
--- /dev/null
@@ -0,0 +1,3306 @@
+/* GStreamer
+ * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <string.h>
+
+#include "mxfparse.h"
+#include "mxfmetadata.h"
+
+GST_DEBUG_CATEGORY_EXTERN (mxf_debug);
+#define GST_CAT_DEFAULT mxf_debug
+
+G_DEFINE_ABSTRACT_TYPE (MXFMetadataBase, mxf_metadata_base,
+    GST_TYPE_MINI_OBJECT);
+
+static void
+mxf_metadata_base_finalize (GstMiniObject * object)
+{
+  MXFMetadataBase *self = MXF_METADATA_BASE (object);
+
+  if (self->other_tags) {
+    g_hash_table_destroy (self->other_tags);
+    self->other_tags = NULL;
+  }
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_base_parent_class)->finalize (object);
+}
+
+static gboolean
+mxf_metadata_base_handle_tag (MXFMetadataBase * self, MXFPrimerPack * primer,
+    guint16 tag, const guint8 * tag_data, guint tag_size)
+{
+  return (mxf_local_tag_add_to_hash_table (primer, tag, tag_data, tag_size,
+          &self->other_tags));
+}
+
+static gboolean
+mxf_metadata_base_resolve (MXFMetadataBase * self, MXFMetadataBase ** metadata)
+{
+  return TRUE;
+}
+
+static void
+mxf_metadata_base_init (MXFMetadataBase * self)
+{
+
+}
+
+static void
+mxf_metadata_base_class_init (MXFMetadataBaseClass * klass)
+{
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_base_finalize;
+  klass->handle_tag = mxf_metadata_base_handle_tag;
+  klass->resolve = mxf_metadata_base_resolve;
+}
+
+gboolean
+mxf_metadata_parse (MXFMetadataBase * self, MXFPrimerPack * primer,
+    const guint8 * data, guint size)
+{
+  guint16 tag, tag_size;
+  const guint8 *tag_data;
+
+  g_return_val_if_fail (MXF_IS_METADATA_BASE (self), FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+  g_return_val_if_fail (primer != NULL, FALSE);
+
+  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+    if (tag_size == 0 || tag == 0x0000)
+      goto next;
+
+    if (!MXF_METADATA_BASE_GET_CLASS (self)->handle_tag (self, primer, tag,
+            tag_data, tag_size))
+      return FALSE;
+  next:
+    data += 4 + tag_size;
+    size -= 4 + tag_size;
+  }
+
+  return TRUE;
+}
+
+gboolean
+mxf_metadata_resolve (MXFMetadataBase * self, MXFMetadataBase ** metadata)
+{
+  MXFMetadataBaseClass *klass;
+
+  g_return_val_if_fail (MXF_IS_METADATA_BASE (self), FALSE);
+  g_return_val_if_fail (metadata != NULL, FALSE);
+
+  if (self->resolved)
+    return TRUE;
+
+  self->resolved = TRUE;
+
+  klass = MXF_METADATA_BASE_GET_CLASS (self);
+
+  if (klass->resolve)
+    return klass->resolve (self, metadata);
+
+  return TRUE;
+}
+
+G_DEFINE_TYPE (MXFMetadata, mxf_metadata, MXF_TYPE_METADATA_BASE);
+
+static gboolean
+mxf_metadata_handle_tag (MXFMetadataBase * metadata, MXFPrimerPack * primer,
+    guint16 tag, const guint8 * tag_data, guint tag_size)
+{
+  gchar str[48];
+  MXFMetadata *self = MXF_METADATA (metadata);
+  gboolean ret = TRUE;
+
+  switch (tag) {
+    case 0x3c0a:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->parent.instance_uid, tag_data, 16);
+      GST_DEBUG ("  instance uid = %s",
+          mxf_ul_to_string (&self->parent.instance_uid, str));
+      break;
+    case 0x0102:
+    case 0x3c09:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->parent.generation_uid, tag_data, 16);
+      GST_DEBUG ("  generation uid = %s",
+          mxf_ul_to_string (&self->parent.generation_uid, str));
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS (mxf_metadata_parent_class)->
+          handle_tag (metadata, primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid metadata local tag 0x%04x of size %u", tag, tag_size);
+
+  return FALSE;
+}
+
+static void
+mxf_metadata_class_init (MXFMetadataClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+
+  metadata_base_class->handle_tag = mxf_metadata_handle_tag;
+}
+
+static void
+mxf_metadata_init (MXFMetadata * self)
+{
+}
+
+static GSList *_mxf_metadata_registry = NULL;
+
+typedef struct
+{
+  guint16 type_id;
+  GType type;
+} _MXFMetadataType;
+
+void
+mxf_metadata_init_types (void)
+{
+  _MXFMetadataType *l;
+
+  g_return_if_fail (_mxf_metadata_registry == NULL);
+
+#define _add_type(TI, T) \
+    l = g_slice_new (_MXFMetadataType); \
+    l->type_id = TI; \
+    l->type = T; \
+    _mxf_metadata_registry = g_slist_prepend (_mxf_metadata_registry, l);
+
+  /* SMPTE S377M 8.6 Table 14 */
+  _add_type (0x012f, MXF_TYPE_METADATA_PREFACE);
+  _add_type (0x0130, MXF_TYPE_METADATA_IDENTIFICATION);
+  _add_type (0x0118, MXF_TYPE_METADATA_CONTENT_STORAGE);
+  _add_type (0x0123, MXF_TYPE_METADATA_ESSENCE_CONTAINER_DATA);
+  _add_type (0x0136, MXF_TYPE_METADATA_MATERIAL_PACKAGE);
+  _add_type (0x0137, MXF_TYPE_METADATA_SOURCE_PACKAGE);
+  _add_type (0x013b, MXF_TYPE_METADATA_TIMELINE_TRACK);
+  _add_type (0x0139, MXF_TYPE_METADATA_EVENT_TRACK);
+  _add_type (0x013a, MXF_TYPE_METADATA_STATIC_TRACK);
+  _add_type (0x010f, MXF_TYPE_METADATA_SEQUENCE);
+  _add_type (0x0111, MXF_TYPE_METADATA_SOURCE_CLIP);
+  _add_type (0x0114, MXF_TYPE_METADATA_TIMECODE_COMPONENT);
+  _add_type (0x0141, MXF_TYPE_METADATA_DM_SEGMENT);
+  _add_type (0x0145, MXF_TYPE_METADATA_DM_SOURCE_CLIP);
+  _add_type (0x0125, MXF_TYPE_METADATA_FILE_DESCRIPTOR);
+  _add_type (0x0127, MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
+  _add_type (0x0128, MXF_TYPE_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR);
+  _add_type (0x0129, MXF_TYPE_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR);
+  _add_type (0x0142, MXF_TYPE_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR);
+  _add_type (0x0143, MXF_TYPE_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR);
+  _add_type (0x0144, MXF_TYPE_METADATA_MULTIPLE_DESCRIPTOR);
+  _add_type (0x0132, MXF_TYPE_METADATA_NETWORK_LOCATOR);
+  _add_type (0x0133, MXF_TYPE_METADATA_TEXT_LOCATOR);
+
+#undef _add_type
+}
+
+void
+mxf_metadata_register (guint16 type_id, GType type)
+{
+  g_return_if_fail (g_type_is_a (type, MXF_TYPE_METADATA));
+  g_return_if_fail (type_id != 0);
+  g_return_if_fail (_mxf_metadata_registry != NULL);
+
+  {
+    GSList *l = _mxf_metadata_registry;
+
+    for (; l; l = l->next) {
+      if (((_MXFMetadataType *) l->data)->type_id == type_id) {
+        return;
+      }
+    }
+  }
+
+  {
+    _MXFMetadataType *l = g_slice_new (_MXFMetadataType);
+    l->type_id = type_id;
+    l->type = type;
+    _mxf_metadata_registry = g_slist_prepend (_mxf_metadata_registry, l);
+  }
+}
+
+MXFMetadata *
+mxf_metadata_new (guint16 type, MXFPrimerPack * primer, const guint8 * data,
+    guint size)
+{
+  GSList *l;
+  GType t = G_TYPE_INVALID;
+  MXFMetadata *ret = NULL;
+
+  g_return_val_if_fail (type != 0, NULL);
+  g_return_val_if_fail (primer != NULL, NULL);
+  g_return_val_if_fail (_mxf_metadata_registry != NULL, NULL);
+
+  for (l = _mxf_metadata_registry; l; l = l->next) {
+    _MXFMetadataType *data = l->data;
+
+    if (data->type_id == type) {
+      t = data->type;
+      break;
+    }
+  }
+
+  if (t == G_TYPE_INVALID) {
+    GST_WARNING
+        ("No handler for type 0x%04x found -- using generic metadata parser",
+        type);
+    t = MXF_TYPE_METADATA;
+  }
+
+  ret = (MXFMetadata *) g_type_create_instance (t);
+  if (!mxf_metadata_parse (MXF_METADATA_BASE (ret), primer, data, size)) {
+    GST_ERROR ("Parsing metadata failed");
+    gst_mini_object_unref ((GstMiniObject *) ret);
+    return NULL;
+  }
+
+  ret->type = type;
+  return ret;
+}
+
+G_DEFINE_TYPE (MXFMetadataPreface, mxf_metadata_preface, MXF_TYPE_METADATA);
+
+static void
+mxf_metadata_preface_finalize (GstMiniObject * object)
+{
+  MXFMetadataPreface *self = MXF_METADATA_PREFACE (object);
+
+  g_free (self->identifications_uids);
+  self->identifications_uids = NULL;
+
+  g_free (self->identifications);
+  self->identifications = NULL;
+
+  g_free (self->essence_containers);
+  self->essence_containers = NULL;
+
+  g_free (self->dm_schemes);
+  self->dm_schemes = NULL;
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_preface_parent_class)->finalize (object);
+}
+
+static gboolean
+mxf_metadata_preface_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataPreface *self = MXF_METADATA_PREFACE (metadata);
+  gchar str[48];
+  gboolean ret = TRUE;
+
+  switch (tag) {
+    case 0x3b02:
+      if (!mxf_timestamp_parse (&self->last_modified_date, tag_data, tag_size))
+        goto error;
+      GST_DEBUG ("  last modified date = %d/%u/%u %u:%u:%u.%u",
+          self->last_modified_date.year, self->last_modified_date.month,
+          self->last_modified_date.day, self->last_modified_date.hour,
+          self->last_modified_date.minute,
+          self->last_modified_date.second,
+          (self->last_modified_date.quarter_msecond * 1000) / 256);
+      break;
+    case 0x3b05:
+      if (tag_size != 2)
+        goto error;
+      self->version = GST_READ_UINT16_BE (tag_data);
+      GST_DEBUG ("  version = %u.%u", (self->version >> 8),
+          (self->version & 0x0f));
+      break;
+    case 0x3b07:
+      if (tag_size != 4)
+        goto error;
+      self->object_model_version = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  object model version = %u", self->object_model_version);
+      break;
+    case 0x3b08:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->primary_package_uid, tag_data, 16);
+      GST_DEBUG ("  primary package = %s",
+          mxf_ul_to_string (&self->primary_package_uid, str));
+      break;
+    case 0x3b06:{
+      guint32 len;
+      guint i;
+
+
+      if (tag_size < 8)
+        goto error;
+      len = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  number of identifications = %u", len);
+      if (len == 0)
+        return TRUE;
+      if (GST_READ_UINT32_BE (tag_data + 4) != 16)
+        goto error;
+      if (tag_size < 8 + len * 16)
+        goto error;
+
+      self->n_identifications = len;
+      self->identifications_uids = g_new (MXFUL, len);
+      for (i = 0; i < len; i++) {
+        memcpy (&self->identifications_uids[i], tag_data + 8 + i * 16, 16);
+        GST_DEBUG ("  identification %u = %s", i,
+            mxf_ul_to_string (&self->identifications_uids[i], str));
+      }
+      break;
+    }
+    case 0x3b03:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->content_storage_uid, tag_data, 16);
+      GST_DEBUG ("  content storage = %s",
+          mxf_ul_to_string (&self->content_storage_uid, str));
+      break;
+    case 0x3b09:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->operational_pattern, tag_data, 16);
+      GST_DEBUG ("  operational pattern = %s",
+          mxf_ul_to_string (&self->operational_pattern, str));
+      break;
+    case 0x3b0a:{
+      guint32 len;
+      guint i;
+
+
+      if (tag_size < 8)
+        goto error;
+      len = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  number of essence containers = %u", len);
+      if (len == 0)
+        return TRUE;
+      if (GST_READ_UINT32_BE (tag_data + 4) != 16)
+        goto error;
+      if (tag_size < 8 + len * 16)
+        goto error;
+
+      self->n_essence_containers = len;
+      self->essence_containers = g_new (MXFUL, len);
+      for (i = 0; i < len; i++) {
+        memcpy (&self->essence_containers[i], tag_data + 8 + i * 16, 16);
+        GST_DEBUG ("  essence container %u = %s", i,
+            mxf_ul_to_string (&self->essence_containers[i], str));
+      }
+      break;
+    }
+    case 0x3b0b:{
+      guint32 len;
+      guint i;
+
+
+      if (tag_size < 8)
+        goto error;
+      len = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  number of DM schemes = %u", len);
+      if (len == 0)
+        return TRUE;
+      if (GST_READ_UINT32_BE (tag_data + 4) != 16)
+        goto error;
+      if (tag_size < 8 + len * 16)
+        goto error;
+
+      self->n_dm_schemes = len;
+      self->dm_schemes = g_new (MXFUL, len);
+      for (i = 0; i < len; i++) {
+        memcpy (&self->dm_schemes[i], tag_data + 8 + i * 16, 16);
+        GST_DEBUG ("  DM schemes %u = %s", i,
+            mxf_ul_to_string (&self->dm_schemes[i], str));
+      }
+      break;
+    }
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS (mxf_metadata_preface_parent_class)->
+          handle_tag (metadata, primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid preface local tag 0x%04x of size %u", tag, tag_size);
+
+  return FALSE;
+}
+
+static gboolean
+mxf_metadata_preface_resolve (MXFMetadataBase * m, MXFMetadataBase ** metadata)
+{
+  MXFMetadataPreface *self = MXF_METADATA_PREFACE (m);
+  MXFMetadataBase **p = metadata, *current;
+  guint i;
+
+  while (*p && (self->primary_package == NULL || self->content_storage == NULL)) {
+    current = *p;
+
+    if (MXF_IS_METADATA_GENERIC_PACKAGE (current) &&
+        mxf_ul_is_equal (&self->primary_package_uid, &current->instance_uid)) {
+      if (mxf_metadata_resolve (current, metadata))
+        self->primary_package = MXF_METADATA_GENERIC_PACKAGE (current);
+    } else if (MXF_IS_METADATA_CONTENT_STORAGE (current) &&
+        mxf_ul_is_equal (&self->content_storage_uid, &current->instance_uid)) {
+      if (mxf_metadata_resolve (current, metadata))
+        self->content_storage = MXF_METADATA_CONTENT_STORAGE (current);
+    }
+    p++;
+  }
+
+  self->identifications =
+      g_new0 (MXFMetadataIdentification *, self->n_identifications);
+  for (i = 0; i < self->n_identifications; i++) {
+    p = metadata;
+    while (*p) {
+      current = *p;
+
+      if (MXF_IS_METADATA_IDENTIFICATION (current) &&
+          mxf_ul_is_equal (&self->identifications_uids[i],
+              &current->instance_uid)) {
+        if (mxf_metadata_resolve (current, metadata))
+          self->identifications[i] = MXF_METADATA_IDENTIFICATION (current);
+        break;
+      }
+      p++;
+    }
+  }
+
+  if (!self->content_storage) {
+    GST_ERROR ("Couldn't resolve content storage");
+    return FALSE;
+  }
+
+  return MXF_METADATA_BASE_CLASS (mxf_metadata_preface_parent_class)->
+      resolve (m, metadata);
+}
+
+static void
+mxf_metadata_preface_init (MXFMetadataPreface * self)
+{
+
+}
+
+static void
+mxf_metadata_preface_class_init (MXFMetadataPrefaceClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_preface_finalize;
+  metadata_base_class->handle_tag = mxf_metadata_preface_handle_tag;
+  metadata_base_class->resolve = mxf_metadata_preface_resolve;
+}
+
+G_DEFINE_TYPE (MXFMetadataIdentification, mxf_metadata_identification,
+    MXF_TYPE_METADATA);
+
+static void
+mxf_metadata_identification_finalize (GstMiniObject * object)
+{
+  MXFMetadataIdentification *self = MXF_METADATA_IDENTIFICATION (object);
+
+  g_free (self->company_name);
+  self->company_name = NULL;
+
+  g_free (self->product_name);
+  self->product_name = NULL;
+
+  g_free (self->version_string);
+  self->version_string = NULL;
+
+  g_free (self->platform);
+  self->platform = NULL;
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_identification_parent_class)->finalize
+      (object);
+}
+
+static gboolean
+mxf_metadata_identification_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataIdentification *self = MXF_METADATA_IDENTIFICATION (metadata);
+  gboolean ret = TRUE;
+  gchar str[48];
+
+  switch (tag) {
+    case 0x3c01:
+      self->company_name = mxf_utf16_to_utf8 (tag_data, tag_size);
+      GST_DEBUG ("  company name = %s", GST_STR_NULL (self->company_name));
+      break;
+    case 0x3c02:
+      self->product_name = mxf_utf16_to_utf8 (tag_data, tag_size);
+      GST_DEBUG ("  product name = %s", GST_STR_NULL (self->product_name));
+      break;
+    case 0x3c03:
+      if (!mxf_product_version_parse (&self->product_version,
+              tag_data, tag_size))
+        goto error;
+      GST_DEBUG ("  product version = %u.%u.%u.%u.%u",
+          self->product_version.major,
+          self->product_version.minor,
+          self->product_version.patch,
+          self->product_version.build, self->product_version.release);
+      break;
+    case 0x3c04:
+      self->version_string = mxf_utf16_to_utf8 (tag_data, tag_size);
+      GST_DEBUG ("  version string = %s", GST_STR_NULL (self->version_string));
+      break;
+    case 0x3c05:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->product_uid, tag_data, 16);
+      GST_DEBUG ("  product uid = %s",
+          mxf_ul_to_string (&self->product_uid, str));
+      break;
+    case 0x3c06:
+      if (!mxf_timestamp_parse (&self->modification_date, tag_data, tag_size))
+        goto error;
+      GST_DEBUG ("  modification date = %d/%u/%u %u:%u:%u.%u",
+          self->modification_date.year,
+          self->modification_date.month,
+          self->modification_date.day,
+          self->modification_date.hour,
+          self->modification_date.minute,
+          self->modification_date.second,
+          (self->modification_date.quarter_msecond * 1000) / 256);
+      break;
+    case 0x3c07:
+      if (!mxf_product_version_parse (&self->toolkit_version,
+              tag_data, tag_size))
+        goto error;
+      GST_DEBUG ("  toolkit version = %u.%u.%u.%u.%u",
+          self->toolkit_version.major,
+          self->toolkit_version.minor,
+          self->toolkit_version.patch,
+          self->toolkit_version.build, self->toolkit_version.release);
+      break;
+    case 0x3c08:
+      self->platform = mxf_utf16_to_utf8 (tag_data, tag_size);
+      GST_DEBUG ("  platform = %s", GST_STR_NULL (self->platform));
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_identification_parent_class)->handle_tag (metadata,
+          primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+  GST_ERROR ("Invalid identification local tag 0x%04x of size %u", tag,
+      tag_size);
+
+  return FALSE;
+}
+
+static void
+mxf_metadata_identification_init (MXFMetadataIdentification * self)
+{
+
+}
+
+static void
+mxf_metadata_identification_class_init (MXFMetadataIdentificationClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_identification_finalize;
+  metadata_base_class->handle_tag = mxf_metadata_identification_handle_tag;
+}
+
+G_DEFINE_TYPE (MXFMetadataContentStorage, mxf_metadata_content_storage,
+    MXF_TYPE_METADATA);
+
+static void
+mxf_metadata_content_storage_finalize (GstMiniObject * object)
+{
+  MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (object);
+
+  g_free (self->packages);
+  self->packages = NULL;
+  g_free (self->packages_uids);
+  self->packages_uids = NULL;
+  g_free (self->essence_container_data);
+  self->essence_container_data = NULL;
+  g_free (self->essence_container_data_uids);
+  self->essence_container_data_uids = NULL;
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_content_storage_parent_class)->finalize
+      (object);
+}
+
+static gboolean
+mxf_metadata_content_storage_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (metadata);
+  gboolean ret = TRUE;
+  gchar str[48];
+
+  switch (tag) {
+    case 0x1901:{
+      guint32 len;
+      guint i;
+
+
+      len = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  number of packages = %u", len);
+      if (len == 0)
+        return TRUE;
+      if (GST_READ_UINT32_BE (tag_data + 4) != 16)
+        goto error;
+      if (tag_size < 8 + len * 16)
+        goto error;
+
+      self->packages_uids = g_new (MXFUL, len);
+      self->n_packages = len;
+      for (i = 0; i < len; i++) {
+        memcpy (&self->packages_uids[i], tag_data + 8 + i * 16, 16);
+        GST_DEBUG ("  package %u = %s", i,
+            mxf_ul_to_string (&self->packages_uids[i], str));
+      }
+      break;
+    }
+    case 0x1902:{
+      guint32 len;
+      guint i;
+
+
+      len = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  number of essence container data = %u", len);
+      if (len == 0)
+        return TRUE;
+      if (GST_READ_UINT32_BE (tag_data + 4) != 16)
+        goto error;
+      if (tag_size < 8 + len * 16)
+        goto error;
+
+      self->essence_container_data_uids = g_new (MXFUL, len);
+      self->n_essence_container_data = len;
+      for (i = 0; i < len; i++) {
+        memcpy (&self->essence_container_data_uids[i],
+            tag_data + 8 + i * 16, 16);
+        GST_DEBUG ("  essence container data %u = %s", i,
+            mxf_ul_to_string (&self->essence_container_data_uids[i], str));
+      }
+      break;
+    }
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_content_storage_parent_class)->handle_tag (metadata,
+          primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid content storage local tag 0x%04x of size %u", tag,
+      tag_size);
+
+  return FALSE;
+}
+
+static gboolean
+mxf_metadata_content_storage_resolve (MXFMetadataBase * m,
+    MXFMetadataBase ** metadata)
+{
+  MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (m);
+  MXFMetadataBase **p = metadata, *current;
+  guint i;
+  gboolean have_package = FALSE;
+  gboolean have_ecd = FALSE;
+
+  self->packages = g_new0 (MXFMetadataGenericPackage *, self->n_packages);
+  for (i = 0; i < self->n_packages; i++) {
+    p = metadata;
+    while (*p) {
+      current = *p;
+      if (MXF_IS_METADATA_GENERIC_PACKAGE (current) &&
+          mxf_ul_is_equal (&current->instance_uid, &self->packages_uids[i])) {
+        if (mxf_metadata_resolve (current, metadata)) {
+          self->packages[i] = MXF_METADATA_GENERIC_PACKAGE (current);
+          have_package = TRUE;
+        }
+        break;
+      }
+      p++;
+    }
+  }
+
+  self->essence_container_data =
+      g_new0 (MXFMetadataEssenceContainerData *,
+      self->n_essence_container_data);
+  for (i = 0; i < self->n_essence_container_data; i++) {
+    p = metadata;
+    while (*p) {
+      current = *p;
+      if (MXF_IS_METADATA_ESSENCE_CONTAINER_DATA (current) &&
+          mxf_ul_is_equal (&current->instance_uid,
+              &self->essence_container_data_uids[i])) {
+        if (mxf_metadata_resolve (current, metadata)) {
+          self->essence_container_data[i] =
+              MXF_METADATA_ESSENCE_CONTAINER_DATA (current);
+          have_ecd = TRUE;
+        }
+        break;
+      }
+      p++;
+    }
+  }
+
+  if (!have_package) {
+    GST_ERROR ("Couldn't resolve any package");
+    return FALSE;
+  } else if (!have_ecd) {
+    GST_ERROR ("Couldn't resolve any essence container data");
+    return FALSE;
+  }
+
+  return MXF_METADATA_BASE_CLASS (mxf_metadata_content_storage_parent_class)->
+      resolve (m, metadata);
+}
+
+static void
+mxf_metadata_content_storage_init (MXFMetadataContentStorage * self)
+{
+
+}
+
+static void
+mxf_metadata_content_storage_class_init (MXFMetadataContentStorageClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_content_storage_finalize;
+  metadata_base_class->handle_tag = mxf_metadata_content_storage_handle_tag;
+  metadata_base_class->resolve = mxf_metadata_content_storage_resolve;
+}
+
+G_DEFINE_TYPE (MXFMetadataEssenceContainerData,
+    mxf_metadata_essence_container_data, MXF_TYPE_METADATA);
+
+static gboolean
+mxf_metadata_essence_container_data_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataEssenceContainerData *self =
+      MXF_METADATA_ESSENCE_CONTAINER_DATA (metadata);
+  gboolean ret = TRUE;
+  gchar str[96];
+
+  switch (tag) {
+    case 0x2701:
+      if (tag_size != 32)
+        goto error;
+      memcpy (&self->linked_package_uid, tag_data, 32);
+      GST_DEBUG ("  linked package = %s",
+          mxf_umid_to_string (&self->linked_package_uid, str));
+      break;
+    case 0x3f06:
+      if (tag_size != 4)
+        goto error;
+      self->index_sid = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  index sid = %u", self->index_sid);
+      break;
+    case 0x3f07:
+      if (tag_size != 4)
+        goto error;
+      self->body_sid = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  body sid = %u", self->body_sid);
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_essence_container_data_parent_class)->handle_tag
+          (metadata, primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid essence container data local tag 0x%04x of size %u", tag,
+      tag_size);
+
+  return FALSE;
+}
+
+static gboolean
+mxf_metadata_essence_container_data_resolve (MXFMetadataBase * m,
+    MXFMetadataBase ** metadata)
+{
+  MXFMetadataEssenceContainerData *self =
+      MXF_METADATA_ESSENCE_CONTAINER_DATA (m);
+  MXFMetadataBase **p = metadata, *current;
+
+  while (*p) {
+    current = *p;
+
+    if (MXF_IS_METADATA_SOURCE_PACKAGE (current)) {
+      MXFMetadataSourcePackage *package = MXF_METADATA_SOURCE_PACKAGE (current);
+
+      if (mxf_umid_is_equal (&package->parent.package_uid,
+              &self->linked_package_uid)) {
+        if (mxf_metadata_resolve (current, metadata)) {
+          self->linked_package = package;
+        }
+        break;
+      }
+    }
+    p++;
+  }
+
+  if (!self->linked_package) {
+    GST_ERROR ("Couldn't resolve a package");
+    return FALSE;
+  }
+
+  return
+      MXF_METADATA_BASE_CLASS
+      (mxf_metadata_essence_container_data_parent_class)->resolve (m, metadata);
+}
+
+static void
+mxf_metadata_essence_container_data_init (MXFMetadataEssenceContainerData *
+    self)
+{
+
+}
+
+static void
+    mxf_metadata_essence_container_data_class_init
+    (MXFMetadataEssenceContainerDataClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+
+  metadata_base_class->handle_tag =
+      mxf_metadata_essence_container_data_handle_tag;
+  metadata_base_class->resolve = mxf_metadata_essence_container_data_resolve;
+}
+
+G_DEFINE_ABSTRACT_TYPE (MXFMetadataGenericPackage, mxf_metadata_generic_package,
+    MXF_TYPE_METADATA);
+
+static void
+mxf_metadata_generic_package_finalize (GstMiniObject * object)
+{
+  MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (object);
+
+  g_free (self->name);
+  self->name = NULL;
+  g_free (self->tracks_uids);
+  self->tracks_uids = NULL;
+
+  g_free (self->tracks);
+  self->tracks = NULL;
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_generic_package_parent_class)->finalize
+      (object);
+}
+
+static gboolean
+mxf_metadata_generic_package_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (metadata);
+  gboolean ret = TRUE;
+  gchar str[96];
+
+  switch (tag) {
+    case 0x4401:
+      if (tag_size != 32)
+        goto error;
+      memcpy (&self->package_uid, tag_data, 32);
+      GST_DEBUG ("  UMID = %s", mxf_umid_to_string (&self->package_uid, str));
+      break;
+    case 0x4402:
+      self->name = mxf_utf16_to_utf8 (tag_data, tag_size);
+      GST_DEBUG ("  name = %s", GST_STR_NULL (self->name));
+      break;
+    case 0x4405:
+      if (!mxf_timestamp_parse (&self->package_creation_date,
+              tag_data, tag_size))
+        goto error;
+      GST_DEBUG ("  creation date = %d/%u/%u %u:%u:%u.%u",
+          self->package_creation_date.year,
+          self->package_creation_date.month,
+          self->package_creation_date.day,
+          self->package_creation_date.hour,
+          self->package_creation_date.minute,
+          self->package_creation_date.second,
+          (self->package_creation_date.quarter_msecond * 1000) / 256);
+      break;
+    case 0x4404:
+      if (!mxf_timestamp_parse (&self->package_modified_date,
+              tag_data, tag_size))
+        goto error;
+      GST_DEBUG ("  modification date = %d/%u/%u %u:%u:%u.%u",
+          self->package_modified_date.year,
+          self->package_modified_date.month,
+          self->package_modified_date.day,
+          self->package_modified_date.hour,
+          self->package_modified_date.minute,
+          self->package_modified_date.second,
+          (self->package_modified_date.quarter_msecond * 1000) / 256);
+      break;
+    case 0x4403:{
+      guint32 len;
+      guint i;
+
+
+      len = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  number of tracks = %u", len);
+      if (len == 0)
+        return TRUE;
+      if (GST_READ_UINT32_BE (tag_data + 4) != 16)
+        goto error;
+      if (tag_size < 8 + len * 16)
+        goto error;
+
+      self->tracks_uids = g_new (MXFUL, len);
+      self->n_tracks = len;
+      for (i = 0; i < len; i++) {
+        memcpy (&self->tracks_uids[i], tag_data + 8 + i * 16, 16);
+        GST_DEBUG ("  track %u = %s", i,
+            mxf_ul_to_string (&self->tracks_uids[i], str));
+      }
+      break;
+    }
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_generic_package_parent_class)->handle_tag (metadata,
+          primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid generic package local tag 0x%04x of size %u", tag,
+      tag_size);
+
+  return FALSE;
+}
+
+static gboolean
+mxf_metadata_generic_package_resolve (MXFMetadataBase * m,
+    MXFMetadataBase ** metadata)
+{
+  MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (m);
+  MXFMetadataBase **p, *current;
+  guint i;
+  gboolean have_track = FALSE;
+
+  self->tracks = g_new0 (MXFMetadataTrack *, self->n_tracks);
+  for (i = 0; i < self->n_tracks; i++) {
+    p = metadata;
+    while (*p) {
+      current = *p;
+
+      if (MXF_IS_METADATA_TRACK (current)) {
+        MXFMetadataTrack *track = MXF_METADATA_TRACK (current);
+
+        if (mxf_ul_is_equal (&current->instance_uid, &self->tracks_uids[i])) {
+          if (mxf_metadata_resolve (current, metadata)) {
+            self->tracks[i] = track;
+            have_track = TRUE;
+
+            if ((track->type & 0xf0) == 0x10)
+              self->n_timecode_tracks++;
+            else if ((track->type & 0xf0) == 0x20)
+              self->n_metadata_tracks++;
+            else if ((track->type & 0xf0) == 0x30)
+              self->n_essence_tracks++;
+            else if ((track->type & 0xf0) == 0x40)
+              self->n_other_tracks++;
+          }
+
+          break;
+        }
+      }
+
+      p++;
+    }
+  }
+
+  if (!have_track) {
+    GST_ERROR ("Couldn't resolve a track");
+    return FALSE;
+  }
+
+  return MXF_METADATA_BASE_CLASS (mxf_metadata_generic_package_parent_class)->
+      resolve (m, metadata);
+}
+
+static void
+mxf_metadata_generic_package_init (MXFMetadataGenericPackage * self)
+{
+
+}
+
+static void
+mxf_metadata_generic_package_class_init (MXFMetadataGenericPackageClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_generic_package_finalize;
+  metadata_base_class->handle_tag = mxf_metadata_generic_package_handle_tag;
+  metadata_base_class->resolve = mxf_metadata_generic_package_resolve;
+}
+
+G_DEFINE_TYPE (MXFMetadataMaterialPackage, mxf_metadata_material_package,
+    MXF_TYPE_METADATA_GENERIC_PACKAGE);
+
+static gboolean
+mxf_metadata_material_package_resolve (MXFMetadataBase * m,
+    MXFMetadataBase ** metadata)
+{
+  gboolean ret =
+      MXF_METADATA_BASE_CLASS (mxf_metadata_material_package_parent_class)->
+      resolve (m, metadata);
+  MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (m);
+  guint i;
+
+  if (!ret)
+    return ret;
+
+  for (i = 0; i < self->n_tracks; i++) {
+    MXFMetadataTrack *track = self->tracks[i];
+    MXFMetadataSequence *sequence;
+    guint j;
+
+    if (!track)
+      continue;
+
+    sequence = track->sequence;
+
+    if (!sequence || !sequence->structural_components)
+      continue;
+
+    for (j = 0; j < sequence->n_structural_components; j++) {
+      MXFMetadataSourceClip *sc;
+
+      if (!sequence->structural_components[j]
+          || !MXF_IS_METADATA_SOURCE_CLIP (sequence->structural_components[j]))
+        continue;
+
+      sc = MXF_METADATA_SOURCE_CLIP (sequence->structural_components[j]);
+
+      if (sc->source_package)
+        sc->source_package->top_level = TRUE;
+    }
+  }
+
+  return TRUE;
+}
+
+static void
+mxf_metadata_material_package_init (MXFMetadataMaterialPackage * self)
+{
+}
+
+static void
+mxf_metadata_material_package_class_init (MXFMetadataMaterialPackageClass *
+    klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+
+  metadata_base_class->resolve = mxf_metadata_material_package_resolve;
+}
+
+G_DEFINE_TYPE (MXFMetadataSourcePackage, mxf_metadata_source_package,
+    MXF_TYPE_METADATA_GENERIC_PACKAGE);
+
+static void
+mxf_metadata_source_package_finalize (GstMiniObject * object)
+{
+  MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (object);
+
+  g_free (self->descriptors);
+  self->descriptors = NULL;
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_source_package_parent_class)->finalize
+      (object);
+}
+
+static gboolean
+mxf_metadata_source_package_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (metadata);
+  gboolean ret = TRUE;
+  gchar str[48];
+
+  switch (tag) {
+    case 0x4701:
+      if (tag_size != 16)
+        goto error;
+
+      self->n_descriptors = 1;
+      memcpy (&self->descriptors_uid, tag_data, 16);
+      GST_DEBUG ("  descriptor = %s",
+          mxf_ul_to_string (&self->descriptors_uid, str));
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_source_package_parent_class)->handle_tag (metadata,
+          primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid source package local tag 0x%04x of size %u", tag,
+      tag_size);
+
+  return FALSE;
+}
+
+static gboolean
+mxf_metadata_source_package_resolve (MXFMetadataBase * m,
+    MXFMetadataBase ** metadata)
+{
+  MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (m);
+  MXFMetadataGenericPackage *package = MXF_METADATA_GENERIC_PACKAGE (m);
+  MXFMetadataBase **p = metadata, *current;
+  guint i, j;
+  gboolean ret;
+  MXFMetadataGenericDescriptor *d = NULL;
+
+  if (mxf_ul_is_zero (&self->descriptors_uid))
+    return MXF_METADATA_BASE_CLASS (mxf_metadata_source_package_parent_class)->
+        resolve (m, metadata);
+
+  while (*p) {
+    current = *p;
+
+    if (MXF_IS_METADATA_GENERIC_DESCRIPTOR (current) &&
+        mxf_ul_is_equal (&current->instance_uid, &self->descriptors_uid)) {
+      d = MXF_METADATA_GENERIC_DESCRIPTOR (current);
+      break;
+    }
+    p++;
+  }
+
+  if (!d || !mxf_metadata_resolve (MXF_METADATA_BASE (d), metadata)) {
+    GST_ERROR ("Couldn't resolve descriptor");
+    return FALSE;
+  }
+
+  if (MXF_IS_METADATA_MULTIPLE_DESCRIPTOR (d)) {
+    MXFMetadataMultipleDescriptor *m = MXF_METADATA_MULTIPLE_DESCRIPTOR (d);
+
+    if (m->sub_descriptors) {
+      self->n_descriptors = m->n_sub_descriptors + 1;
+      self->descriptors =
+          g_new0 (MXFMetadataGenericDescriptor *, self->n_descriptors);
+
+      for (i = 0; i < m->n_sub_descriptors; i++) {
+        self->descriptors[i] = m->sub_descriptors[i];
+      }
+      self->descriptors[self->n_descriptors - 1] =
+          MXF_METADATA_GENERIC_DESCRIPTOR (m);
+    }
+  } else {
+    self->n_descriptors = 1;
+    self->descriptors = g_new0 (MXFMetadataGenericDescriptor *, 1);
+    self->descriptors[0] = d;
+  }
+
+  ret =
+      MXF_METADATA_BASE_CLASS (mxf_metadata_source_package_parent_class)->
+      resolve (m, metadata);
+
+  for (i = 0; i < package->n_tracks; i++) {
+    guint n_descriptor = 0, k = 0;
+
+    for (j = 0; j < self->n_descriptors; j++) {
+      MXFMetadataFileDescriptor *d;
+
+      if (!MXF_IS_METADATA_FILE_DESCRIPTOR (self->descriptors[j]))
+        continue;
+      d = MXF_METADATA_FILE_DESCRIPTOR (self->descriptors[j]);
+
+      if (d->linked_track_id == package->tracks[i]->track_id ||
+          d->linked_track_id == 0)
+        n_descriptor++;
+    }
+
+    package->tracks[i]->descriptor =
+        g_new0 (MXFMetadataFileDescriptor *, n_descriptor);
+    package->tracks[i]->n_descriptor = n_descriptor;
+    for (j = 0; j < self->n_descriptors; j++) {
+      MXFMetadataFileDescriptor *d;
+
+      if (!MXF_IS_METADATA_FILE_DESCRIPTOR (self->descriptors[j]))
+        continue;
+      d = MXF_METADATA_FILE_DESCRIPTOR (self->descriptors[j]);
+
+      if (d->linked_track_id == package->tracks[i]->track_id ||
+          (d->linked_track_id == 0 && n_descriptor == 1))
+        package->tracks[i]->descriptor[k++] = d;
+    }
+  }
+
+  return ret;
+}
+
+static void
+mxf_metadata_source_package_init (MXFMetadataSourcePackage * self)
+{
+
+}
+
+static void
+mxf_metadata_source_package_class_init (MXFMetadataSourcePackageClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_source_package_finalize;
+  metadata_base_class->handle_tag = mxf_metadata_source_package_handle_tag;
+  metadata_base_class->resolve = mxf_metadata_source_package_resolve;
+}
+
+G_DEFINE_ABSTRACT_TYPE (MXFMetadataTrack, mxf_metadata_track,
+    MXF_TYPE_METADATA);
+
+static void
+mxf_metadata_track_finalize (GstMiniObject * object)
+{
+  MXFMetadataTrack *self = MXF_METADATA_TRACK (object);
+
+  g_free (self->track_name);
+  self->track_name = NULL;
+  g_free (self->descriptor);
+  self->descriptor = NULL;
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_track_parent_class)->finalize (object);
+}
+
+static gboolean
+mxf_metadata_track_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataTrack *self = MXF_METADATA_TRACK (metadata);
+  gboolean ret = TRUE;
+  gchar str[48];
+
+  switch (tag) {
+    case 0x4801:
+      if (tag_size != 4)
+        goto error;
+      self->track_id = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  track id = %u", self->track_id);
+      break;
+    case 0x4804:
+      if (tag_size != 4)
+        goto error;
+      self->track_number = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  track number = %u", self->track_number);
+      break;
+    case 0x4802:
+      self->track_name = mxf_utf16_to_utf8 (tag_data, tag_size);
+      GST_DEBUG ("  track name = %s", GST_STR_NULL (self->track_name));
+      break;
+    case 0x4803:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->sequence_uid, tag_data, 16);
+      GST_DEBUG ("  sequence uid = %s",
+          mxf_ul_to_string (&self->sequence_uid, str));
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->handle_tag
+          (metadata, primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid track local tag 0x%04x of size %u", tag, tag_size);
+
+  return FALSE;
+}
+
+static gboolean
+mxf_metadata_track_resolve (MXFMetadataBase * m, MXFMetadataBase ** metadata)
+{
+  MXFMetadataTrack *self = MXF_METADATA_TRACK (m);
+  MXFMetadataBase **p = metadata, *current;
+  guint i;
+
+  while (*p) {
+    current = *p;
+    if (MXF_IS_METADATA_SEQUENCE (current) &&
+        mxf_ul_is_equal (&current->instance_uid, &self->sequence_uid)) {
+      self->sequence = MXF_METADATA_SEQUENCE (current);
+      break;
+    }
+    p++;
+  }
+
+  if (!self->sequence
+      || !mxf_metadata_resolve (MXF_METADATA_BASE (self->sequence), metadata)) {
+    GST_ERROR ("Couldn't resolve sequence");
+    return FALSE;
+  }
+
+  self->type =
+      mxf_metadata_track_identifier_parse (&self->sequence->data_definition);
+  if (self->type == MXF_METADATA_TRACK_UNKNOWN) {
+    MXFMetadataSequence *sequence = self->sequence;
+
+    for (i = 0; i < sequence->n_structural_components; i++) {
+      MXFMetadataStructuralComponent *component =
+          sequence->structural_components[i];
+
+      if (!component)
+        continue;
+
+      self->type =
+          mxf_metadata_track_identifier_parse (&component->data_definition);
+      if (self->type != MXF_METADATA_TRACK_UNKNOWN)
+        break;
+    }
+  }
+
+  return MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->resolve (m,
+      metadata);
+}
+
+static void
+mxf_metadata_track_init (MXFMetadataTrack * self)
+{
+
+}
+
+static void
+mxf_metadata_track_class_init (MXFMetadataTrackClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_track_finalize;
+  metadata_base_class->handle_tag = mxf_metadata_track_handle_tag;
+  metadata_base_class->resolve = mxf_metadata_track_resolve;
+}
+
+/* SMPTE RP224 */
+static const struct
+{
+  guint8 ul[16];
+  MXFMetadataTrackType type;
+} mxf_metadata_track_identifier[] = {
+  { {
+  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01,
+          0x01, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00},
+      MXF_METADATA_TRACK_TIMECODE_12M_INACTIVE}, { {
+  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01,
+          0x02, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_TIMECODE_12M_ACTIVE}, { {
+  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01,
+          0x03, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_TIMECODE_309M}, { {
+  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01,
+          0x10, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_METADATA}, { {
+  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02,
+          0x01, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_PICTURE_ESSENCE}, { {
+  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02,
+          0x02, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_SOUND_ESSENCE}, { {
+  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02,
+          0x03, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_DATA_ESSENCE}, { {
+  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03,
+          0x01, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_AUXILIARY_DATA}, { {
+  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03,
+          0x02, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_PARSED_TEXT}
+};
+
+MXFMetadataTrackType
+mxf_metadata_track_identifier_parse (const MXFUL * track_identifier)
+{
+  guint i;
+
+  for (i = 0; i < G_N_ELEMENTS (mxf_metadata_track_identifier); i++)
+    if (memcmp (&mxf_metadata_track_identifier[i].ul, &track_identifier->u,
+            16) == 0)
+      return mxf_metadata_track_identifier[i].type;
+
+  return MXF_METADATA_TRACK_UNKNOWN;
+}
+
+G_DEFINE_TYPE (MXFMetadataTimelineTrack, mxf_metadata_timeline_track,
+    MXF_TYPE_METADATA_TRACK);
+
+static gboolean
+mxf_metadata_timeline_track_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataTimelineTrack *self = MXF_METADATA_TIMELINE_TRACK (metadata);
+  gboolean ret = TRUE;
+
+  switch (tag) {
+    case 0x4b01:
+      if (!mxf_fraction_parse (&self->edit_rate, tag_data, tag_size))
+        goto error;
+      GST_DEBUG ("  edit rate = %d/%d", self->edit_rate.n, self->edit_rate.d);
+      break;
+    case 0x4b02:
+      if (tag_size != 8)
+        goto error;
+      self->origin = GST_READ_UINT64_BE (tag_data);
+      GST_DEBUG ("  origin = %" G_GINT64_FORMAT, self->origin);
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_timeline_track_parent_class)->handle_tag (metadata,
+          primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid timeline track local tag 0x%04x of size %u", tag,
+      tag_size);
+
+  return FALSE;
+}
+
+static void
+mxf_metadata_timeline_track_init (MXFMetadataTimelineTrack * self)
+{
+
+}
+
+static void
+mxf_metadata_timeline_track_class_init (MXFMetadataTimelineTrackClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+
+  metadata_base_class->handle_tag = mxf_metadata_timeline_track_handle_tag;
+}
+
+G_DEFINE_TYPE (MXFMetadataEventTrack, mxf_metadata_event_track,
+    MXF_TYPE_METADATA_TRACK);
+
+static gboolean
+mxf_metadata_event_track_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataEventTrack *self = MXF_METADATA_EVENT_TRACK (metadata);
+  gboolean ret = TRUE;
+
+  switch (tag) {
+    case 0x4901:
+      if (!mxf_fraction_parse (&self->event_edit_rate, tag_data, tag_size))
+        goto error;
+      GST_DEBUG ("  event edit rate = %d/%d", self->event_edit_rate.n,
+          self->event_edit_rate.d);
+      break;
+    case 0x4902:
+      if (tag_size != 8)
+        goto error;
+      self->event_origin = GST_READ_UINT64_BE (tag_data);
+      GST_DEBUG ("  event origin = %" G_GINT64_FORMAT, self->event_origin);
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_event_track_parent_class)->handle_tag (metadata, primer,
+          tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid event track local tag 0x%04x of size %u", tag, tag_size);
+
+  return FALSE;
+}
+
+static void
+mxf_metadata_event_track_init (MXFMetadataEventTrack * self)
+{
+
+}
+
+static void
+mxf_metadata_event_track_class_init (MXFMetadataEventTrackClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+
+  metadata_base_class->handle_tag = mxf_metadata_event_track_handle_tag;
+}
+
+G_DEFINE_TYPE (MXFMetadataStaticTrack, mxf_metadata_static_track,
+    MXF_TYPE_METADATA_TRACK);
+
+static void
+mxf_metadata_static_track_init (MXFMetadataStaticTrack * self)
+{
+}
+
+static void
+mxf_metadata_static_track_class_init (MXFMetadataStaticTrackClass * klass)
+{
+}
+
+G_DEFINE_TYPE (MXFMetadataSequence, mxf_metadata_sequence, MXF_TYPE_METADATA);
+
+static void
+mxf_metadata_sequence_finalize (GstMiniObject * object)
+{
+  MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (object);
+
+  g_free (self->structural_components_uids);
+  self->structural_components_uids = NULL;
+  g_free (self->structural_components);
+  self->structural_components = NULL;
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_sequence_parent_class)->finalize (object);
+}
+
+static gboolean
+mxf_metadata_sequence_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (metadata);
+  gboolean ret = TRUE;
+  gchar str[48];
+
+  switch (tag) {
+    case 0x0201:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->data_definition, tag_data, 16);
+      GST_DEBUG ("  data definition = %s",
+          mxf_ul_to_string (&self->data_definition, str));
+      break;
+    case 0x0202:
+      if (tag_size != 8)
+        goto error;
+      self->duration = GST_READ_UINT64_BE (tag_data);
+      GST_DEBUG ("  duration = %" G_GINT64_FORMAT, self->duration);
+      break;
+    case 0x1001:{
+      guint32 len;
+      guint i;
+
+
+      len = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  number of structural components = %u", len);
+      if (len == 0)
+        return TRUE;
+      if (GST_READ_UINT32_BE (tag_data + 4) != 16)
+        goto error;
+      if (tag_size < 8 + len * 16)
+        goto error;
+
+      self->structural_components_uids = g_new (MXFUL, len);
+      self->n_structural_components = len;
+      for (i = 0; i < len; i++) {
+        memcpy (&self->structural_components_uids[i],
+            tag_data + 8 + i * 16, 16);
+        GST_DEBUG ("  structural component %u = %s", i,
+            mxf_ul_to_string (&self->structural_components_uids[i], str));
+      }
+      break;
+    }
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_sequence_parent_class)->handle_tag (metadata, primer,
+          tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid sequence local tag 0x%04x of size %u", tag, tag_size);
+
+  return FALSE;
+}
+
+static gboolean
+mxf_metadata_sequence_resolve (MXFMetadataBase * m, MXFMetadataBase ** metadata)
+{
+  MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (m);
+  MXFMetadataBase **p, *current;
+  guint i;
+  guint have_sc = 0;
+
+  self->structural_components =
+      g_new0 (MXFMetadataStructuralComponent *, self->n_structural_components);
+  for (i = 0; i < self->n_structural_components; i++) {
+    p = metadata;
+
+    while (*p) {
+      current = *p;
+
+      if (MXF_IS_METADATA_STRUCTURAL_COMPONENT (current)
+          && mxf_ul_is_equal (&current->instance_uid,
+              &self->structural_components_uids[i])) {
+        if (mxf_metadata_resolve (current, metadata)) {
+          self->structural_components[i] =
+              MXF_METADATA_STRUCTURAL_COMPONENT (current);
+          have_sc++;
+          break;
+        }
+      }
+      p++;
+    }
+  }
+
+  if (have_sc != self->n_structural_components) {
+    GST_ERROR ("Couldn't resolve all structural components");
+    return FALSE;
+  }
+
+  return MXF_METADATA_BASE_CLASS (mxf_metadata_sequence_parent_class)->
+      resolve (m, metadata);
+
+}
+
+static void
+mxf_metadata_sequence_init (MXFMetadataSequence * self)
+{
+
+}
+
+static void
+mxf_metadata_sequence_class_init (MXFMetadataSequenceClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_sequence_finalize;
+  metadata_base_class->handle_tag = mxf_metadata_sequence_handle_tag;
+  metadata_base_class->resolve = mxf_metadata_sequence_resolve;
+}
+
+G_DEFINE_TYPE (MXFMetadataStructuralComponent,
+    mxf_metadata_structural_component, MXF_TYPE_METADATA);
+
+static gboolean
+mxf_metadata_structural_component_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataStructuralComponent *self =
+      MXF_METADATA_STRUCTURAL_COMPONENT (metadata);
+  gboolean ret = TRUE;
+  gchar str[48];
+
+  switch (tag) {
+    case 0x0201:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->data_definition, tag_data, 16);
+      GST_DEBUG ("  data definition = %s",
+          mxf_ul_to_string (&self->data_definition, str));
+      break;
+    case 0x0202:
+      if (tag_size != 8)
+        goto error;
+      self->duration = GST_READ_UINT64_BE (tag_data);
+      GST_DEBUG ("  duration = %" G_GINT64_FORMAT, self->duration);
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_structural_component_parent_class)->handle_tag
+          (metadata, primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid structural component local tag 0x%04x of size %u", tag,
+      tag_size);
+
+  return FALSE;
+}
+
+static void
+mxf_metadata_structural_component_init (MXFMetadataStructuralComponent * self)
+{
+
+}
+
+static void
+    mxf_metadata_structural_component_class_init
+    (MXFMetadataStructuralComponentClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+
+  metadata_base_class->handle_tag =
+      mxf_metadata_structural_component_handle_tag;
+}
+
+G_DEFINE_TYPE (MXFMetadataTimecodeComponent, mxf_metadata_timecode_component,
+    MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
+
+static gboolean
+mxf_metadata_timecode_component_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataTimecodeComponent *self =
+      MXF_METADATA_TIMECODE_COMPONENT (metadata);
+  gboolean ret = TRUE;
+
+  switch (tag) {
+    case 0x1502:
+      if (tag_size != 2)
+        goto error;
+      self->rounded_timecode_base = GST_READ_UINT16_BE (tag_data);
+      GST_DEBUG ("  rounded timecode base = %u", self->rounded_timecode_base);
+      break;
+    case 0x1501:
+      if (tag_size != 8)
+        goto error;
+      self->start_timecode = GST_READ_UINT64_BE (tag_data);
+      GST_DEBUG ("  start timecode = %" G_GINT64_FORMAT, self->start_timecode);
+      break;
+    case 0x1503:
+      if (tag_size != 1)
+        goto error;
+      self->drop_frame = (GST_READ_UINT8 (tag_data) != 0);
+      GST_DEBUG ("  drop frame = %s", (self->drop_frame) ? "yes" : "no");
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_timecode_component_parent_class)->handle_tag (metadata,
+          primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid timecode component local tag 0x%04x of size %u", tag,
+      tag_size);
+
+  return FALSE;
+}
+
+static void
+mxf_metadata_timecode_component_init (MXFMetadataTimecodeComponent * self)
+{
+
+}
+
+static void
+mxf_metadata_timecode_component_class_init (MXFMetadataTimecodeComponentClass *
+    klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+
+  metadata_base_class->handle_tag = mxf_metadata_timecode_component_handle_tag;
+}
+
+G_DEFINE_TYPE (MXFMetadataSourceClip, mxf_metadata_source_clip,
+    MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
+
+static gboolean
+mxf_metadata_source_clip_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (metadata);
+  gboolean ret = TRUE;
+  gchar str[96];
+
+  switch (tag) {
+    case 0x1201:
+      if (tag_size != 8)
+        goto error;
+
+      self->start_position = GST_READ_UINT64_BE (tag_data);
+      GST_DEBUG ("  start position = %" G_GINT64_FORMAT, self->start_position);
+      break;
+    case 0x1101:
+      if (tag_size != 32)
+        goto error;
+
+      memcpy (&self->source_package_id, tag_data, 32);
+      GST_DEBUG ("  source package id = %s",
+          mxf_umid_to_string (&self->source_package_id, str));
+      break;
+    case 0x1102:
+      if (tag_size != 4)
+        goto error;
+
+      self->source_track_id = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  source track id = %u", self->source_track_id);
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_source_clip_parent_class)->handle_tag (metadata, primer,
+          tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid source clip local tag 0x%04x of size %u", tag, tag_size);
+
+  return FALSE;
+}
+
+static gboolean
+mxf_metadata_source_clip_resolve (MXFMetadataBase * m,
+    MXFMetadataBase ** metadata)
+{
+  MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (m);
+  MXFMetadataBase **p, *current;
+
+  p = metadata;
+  while (*p) {
+    current = *p;
+    if (MXF_IS_METADATA_SOURCE_PACKAGE (current)) {
+      MXFMetadataGenericPackage *p = MXF_METADATA_GENERIC_PACKAGE (current);
+
+      if (mxf_umid_is_equal (&p->package_uid, &self->source_package_id)) {
+        self->source_package = MXF_METADATA_SOURCE_PACKAGE (current);
+        break;
+      }
+    }
+    p++;
+  }
+
+  return MXF_METADATA_BASE_CLASS (mxf_metadata_source_clip_parent_class)->
+      resolve (m, metadata);
+}
+
+static void
+mxf_metadata_source_clip_init (MXFMetadataSourceClip * self)
+{
+
+}
+
+static void
+mxf_metadata_source_clip_class_init (MXFMetadataSourceClipClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+
+  metadata_base_class->handle_tag = mxf_metadata_source_clip_handle_tag;
+  metadata_base_class->resolve = mxf_metadata_source_clip_resolve;
+}
+
+G_DEFINE_TYPE (MXFMetadataDMSourceClip, mxf_metadata_dm_source_clip,
+    MXF_TYPE_METADATA_SOURCE_CLIP);
+
+static void
+mxf_metadata_dm_source_clip_finalize (GstMiniObject * object)
+{
+  MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (object);
+
+  g_free (self->track_ids);
+  self->track_ids = NULL;
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_dm_source_clip_parent_class)->finalize
+      (object);
+}
+
+static gboolean
+mxf_metadata_dm_source_clip_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (metadata);
+  gboolean ret = TRUE;
+
+  switch (tag) {
+    case 0x6103:
+    {
+      guint32 len;
+      guint i;
+
+      if (tag_size < 8)
+        goto error;
+
+      len = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  number of track ids = %u", len);
+      if (len == 0)
+        return TRUE;
+
+      if (GST_READ_UINT32_BE (tag_data + 4) != 4)
+        goto error;
+
+      if (tag_size < 8 + 4 * len)
+        goto error;
+
+      tag_data += 8;
+      tag_size -= 8;
+
+      self->n_track_ids = len;
+      self->track_ids = g_new0 (guint32, len);
+
+      for (i = 0; i < len; i++) {
+        self->track_ids[i] = GST_READ_UINT32_BE (tag_data);
+        GST_DEBUG ("    track id %u = %u", i, self->track_ids[i]);
+        tag_data += 4;
+        tag_size -= 4;
+      }
+      break;
+    }
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_dm_source_clip_parent_class)->handle_tag (metadata,
+          primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid DM source clip local tag 0x%04x of size %u", tag,
+      tag_size);
+
+  return FALSE;
+}
+
+static void
+mxf_metadata_dm_source_clip_init (MXFMetadataDMSourceClip * self)
+{
+
+}
+
+static void
+mxf_metadata_dm_source_clip_class_init (MXFMetadataDMSourceClipClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_dm_source_clip_finalize;
+  metadata_base_class->handle_tag = mxf_metadata_dm_source_clip_handle_tag;
+}
+
+G_DEFINE_TYPE (MXFMetadataDMSegment, mxf_metadata_dm_segment,
+    MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
+
+static void
+mxf_metadata_dm_segment_finalize (GstMiniObject * object)
+{
+  MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (object);
+
+  g_free (self->track_ids);
+  self->track_ids = NULL;
+
+  g_free (self->event_comment);
+  self->event_comment = NULL;
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_dm_segment_parent_class)->finalize
+      (object);
+}
+
+static gboolean
+mxf_metadata_dm_segment_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (metadata);
+  gboolean ret = TRUE;
+  gchar str[48];
+
+  switch (tag) {
+    case 0x0601:
+      if (tag_size != 8)
+        goto error;
+      self->event_start_position = GST_READ_UINT64_BE (tag_data);
+      GST_DEBUG ("  event start position = %" G_GINT64_FORMAT,
+          self->event_start_position);
+      break;
+    case 0x0602:
+      self->event_comment = mxf_utf16_to_utf8 (tag_data, tag_size);
+      GST_DEBUG ("  event comment = %s", GST_STR_NULL (self->event_comment));
+      break;
+    case 0x6102:
+    {
+      guint32 len;
+      guint i;
+
+      if (tag_size < 8)
+        goto error;
+      len = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  number of track ids = %u", len);
+      if (len == 0)
+        return TRUE;
+
+      if (GST_READ_UINT32_BE (tag_data + 4) != 4)
+        goto error;
+
+      if (len * 4 + 8 < tag_size)
+        goto error;
+
+      self->n_track_ids = len;
+      self->track_ids = g_new0 (guint32, len);
+
+      tag_data += 8;
+      tag_size -= 8;
+
+      for (i = 0; i < len; i++) {
+        self->track_ids[i] = GST_READ_UINT32_BE (tag_data);
+        GST_DEBUG ("    track id %u = %u", i, self->track_ids[i]);
+        tag_data += 4;
+        tag_size -= 4;
+      }
+      break;
+    }
+    case 0x6101:
+      if (tag_size != 16)
+        goto error;
+
+      memcpy (&self->dm_framework_uid, tag_data, 16);
+      GST_DEBUG ("  DM framework = %s",
+          mxf_ul_to_string (&self->dm_framework_uid, str));
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_dm_segment_parent_class)->handle_tag (metadata, primer,
+          tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid DM segment local tag 0x%04x of size %u", tag, tag_size);
+
+  return FALSE;
+}
+
+static gboolean
+mxf_metadata_dm_segment_resolve (MXFMetadataBase * m,
+    MXFMetadataBase ** metadata)
+{
+  MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (m);
+  MXFMetadataBase **p = metadata, *current;
+
+  while (*p) {
+    current = *p;
+
+    /* TODO: if (MXF_IS_DM_FRAMEWORK (current) && */
+    if (mxf_ul_is_equal (&current->instance_uid, &self->dm_framework_uid)) {
+      if (mxf_metadata_resolve (current, metadata)) {
+        self->dm_framework = current;
+      }
+      break;
+    }
+
+    p++;
+  }
+
+  if (!self->dm_framework) {
+    GST_ERROR ("Couldn't resolve DM framework");
+    return FALSE;
+  }
+
+  return MXF_METADATA_BASE_CLASS (mxf_metadata_dm_segment_parent_class)->
+      resolve (m, metadata);
+}
+
+static void
+mxf_metadata_dm_segment_init (MXFMetadataDMSegment * self)
+{
+
+}
+
+static void
+mxf_metadata_dm_segment_class_init (MXFMetadataDMSegmentClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_dm_segment_finalize;
+  metadata_base_class->handle_tag = mxf_metadata_dm_segment_handle_tag;
+  metadata_base_class->resolve = mxf_metadata_dm_segment_resolve;
+}
+
+G_DEFINE_ABSTRACT_TYPE (MXFMetadataGenericDescriptor,
+    mxf_metadata_generic_descriptor, MXF_TYPE_METADATA);
+
+static void
+mxf_metadata_generic_descriptor_finalize (GstMiniObject * object)
+{
+  MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (object);
+
+  g_free (self->locators_uids);
+  self->locators_uids = NULL;
+
+  g_free (self->locators);
+  self->locators = NULL;
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_generic_descriptor_parent_class)->finalize
+      (object);
+}
+
+static gboolean
+mxf_metadata_generic_descriptor_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataGenericDescriptor *self =
+      MXF_METADATA_GENERIC_DESCRIPTOR (metadata);
+  gboolean ret = TRUE;
+  gchar str[48];
+
+  switch (tag) {
+    case 0x2f01:{
+      guint32 len;
+      guint i;
+
+      if (tag_size < 8)
+        goto error;
+
+      len = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  number of locators = %u", len);
+      if (len == 0)
+        return TRUE;
+
+      if (GST_READ_UINT32_BE (tag_data + 4) != 16)
+        goto error;
+
+      self->locators_uids = g_new (MXFUL, len);
+      self->n_locators = len;
+      for (i = 0; i < len; i++) {
+        memcpy (&self->locators_uids[i], tag_data + 8 + i * 16, 16);
+        GST_DEBUG ("  locator %u = %s", i,
+            mxf_ul_to_string (&self->locators_uids[i], str));
+      }
+      break;
+    }
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_generic_descriptor_parent_class)->handle_tag (metadata,
+          primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid generic descriptor local tag 0x%04x of size %u", tag,
+      tag_size);
+
+  return FALSE;
+}
+
+static gboolean
+mxf_metadata_generic_descriptor_resolve (MXFMetadataBase * m,
+    MXFMetadataBase ** metadata)
+{
+  MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (m);
+  MXFMetadataBase **p, *current;
+  guint i;
+  gboolean have_locator = FALSE;
+
+  self->locators = g_new0 (MXFMetadataLocator *, self->n_locators);
+  for (i = 0; i < self->n_locators; i++) {
+    p = metadata;
+    while (*p) {
+      current = *p;
+
+      if (MXF_IS_METADATA_LOCATOR (current) &&
+          mxf_ul_is_equal (&current->instance_uid, &self->locators_uids[i])) {
+        if (mxf_metadata_resolve (current, metadata)) {
+          self->locators[i] = MXF_METADATA_LOCATOR (current);
+          have_locator = TRUE;
+        }
+        break;
+      }
+      p++;
+    }
+  }
+
+  if (!have_locator && self->n_locators > 0) {
+    GST_ERROR ("Couldn't resolve a locator");
+    return FALSE;
+  }
+
+  return
+      MXF_METADATA_BASE_CLASS (mxf_metadata_generic_descriptor_parent_class)->
+      resolve (m, metadata);
+}
+
+static void
+mxf_metadata_generic_descriptor_init (MXFMetadataGenericDescriptor * self)
+{
+
+}
+
+static void
+mxf_metadata_generic_descriptor_class_init (MXFMetadataGenericDescriptorClass *
+    klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_generic_descriptor_finalize;
+  metadata_base_class->handle_tag = mxf_metadata_generic_descriptor_handle_tag;
+  metadata_base_class->resolve = mxf_metadata_generic_descriptor_resolve;
+}
+
+G_DEFINE_TYPE (MXFMetadataFileDescriptor, mxf_metadata_file_descriptor,
+    MXF_TYPE_METADATA_GENERIC_DESCRIPTOR);
+
+static gboolean
+mxf_metadata_file_descriptor_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataFileDescriptor *self = MXF_METADATA_FILE_DESCRIPTOR (metadata);
+  gboolean ret = TRUE;
+  gchar str[48];
+
+  switch (tag) {
+    case 0x3006:
+      if (tag_size != 4)
+        goto error;
+      self->linked_track_id = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  linked track id = %u", self->linked_track_id);
+      break;
+    case 0x3001:
+      if (!mxf_fraction_parse (&self->sample_rate, tag_data, tag_size))
+        goto error;
+      GST_DEBUG ("  sample rate = %d/%d", self->sample_rate.n,
+          self->sample_rate.d);
+      break;
+    case 0x3002:
+      if (tag_size != 8)
+        goto error;
+      self->container_duration = GST_READ_UINT64_BE (tag_data);
+      GST_DEBUG ("  container duration = %" G_GINT64_FORMAT,
+          self->container_duration);
+      break;
+    case 0x3004:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->essence_container, tag_data, 16);
+      GST_DEBUG ("  essence container = %s",
+          mxf_ul_to_string (&self->essence_container, str));
+      break;
+    case 0x3005:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->codec, tag_data, 16);
+      GST_DEBUG ("  codec = %s", mxf_ul_to_string (&self->codec, str));
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_file_descriptor_parent_class)->handle_tag (metadata,
+          primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid file descriptor local tag 0x%04x of size %u", tag,
+      tag_size);
+
+  return FALSE;
+}
+
+static void
+mxf_metadata_file_descriptor_init (MXFMetadataFileDescriptor * self)
+{
+
+}
+
+static void
+mxf_metadata_file_descriptor_class_init (MXFMetadataFileDescriptorClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+
+  metadata_base_class->handle_tag = mxf_metadata_file_descriptor_handle_tag;
+}
+
+G_DEFINE_TYPE (MXFMetadataGenericPictureEssenceDescriptor,
+    mxf_metadata_generic_picture_essence_descriptor,
+    MXF_TYPE_METADATA_FILE_DESCRIPTOR);
+
+static gboolean
+mxf_metadata_generic_picture_essence_descriptor_handle_tag (MXFMetadataBase *
+    metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataGenericPictureEssenceDescriptor *self =
+      MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (metadata);
+  gboolean ret = TRUE;
+  gchar str[48];
+
+  switch (tag) {
+    case 0x3215:
+      if (tag_size != 1)
+        goto error;
+      self->signal_standard = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  signal standard = %u", self->signal_standard);
+      break;
+    case 0x320c:
+      if (tag_size != 1)
+        goto error;
+      self->frame_layout = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  frame layout = %u", self->frame_layout);
+      break;
+    case 0x3203:
+      if (tag_size != 4)
+        goto error;
+      self->stored_width = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  stored width = %u", self->stored_width);
+      break;
+    case 0x3202:
+      if (tag_size != 4)
+        goto error;
+      self->stored_height = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  stored height = %u", self->stored_height);
+      break;
+    case 0x3216:
+      if (tag_size != 4)
+        goto error;
+      self->stored_f2_offset = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  stored f2 offset = %d", self->stored_f2_offset);
+      break;
+    case 0x3205:
+      if (tag_size != 4)
+        goto error;
+      self->sampled_width = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  sampled width = %u", self->sampled_width);
+      break;
+    case 0x3204:
+      if (tag_size != 4)
+        goto error;
+      self->sampled_height = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  sampled height = %u", self->sampled_height);
+      break;
+    case 0x3206:
+      if (tag_size != 4)
+        goto error;
+      self->sampled_x_offset = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  sampled x offset = %d", self->sampled_x_offset);
+      break;
+    case 0x3207:
+      if (tag_size != 4)
+        goto error;
+      self->sampled_y_offset = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  sampled y offset = %d", self->sampled_y_offset);
+      break;
+    case 0x3208:
+      if (tag_size != 4)
+        goto error;
+      self->display_height = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  display height = %u", self->display_height);
+      break;
+    case 0x3209:
+      if (tag_size != 4)
+        goto error;
+      self->display_width = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  display width = %u", self->display_width);
+      break;
+    case 0x320a:
+      if (tag_size != 4)
+        goto error;
+      self->display_x_offset = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  display x offset = %d", self->display_x_offset);
+      break;
+    case 0x320b:
+      if (tag_size != 4)
+        goto error;
+      self->display_y_offset = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  display y offset = %d", self->display_y_offset);
+      break;
+    case 0x3217:
+      if (tag_size != 4)
+        goto error;
+      self->display_f2_offset = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  display f2 offset = %d", self->display_f2_offset);
+      break;
+    case 0x320e:
+      if (!mxf_fraction_parse (&self->aspect_ratio, tag_data, tag_size))
+        goto error;
+      GST_DEBUG ("  aspect ratio = %d/%d", self->aspect_ratio.n,
+          self->aspect_ratio.d);
+      break;
+    case 0x3218:
+      if (tag_size != 1)
+        goto error;
+      self->active_format_descriptor = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  active format descriptor = %u",
+          self->active_format_descriptor);
+      break;
+    case 0x320d:
+      if (tag_size < 8)
+        goto error;
+
+      if (GST_READ_UINT32_BE (tag_data) == 0)
+        return TRUE;
+
+      if (GST_READ_UINT32_BE (tag_data) != 2 &&
+          GST_READ_UINT32_BE (tag_data + 4) != 4)
+        goto error;
+
+      if (tag_size != 16)
+        goto error;
+
+      self->video_line_map[0] = GST_READ_UINT32_BE (tag_data + 8);
+      self->video_line_map[1] = GST_READ_UINT32_BE (tag_data + 12);
+      GST_DEBUG ("  video line map = {%i, %i}", self->video_line_map[0],
+          self->video_line_map[1]);
+      break;
+    case 0x320f:
+      if (tag_size != 1)
+        goto error;
+      self->alpha_transparency = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  alpha transparency = %u", self->alpha_transparency);
+      break;
+    case 0x3210:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->capture_gamma, tag_data, 16);
+      GST_DEBUG ("  capture gamma = %s",
+          mxf_ul_to_string (&self->capture_gamma, str));
+      break;
+    case 0x3211:
+      if (tag_size != 4)
+        goto error;
+      self->image_alignment_offset = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  image alignment offset = %u", self->image_alignment_offset);
+      break;
+    case 0x3213:
+      if (tag_size != 4)
+        goto error;
+      self->image_start_offset = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  image start offset = %u", self->image_start_offset);
+      break;
+    case 0x3214:
+      if (tag_size != 4)
+        goto error;
+      self->image_end_offset = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  image end offset = %u", self->image_end_offset);
+      break;
+    case 0x3212:
+      if (tag_size != 1)
+        goto error;
+      self->field_dominance = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  field dominance = %u", self->field_dominance);
+      break;
+    case 0x3201:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->picture_essence_coding, tag_data, 16);
+      GST_DEBUG ("  picture essence coding = %s",
+          mxf_ul_to_string (&self->picture_essence_coding, str));
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_generic_picture_essence_descriptor_parent_class)->
+          handle_tag (metadata, primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR
+      ("Invalid generic picture essence descriptor local tag 0x%04x of size %u",
+      tag, tag_size);
+
+  return FALSE;
+}
+
+static void
+    mxf_metadata_generic_picture_essence_descriptor_init
+    (MXFMetadataGenericPictureEssenceDescriptor * self)
+{
+  self->signal_standard = 1;
+}
+
+static void
+    mxf_metadata_generic_picture_essence_descriptor_class_init
+    (MXFMetadataGenericPictureEssenceDescriptorClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+
+  metadata_base_class->handle_tag =
+      mxf_metadata_generic_picture_essence_descriptor_handle_tag;
+}
+
+void mxf_metadata_generic_picture_essence_descriptor_set_caps
+    (MXFMetadataGenericPictureEssenceDescriptor * self, GstCaps * caps)
+{
+  guint par_n, par_d;
+  guint width, height;
+  MXFMetadataFileDescriptor *f = (MXFMetadataFileDescriptor *) self;
+
+  g_return_if_fail (MXF_IS_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (self));
+  g_return_if_fail (GST_IS_CAPS (caps));
+
+  gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, f->sample_rate.n,
+      f->sample_rate.d, NULL);
+
+  width = self->stored_width;
+  height = self->stored_height;
+
+  /* If the video is stored as separate fields the
+   * height is only the height of one field, i.e.
+   * half the height of the frame.
+   *
+   * See SMPTE 377M E2.2 and E1.2
+   */
+  if (self->frame_layout != 0)
+    height *= 2;
+
+  if (width == 0 || height == 0)
+    return;
+
+  gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height", G_TYPE_INT,
+      height, NULL);
+
+  if (self->aspect_ratio.n == 0 || self->aspect_ratio.d == 0)
+    return;
+
+  par_n = height * self->aspect_ratio.n;
+  par_d = width * self->aspect_ratio.d;
+
+  gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
+      par_n, par_d, NULL);
+}
+
+G_DEFINE_TYPE (MXFMetadataGenericSoundEssenceDescriptor,
+    mxf_metadata_generic_sound_essence_descriptor,
+    MXF_TYPE_METADATA_FILE_DESCRIPTOR);
+
+static gboolean
+mxf_metadata_generic_sound_essence_descriptor_handle_tag (MXFMetadataBase *
+    metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataGenericSoundEssenceDescriptor *self =
+      MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (metadata);
+  gboolean ret = TRUE;
+  gchar str[48];
+
+  switch (tag) {
+    case 0x3d03:
+      if (!mxf_fraction_parse (&self->audio_sampling_rate, tag_data, tag_size))
+        goto error;
+      GST_DEBUG ("  audio sampling rate = %d/%d",
+          self->audio_sampling_rate.n, self->audio_sampling_rate.d);
+      break;
+    case 0x3d02:
+      if (tag_size != 1)
+        goto error;
+      self->locked = (GST_READ_UINT8 (tag_data) != 0);
+      GST_DEBUG ("  locked = %s", (self->locked) ? "yes" : "no");
+      break;
+    case 0x3d04:
+      if (tag_size != 1)
+        goto error;
+      self->audio_ref_level = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  audio ref level = %d", self->audio_ref_level);
+      break;
+    case 0x3d05:
+      if (tag_size != 1)
+        goto error;
+      self->electro_spatial_formulation = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  electro spatial formulation = %u",
+          self->electro_spatial_formulation);
+      break;
+    case 0x3d07:
+      if (tag_size != 4)
+        goto error;
+      self->channel_count = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  channel count = %u", self->channel_count);
+      break;
+    case 0x3d01:
+      if (tag_size != 4)
+        goto error;
+      self->quantization_bits = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  quantization bits = %u", self->quantization_bits);
+      break;
+    case 0x3d0c:
+      if (tag_size != 1)
+        goto error;
+      self->dial_norm = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  dial norm = %d", self->dial_norm);
+      break;
+    case 0x3d06:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->sound_essence_compression, tag_data, 16);
+      GST_DEBUG ("  sound essence compression = %s",
+          mxf_ul_to_string (&self->sound_essence_compression, str));
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_generic_sound_essence_descriptor_parent_class)->
+          handle_tag (metadata, primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR
+      ("Invalid generic sound essence descriptor local tag 0x%04x of size %u",
+      tag, tag_size);
+
+  return FALSE;
+}
+
+static void
+    mxf_metadata_generic_sound_essence_descriptor_init
+    (MXFMetadataGenericSoundEssenceDescriptor * self)
+{
+  self->audio_sampling_rate.n = 48000;
+  self->audio_sampling_rate.d = 1;
+}
+
+static void
+    mxf_metadata_generic_sound_essence_descriptor_class_init
+    (MXFMetadataGenericSoundEssenceDescriptorClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+
+  metadata_base_class->handle_tag =
+      mxf_metadata_generic_sound_essence_descriptor_handle_tag;
+}
+
+G_DEFINE_TYPE (MXFMetadataCDCIPictureEssenceDescriptor,
+    mxf_metadata_cdci_picture_essence_descriptor,
+    MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
+
+static gboolean
+mxf_metadata_cdci_picture_essence_descriptor_handle_tag (MXFMetadataBase *
+    metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataCDCIPictureEssenceDescriptor *self =
+      MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR (metadata);
+  gboolean ret = TRUE;
+
+  switch (tag) {
+    case 0x3301:
+      if (tag_size != 4)
+        goto error;
+      self->component_depth = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  component depth = %u", self->component_depth);
+      break;
+    case 0x3302:
+      if (tag_size != 4)
+        goto error;
+      self->horizontal_subsampling = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  horizontal subsampling = %u", self->horizontal_subsampling);
+      break;
+    case 0x3308:
+      if (tag_size != 4)
+        goto error;
+      self->vertical_subsampling = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  vertical subsampling = %u", self->vertical_subsampling);
+      break;
+    case 0x3303:
+      if (tag_size != 1)
+        goto error;
+      self->color_siting = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  color siting = %u", self->color_siting);
+      break;
+    case 0x330b:
+      if (tag_size != 1)
+        goto error;
+      self->reversed_byte_order = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  reversed byte order = %s",
+          (self->reversed_byte_order) ? "yes" : "no");
+      break;
+    case 0x3307:
+      if (tag_size != 2)
+        goto error;
+      self->padding_bits = GST_READ_UINT16_BE (tag_data);
+      GST_DEBUG ("  padding bits = %d", self->padding_bits);
+      break;
+    case 0x3309:
+      if (tag_size != 4)
+        goto error;
+      self->alpha_sample_depth = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  alpha sample depth = %u", self->alpha_sample_depth);
+      break;
+    case 0x3304:
+      if (tag_size != 4)
+        goto error;
+      self->black_ref_level = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  black ref level = %u", self->black_ref_level);
+      break;
+    case 0x3305:
+      if (tag_size != 4)
+        goto error;
+      self->white_ref_level = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  white ref level = %u", self->white_ref_level);
+      break;
+    case 0x3306:
+      if (tag_size != 4)
+        goto error;
+      self->color_range = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  color range = %u", self->color_range);
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_cdci_picture_essence_descriptor_parent_class)->
+          handle_tag (metadata, primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR
+      ("Invalid CDCI picture essence descriptor local tag 0x%04x of size %u",
+      tag, tag_size);
+
+  return FALSE;
+}
+
+static void
+    mxf_metadata_cdci_picture_essence_descriptor_init
+    (MXFMetadataCDCIPictureEssenceDescriptor * self)
+{
+
+}
+
+static void
+    mxf_metadata_cdci_picture_essence_descriptor_class_init
+    (MXFMetadataCDCIPictureEssenceDescriptorClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+
+  metadata_base_class->handle_tag =
+      mxf_metadata_cdci_picture_essence_descriptor_handle_tag;
+}
+
+G_DEFINE_TYPE (MXFMetadataRGBAPictureEssenceDescriptor,
+    mxf_metadata_rgba_picture_essence_descriptor,
+    MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
+
+static void
+mxf_metadata_rgba_picture_essence_descriptor_finalize (GstMiniObject * object)
+{
+  MXFMetadataRGBAPictureEssenceDescriptor *self =
+      MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (object);
+
+  g_free (self->pixel_layout);
+  self->pixel_layout = NULL;
+
+  GST_MINI_OBJECT_CLASS
+      (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->finalize
+      (object);
+}
+
+static gboolean
+mxf_metadata_rgba_picture_essence_descriptor_handle_tag (MXFMetadataBase *
+    metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataRGBAPictureEssenceDescriptor *self =
+      MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (metadata);
+  gboolean ret = TRUE;
+
+  switch (tag) {
+    case 0x3406:
+      if (tag_size != 4)
+        goto error;
+      self->component_max_ref = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  component max ref = %u", self->component_max_ref);
+      break;
+    case 0x3407:
+      if (tag_size != 4)
+        goto error;
+      self->component_min_ref = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  component min ref = %u", self->component_min_ref);
+      break;
+    case 0x3408:
+      if (tag_size != 4)
+        goto error;
+      self->alpha_max_ref = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  alpha max ref = %u", self->alpha_max_ref);
+      break;
+    case 0x3409:
+      if (tag_size != 4)
+        goto error;
+      self->alpha_min_ref = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  alpha min ref = %u", self->alpha_min_ref);
+      break;
+    case 0x3405:
+      if (tag_size != 1)
+        goto error;
+      self->scanning_direction = GST_READ_UINT8 (tag_data);
+      GST_DEBUG ("  scanning direction = %u", self->scanning_direction);
+      break;
+    case 0x3401:{
+      guint i, len;
+
+      if (tag_size % 2 != 0)
+        goto error;
+
+      i = 0;
+      while (tag_data[i] != 0 && tag_data[i + 1] != 0 && i + 2 <= tag_size)
+        i += 2;
+      len = i / 2;
+
+      self->n_pixel_layout = len;
+      GST_DEBUG ("  number of pixel layouts = %u", len);
+      if (len == 0)
+        return TRUE;
+
+      self->pixel_layout = g_malloc0 (2 * len);
+
+      for (i = 0; i < len; i++) {
+        self->pixel_layout[2 * i] = tag_data[2 * i];
+        self->pixel_layout[2 * i + 1] = tag_data[2 * i + 1];
+        GST_DEBUG ("    pixel layout %u = %c : %u", i,
+            (gchar) self->pixel_layout[2 * i], self->pixel_layout[2 * i + 1]);
+      }
+
+      break;
+    }
+    case 0x3403:
+    case 0x3404:
+      /* TODO: handle this */
+      GST_WARNING ("  tag 0x%04x not implemented yet", tag);
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->
+          handle_tag (metadata, primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR
+      ("Invalid RGBA picture essence descriptor local tag 0x%04x of size %u",
+      tag, tag_size);
+
+  return FALSE;
+}
+
+static void
+    mxf_metadata_rgba_picture_essence_descriptor_init
+    (MXFMetadataRGBAPictureEssenceDescriptor * self)
+{
+  self->component_max_ref = 255;
+  self->alpha_max_ref = 255;
+}
+
+static void
+    mxf_metadata_rgba_picture_essence_descriptor_class_init
+    (MXFMetadataRGBAPictureEssenceDescriptorClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize =
+      mxf_metadata_rgba_picture_essence_descriptor_finalize;
+  metadata_base_class->handle_tag =
+      mxf_metadata_rgba_picture_essence_descriptor_handle_tag;
+}
+
+G_DEFINE_TYPE (MXFMetadataGenericDataEssenceDescriptor,
+    mxf_metadata_generic_data_essence_descriptor,
+    MXF_TYPE_METADATA_FILE_DESCRIPTOR);
+
+static gboolean
+mxf_metadata_generic_data_essence_descriptor_handle_tag (MXFMetadataBase *
+    metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataGenericDataEssenceDescriptor *self =
+      MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR (metadata);
+  gboolean ret = TRUE;
+  gchar str[48];
+
+  switch (tag) {
+    case 0x3e01:
+      if (tag_size != 16)
+        goto error;
+      memcpy (&self->data_essence_compression, tag_data, 16);
+      GST_DEBUG ("  data essence compression = %s",
+          mxf_ul_to_string (&self->data_essence_compression, str));
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_generic_data_essence_descriptor_parent_class)->
+          handle_tag (metadata, primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR
+      ("Invalid generic data essence descriptor local tag 0x%04x of size %u",
+      tag, tag_size);
+
+  return FALSE;
+}
+
+static void
+    mxf_metadata_generic_data_essence_descriptor_init
+    (MXFMetadataGenericDataEssenceDescriptor * self)
+{
+
+}
+
+static void
+    mxf_metadata_generic_data_essence_descriptor_class_init
+    (MXFMetadataGenericDataEssenceDescriptorClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+
+  metadata_base_class->handle_tag =
+      mxf_metadata_generic_data_essence_descriptor_handle_tag;
+}
+
+G_DEFINE_TYPE (MXFMetadataMultipleDescriptor, mxf_metadata_multiple_descriptor,
+    MXF_TYPE_METADATA_FILE_DESCRIPTOR);
+
+static void
+mxf_metadata_multiple_descriptor_finalize (GstMiniObject * object)
+{
+  MXFMetadataMultipleDescriptor *self =
+      MXF_METADATA_MULTIPLE_DESCRIPTOR (object);
+
+  g_free (self->sub_descriptors_uids);
+  self->sub_descriptors_uids = NULL;
+  g_free (self->sub_descriptors);
+  self->sub_descriptors = NULL;
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_multiple_descriptor_parent_class)->
+      finalize (object);
+}
+
+static gboolean
+mxf_metadata_multiple_descriptor_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataMultipleDescriptor *self =
+      MXF_METADATA_MULTIPLE_DESCRIPTOR (metadata);
+  gboolean ret = TRUE;
+  gchar str[48];
+
+  switch (tag) {
+    case 0x3f01:{
+      guint32 len;
+      guint i;
+
+      if (tag_size < 8)
+        goto error;
+      len = GST_READ_UINT32_BE (tag_data);
+      GST_DEBUG ("  number of sub descriptors = %u", len);
+      if (len == 0)
+        return TRUE;
+
+      if (GST_READ_UINT32_BE (tag_data + 4) != 16)
+        goto error;
+
+      tag_data += 8;
+      tag_size -= 8;
+      if (tag_size < len * 16)
+        goto error;
+
+      self->n_sub_descriptors = len;
+      self->sub_descriptors_uids = g_new (MXFUL, len);
+      for (i = 0; i < len; i++) {
+        memcpy (&self->sub_descriptors_uids[i], tag_data, 16);
+        tag_data += 16;
+        tag_size -= 16;
+        GST_DEBUG ("    sub descriptor %u = %s", i,
+            mxf_ul_to_string (&self->sub_descriptors_uids[i], str));
+      }
+
+      break;
+    }
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_multiple_descriptor_parent_class)->handle_tag (metadata,
+          primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+
+error:
+
+  GST_ERROR ("Invalid multiple descriptor local tag 0x%04x of size %u", tag,
+      tag_size);
+
+  return TRUE;
+}
+
+static gboolean
+mxf_metadata_multiple_descriptor_resolve (MXFMetadataBase * m,
+    MXFMetadataBase ** metadata)
+{
+  MXFMetadataMultipleDescriptor *self = MXF_METADATA_MULTIPLE_DESCRIPTOR (m);
+  MXFMetadataBase **p, *current;
+  guint i, have_subdescriptors = 0;
+
+  self->sub_descriptors =
+      g_new0 (MXFMetadataGenericDescriptor *, self->n_sub_descriptors);
+  for (i = 0; i < self->n_sub_descriptors; i++) {
+    p = metadata;
+    while (*p) {
+      current = *p;
+      if (MXF_IS_METADATA_GENERIC_DESCRIPTOR (current) &&
+          mxf_ul_is_equal (&current->instance_uid,
+              &self->sub_descriptors_uids[i])) {
+        if (mxf_metadata_resolve (current, metadata)) {
+          self->sub_descriptors[i] = MXF_METADATA_GENERIC_DESCRIPTOR (current);
+          have_subdescriptors++;
+        }
+        break;
+      }
+      p++;
+    }
+  }
+
+  if (have_subdescriptors != self->n_sub_descriptors) {
+    GST_ERROR ("Couldn't resolve all subdescriptors");
+    return FALSE;
+  }
+
+  return
+      MXF_METADATA_BASE_CLASS (mxf_metadata_multiple_descriptor_parent_class)->
+      resolve (m, metadata);
+}
+
+static void
+mxf_metadata_multiple_descriptor_init (MXFMetadataMultipleDescriptor * self)
+{
+
+}
+
+static void
+mxf_metadata_multiple_descriptor_class_init (MXFMetadataMultipleDescriptorClass
+    * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_multiple_descriptor_finalize;
+  metadata_base_class->handle_tag = mxf_metadata_multiple_descriptor_handle_tag;
+  metadata_base_class->resolve = mxf_metadata_multiple_descriptor_resolve;
+}
+
+G_DEFINE_ABSTRACT_TYPE (MXFMetadataLocator, mxf_metadata_locator,
+    MXF_TYPE_METADATA);
+
+static void
+mxf_metadata_locator_init (MXFMetadataLocator * self)
+{
+}
+
+static void
+mxf_metadata_locator_class_init (MXFMetadataLocatorClass * klass)
+{
+}
+
+G_DEFINE_TYPE (MXFMetadataTextLocator, mxf_metadata_text_locator,
+    MXF_TYPE_METADATA_LOCATOR);
+
+static void
+mxf_metadata_text_locator_finalize (GstMiniObject * object)
+{
+  MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (object);
+
+  g_free (self->locator_name);
+  self->locator_name = NULL;
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_text_locator_parent_class)->finalize
+      (object);
+}
+
+static gboolean
+mxf_metadata_text_locator_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (metadata);
+  gboolean ret = TRUE;
+
+  switch (tag) {
+    case 0x4101:
+      self->locator_name = mxf_utf16_to_utf8 (tag_data, tag_size);
+      GST_DEBUG ("  text locator = %s", GST_STR_NULL (self->locator_name));
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_text_locator_parent_class)->handle_tag (metadata,
+          primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+}
+
+static void
+mxf_metadata_text_locator_init (MXFMetadataTextLocator * self)
+{
+
+}
+
+static void
+mxf_metadata_text_locator_class_init (MXFMetadataTextLocatorClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_text_locator_finalize;
+  metadata_base_class->handle_tag = mxf_metadata_text_locator_handle_tag;
+}
+
+G_DEFINE_TYPE (MXFMetadataNetworkLocator, mxf_metadata_network_locator,
+    MXF_TYPE_METADATA_LOCATOR);
+
+static void
+mxf_metadata_network_locator_finalize (GstMiniObject * object)
+{
+  MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (object);
+
+  g_free (self->url_string);
+  self->url_string = NULL;
+
+  GST_MINI_OBJECT_CLASS (mxf_metadata_network_locator_parent_class)->finalize
+      (object);
+}
+
+static gboolean
+mxf_metadata_network_locator_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
+{
+  MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (metadata);
+  gboolean ret = TRUE;
+
+  switch (tag) {
+    case 0x4101:
+      self->url_string = mxf_utf16_to_utf8 (tag_data, tag_size);
+      GST_DEBUG ("  url string = %s", GST_STR_NULL (self->url_string));
+      break;
+    default:
+      ret =
+          MXF_METADATA_BASE_CLASS
+          (mxf_metadata_network_locator_parent_class)->handle_tag (metadata,
+          primer, tag, tag_data, tag_size);
+      break;
+  }
+
+  return ret;
+}
+
+static void
+mxf_metadata_network_locator_init (MXFMetadataNetworkLocator * self)
+{
+}
+
+static void
+mxf_metadata_network_locator_class_init (MXFMetadataNetworkLocatorClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
+  GstMiniObjectClass *miniobject_class = (GstMiniObjectClass *) klass;
+
+  miniobject_class->finalize = mxf_metadata_network_locator_finalize;
+  metadata_base_class->handle_tag = mxf_metadata_network_locator_handle_tag;
+}
diff --git a/gst/mxf/mxfmetadata.h b/gst/mxf/mxfmetadata.h
new file mode 100644 (file)
index 0000000..e24ce88
--- /dev/null
@@ -0,0 +1,703 @@
+/* GStreamer
+ * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Handling of MXF structural metadata */
+
+#ifndef __MXF_METADATA_H__
+#define __MXF_METADATA_H__
+
+#include <gst/gst.h>
+#include "mxftypes.h"
+
+#define MXF_TYPE_METADATA_BASE \
+  (mxf_metadata_base_get_type())
+#define MXF_METADATA_BASE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_BASE, MXFMetadataBase))
+#define MXF_IS_METADATA_BASE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_BASE))
+#define MXF_METADATA_BASE_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), MXF_TYPE_METADATA_BASE, MXFMetadataBaseClass))
+#define MXF_METADATA_BASE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),MXF_TYPE_METADATA_BASE,MXFMetadataBaseClass))
+typedef struct _MXFMetadataBase MXFMetadataBase;
+typedef struct _MXFMetadataBaseClass MXFMetadataBaseClass;
+GType mxf_metadata_base_get_type (void);
+
+#define MXF_TYPE_METADATA \
+  (mxf_metadata_get_type())
+#define MXF_METADATA(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA, MXFMetadata))
+#define MXF_IS_METADATA(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA))
+#define MXF_METADATA_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), MXF_TYPE_METADATA, MXFMetadataClass))
+#define MXF_METADATA_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),MXF_TYPE_METADATA,MXFMetadataClass))
+typedef struct _MXFMetadata MXFMetadata;
+typedef MXFMetadataBaseClass MXFMetadataClass;
+GType mxf_metadata_get_type (void);
+
+#define MXF_TYPE_METADATA_PREFACE \
+  (mxf_metadata_preface_get_type())
+#define MXF_METADATA_PREFACE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_PREFACE,MXFMetadataPreface))
+#define MXF_IS_METADATA_PREFACE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_PREFACE))
+typedef struct _MXFMetadataPreface MXFMetadataPreface;
+typedef MXFMetadataBaseClass MXFMetadataPrefaceClass;
+GType mxf_metadata_preface_get_type (void);
+
+#define MXF_TYPE_METADATA_IDENTIFICATION \
+  (mxf_metadata_identification_get_type())
+#define MXF_METADATA_IDENTIFICATION(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_IDENTIFICATION,MXFMetadataIdentification))
+#define MXF_IS_METADATA_IDENTIFICATION(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_IDENTIFICATION))
+typedef struct _MXFMetadataIdentification MXFMetadataIdentification;
+typedef MXFMetadataBaseClass MXFMetadataIdentificationClass;
+GType mxf_metadata_identification_get_type (void);
+
+#define MXF_TYPE_METADATA_CONTENT_STORAGE \
+  (mxf_metadata_content_storage_get_type())
+#define MXF_METADATA_CONTENT_STORAGE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_CONTENT_STORAGE, MXFMetadataContentStorage))
+#define MXF_IS_METADATA_CONTENT_STORAGE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_CONTENT_STORAGE))
+typedef struct _MXFMetadataContentStorage MXFMetadataContentStorage;
+typedef MXFMetadataBaseClass MXFMetadataContentStorageClass;
+GType mxf_metadata_content_storage_get_type (void);
+
+#define MXF_TYPE_METADATA_ESSENCE_CONTAINER_DATA \
+  (mxf_metadata_essence_container_data_get_type())
+#define MXF_METADATA_ESSENCE_CONTAINER_DATA(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_ESSENCE_CONTAINER_DATA, MXFMetadataEssenceContainerData))
+#define MXF_IS_METADATA_ESSENCE_CONTAINER_DATA(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_ESSENCE_CONTAINER_DATA))
+typedef struct _MXFMetadataEssenceContainerData MXFMetadataEssenceContainerData;
+typedef MXFMetadataBaseClass MXFMetadataEssenceContainerDataClass;
+GType mxf_metadata_essence_container_data_get_type (void);
+
+#define MXF_TYPE_METADATA_GENERIC_PACKAGE \
+  (mxf_metadata_generic_package_get_type())
+#define MXF_METADATA_GENERIC_PACKAGE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_GENERIC_PACKAGE, MXFMetadataGenericPackage))
+#define MXF_IS_METADATA_GENERIC_PACKAGE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_GENERIC_PACKAGE))
+typedef struct _MXFMetadataGenericPackage MXFMetadataGenericPackage;
+typedef MXFMetadataBaseClass MXFMetadataGenericPackageClass;
+GType mxf_metadata_generic_package_get_type (void);
+
+#define MXF_TYPE_METADATA_MATERIAL_PACKAGE \
+  (mxf_metadata_material_package_get_type())
+#define MXF_METADATA_MATERIAL_PACKAGE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_MATERIAL_PACKAGE, MXFMetadataMaterialPackage))
+#define MXF_IS_METADATA_MATERIAL_PACKAGE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_MATERIAL_PACKAGE))
+typedef MXFMetadataGenericPackage MXFMetadataMaterialPackage;
+typedef MXFMetadataBaseClass MXFMetadataMaterialPackageClass;
+GType mxf_metadata_material_package_get_type (void);
+
+#define MXF_TYPE_METADATA_SOURCE_PACKAGE \
+  (mxf_metadata_source_package_get_type())
+#define MXF_METADATA_SOURCE_PACKAGE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_SOURCE_PACKAGE, MXFMetadataSourcePackage))
+#define MXF_IS_METADATA_SOURCE_PACKAGE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_SOURCE_PACKAGE))
+typedef struct _MXFMetadataSourcePackage MXFMetadataSourcePackage;
+typedef MXFMetadataBaseClass MXFMetadataSourcePackageClass;
+GType mxf_metadata_source_package_get_type (void);
+
+#define MXF_TYPE_METADATA_TRACK \
+  (mxf_metadata_track_get_type())
+#define MXF_METADATA_TRACK(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_TRACK, MXFMetadataTrack))
+#define MXF_IS_METADATA_TRACK(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_TRACK))
+typedef struct _MXFMetadataTrack MXFMetadataTrack;
+typedef MXFMetadataBaseClass MXFMetadataTrackClass;
+GType mxf_metadata_track_get_type (void);
+
+#define MXF_TYPE_METADATA_TIMELINE_TRACK \
+  (mxf_metadata_timeline_track_get_type())
+#define MXF_METADATA_TIMELINE_TRACK(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_TIMELINE_TRACK, MXFMetadataTimelineTrack))
+#define MXF_IS_METADATA_TIMELINE_TRACK(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_TIMELINE_TRACK))
+typedef struct _MXFMetadataTimelineTrack MXFMetadataTimelineTrack;
+typedef MXFMetadataBaseClass MXFMetadataTimelineTrackClass;
+GType mxf_metadata_timeline_track_get_type (void);
+
+#define MXF_TYPE_METADATA_EVENT_TRACK \
+  (mxf_metadata_event_track_get_type())
+#define MXF_METADATA_EVENT_TRACK(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_EVENT_TRACK, MXFMetadataEventTrack))
+#define MXF_IS_METADATA_EVENT_TRACK(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_EVENT_TRACK))
+typedef struct _MXFMetadataEventTrack MXFMetadataEventTrack;
+typedef MXFMetadataBaseClass MXFMetadataEventTrackClass;
+GType mxf_metadata_event_track_get_type (void);
+
+#define MXF_TYPE_METADATA_STATIC_TRACK \
+  (mxf_metadata_static_track_get_type())
+#define MXF_METADATA_STATIC_TRACK(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_STATIC_TRACK, MXFMetadataStaticTrack))
+#define MXF_IS_METADATA_STATIC_TRACK(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_STATIC_TRACK))
+typedef MXFMetadataTrack MXFMetadataStaticTrack;
+typedef MXFMetadataBaseClass MXFMetadataStaticTrackClass;
+GType mxf_metadata_static_track_get_type (void);
+
+#define MXF_TYPE_METADATA_SEQUENCE \
+  (mxf_metadata_sequence_get_type())
+#define MXF_METADATA_SEQUENCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_SEQUENCE, MXFMetadataSequence))
+#define MXF_IS_METADATA_SEQUENCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_SEQUENCE))
+typedef struct _MXFMetadataSequence MXFMetadataSequence;
+typedef MXFMetadataBaseClass MXFMetadataSequenceClass;
+GType mxf_metadata_sequence_get_type (void);
+
+#define MXF_TYPE_METADATA_STRUCTURAL_COMPONENT \
+  (mxf_metadata_structural_component_get_type())
+#define MXF_METADATA_STRUCTURAL_COMPONENT(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_STRUCTURAL_COMPONENT, MXFMetadataStructuralComponent))
+#define MXF_IS_METADATA_STRUCTURAL_COMPONENT(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_STRUCTURAL_COMPONENT))
+typedef struct _MXFMetadataStructuralComponent MXFMetadataStructuralComponent;
+typedef MXFMetadataBaseClass MXFMetadataStructuralComponentClass;
+GType mxf_metadata_structural_component_get_type (void);
+
+#define MXF_TYPE_METADATA_SOURCE_CLIP \
+  (mxf_metadata_source_clip_get_type())
+#define MXF_METADATA_SOURCE_CLIP(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_SOURCE_CLIP, MXFMetadataSourceClip))
+#define MXF_IS_METADATA_SOURCE_CLIP(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_SOURCE_CLIP))
+typedef struct _MXFMetadataSourceClip MXFMetadataSourceClip;
+typedef MXFMetadataBaseClass MXFMetadataSourceClipClass;
+GType mxf_metadata_source_clip_get_type (void);
+
+#define MXF_TYPE_METADATA_TIMECODE_COMPONENT \
+  (mxf_metadata_timecode_component_get_type())
+#define MXF_METADATA_TIMECODE_COMPONENT(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_TIMECODE_COMPONENT, MXFMetadataTimecodeComponent))
+#define MXF_IS_METADATA_TIMECODE_COMPONENT(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_TIMECODE_COMPONENT))
+typedef struct _MXFMetadataTimecodeComponent MXFMetadataTimecodeComponent;
+typedef MXFMetadataBaseClass MXFMetadataTimecodeComponentClass;
+GType mxf_metadata_timecode_component_get_type (void);
+
+#define MXF_TYPE_METADATA_DM_SOURCE_CLIP \
+  (mxf_metadata_dm_source_clip_get_type())
+#define MXF_METADATA_DM_SOURCE_CLIP(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_DM_SOURCE_CLIP, MXFMetadataDMSourceClip))
+#define MXF_IS_METADATA_DM_SOURCE_CLIP(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_DM_SOURCE_CLIP))
+typedef struct _MXFMetadataDMSourceClip MXFMetadataDMSourceClip;
+typedef MXFMetadataBaseClass MXFMetadataDMSourceClipClass;
+GType mxf_metadata_dm_source_clip_get_type (void);
+
+#define MXF_TYPE_METADATA_DM_SEGMENT \
+  (mxf_metadata_dm_segment_get_type())
+#define MXF_METADATA_DM_SEGMENT(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_DM_SEGMENT, MXFMetadataDMSegment))
+#define MXF_IS_METADATA_DM_SEGMENT(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_DM_SEGMENT))
+typedef struct _MXFMetadataDMSegment MXFMetadataDMSegment;
+typedef MXFMetadataBaseClass MXFMetadataDMSegmentClass;
+GType mxf_metadata_dm_segment_get_type (void);
+
+#define MXF_TYPE_METADATA_GENERIC_DESCRIPTOR \
+  (mxf_metadata_generic_descriptor_get_type())
+#define MXF_METADATA_GENERIC_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_GENERIC_DESCRIPTOR, MXFMetadataGenericDescriptor))
+#define MXF_IS_METADATA_GENERIC_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_GENERIC_DESCRIPTOR))
+typedef struct _MXFMetadataGenericDescriptor MXFMetadataGenericDescriptor;
+typedef MXFMetadataBaseClass MXFMetadataGenericDescriptorClass;
+GType mxf_metadata_generic_descriptor_get_type (void);
+
+#define MXF_TYPE_METADATA_FILE_DESCRIPTOR \
+  (mxf_metadata_file_descriptor_get_type())
+#define MXF_METADATA_FILE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_FILE_DESCRIPTOR, MXFMetadataFileDescriptor))
+#define MXF_IS_METADATA_FILE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_FILE_DESCRIPTOR))
+typedef struct _MXFMetadataFileDescriptor MXFMetadataFileDescriptor;
+typedef MXFMetadataBaseClass MXFMetadataFileDescriptorClass;
+GType mxf_metadata_file_descriptor_get_type (void);
+
+#define MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR \
+  (mxf_metadata_generic_picture_essence_descriptor_get_type())
+#define MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR, MXFMetadataGenericPictureEssenceDescriptor))
+#define MXF_IS_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR))
+typedef struct _MXFMetadataGenericPictureEssenceDescriptor MXFMetadataGenericPictureEssenceDescriptor;
+typedef MXFMetadataBaseClass MXFMetadataGenericPictureEssenceDescriptorClass;
+GType mxf_metadata_generic_picture_essence_descriptor_get_type (void);
+
+#define MXF_TYPE_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR \
+  (mxf_metadata_cdci_picture_essence_descriptor_get_type())
+#define MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR, MXFMetadataCDCIPictureEssenceDescriptor))
+#define MXF_IS_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR))
+typedef struct _MXFMetadataCDCIPictureEssenceDescriptor MXFMetadataCDCIPictureEssenceDescriptor;
+typedef MXFMetadataBaseClass MXFMetadataCDCIPictureEssenceDescriptorClass;
+GType mxf_metadata_cdci_picture_essence_descriptor_get_type (void);
+
+#define MXF_TYPE_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR \
+  (mxf_metadata_rgba_picture_essence_descriptor_get_type())
+#define MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR, MXFMetadataRGBAPictureEssenceDescriptor))
+#define MXF_IS_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR))
+typedef struct _MXFMetadataRGBAPictureEssenceDescriptor MXFMetadataRGBAPictureEssenceDescriptor;
+typedef MXFMetadataBaseClass MXFMetadataRGBAPictureEssenceDescriptorClass;
+GType mxf_metadata_rgba_picture_essence_descriptor_get_type (void);
+
+#define MXF_TYPE_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR \
+  (mxf_metadata_generic_sound_essence_descriptor_get_type())
+#define MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR, MXFMetadataGenericSoundEssenceDescriptor))
+#define MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR))
+typedef struct _MXFMetadataGenericSoundEssenceDescriptor MXFMetadataGenericSoundEssenceDescriptor;
+typedef MXFMetadataBaseClass MXFMetadataGenericSoundEssenceDescriptorClass;
+GType mxf_metadata_generic_sound_essence_descriptor_get_type (void);
+
+#define MXF_TYPE_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR \
+  (mxf_metadata_generic_data_essence_descriptor_get_type())
+#define MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR, MXFMetadataGenericDataEssenceDescriptor))
+#define MXF_IS_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR))
+typedef struct _MXFMetadataGenericDataEssenceDescriptor MXFMetadataGenericDataEssenceDescriptor;
+typedef MXFMetadataBaseClass MXFMetadataGenericDataEssenceDescriptorClass;
+GType mxf_metadata_generic_data_essence_descriptor_get_type (void);
+
+#define MXF_TYPE_METADATA_MULTIPLE_DESCRIPTOR \
+  (mxf_metadata_multiple_descriptor_get_type())
+#define MXF_METADATA_MULTIPLE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_MULTIPLE_DESCRIPTOR, MXFMetadataMultipleDescriptor))
+#define MXF_IS_METADATA_MULTIPLE_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_MULTIPLE_DESCRIPTOR))
+typedef struct _MXFMetadataMultipleDescriptor MXFMetadataMultipleDescriptor;
+typedef MXFMetadataBaseClass MXFMetadataMultipleDescriptorClass;
+GType mxf_metadata_multiple_descriptor_get_type (void);
+
+#define MXF_TYPE_METADATA_LOCATOR \
+  (mxf_metadata_locator_get_type())
+#define MXF_METADATA_LOCATOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_LOCATOR, MXFMetadataLocator))
+#define MXF_IS_METADATA_LOCATOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_LOCATOR))
+typedef struct _MXFMetadataLocator MXFMetadataLocator;
+typedef MXFMetadataBaseClass MXFMetadataLocatorClass;
+GType mxf_metadata_locator_get_type (void);
+
+#define MXF_TYPE_METADATA_NETWORK_LOCATOR \
+  (mxf_metadata_network_locator_get_type())
+#define MXF_METADATA_NETWORK_LOCATOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_NETWORK_LOCATOR, MXFMetadataNetworkLocator))
+#define MXF_IS_METADATA_NETWORK_LOCATOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_NETWORK_LOCATOR))
+typedef struct _MXFMetadataNetworkLocator MXFMetadataNetworkLocator;
+typedef MXFMetadataBaseClass MXFMetadataNetworkLocatorClass;
+GType mxf_metadata_network_locator_get_type (void);
+
+#define MXF_TYPE_METADATA_TEXT_LOCATOR \
+  (mxf_metadata_text_locator_get_type())
+#define MXF_METADATA_TEXT_LOCATOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_TEXT_LOCATOR, MXFMetadataTextLocator))
+#define MXF_IS_METADATA_TEXT_LOCATOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_TEXT_LOCATOR))
+typedef struct _MXFMetadataTextLocator MXFMetadataTextLocator;
+typedef MXFMetadataBaseClass MXFMetadataTextLocatorClass;
+GType mxf_metadata_text_locator_get_type (void);
+
+struct _MXFMetadataBase {
+  GstMiniObject parent;
+
+  MXFUL instance_uid;
+  MXFUL generation_uid;
+
+  gboolean resolved;
+
+  GHashTable *other_tags;
+};
+
+struct _MXFMetadataBaseClass {
+  GstMiniObjectClass parent;
+
+  gboolean (*handle_tag) (MXFMetadataBase *self, MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint tag_size);
+  gboolean (*resolve) (MXFMetadataBase *self, MXFMetadataBase **metadata);
+};
+
+struct _MXFMetadata {
+  MXFMetadataBase parent;
+  
+  guint16 type;
+};
+
+struct _MXFMetadataPreface {
+  MXFMetadata parent;
+
+  MXFTimestamp last_modified_date;
+  guint16 version;
+
+  guint32 object_model_version;
+
+  MXFUL primary_package_uid;
+  MXFMetadataGenericPackage *primary_package;
+
+  guint32 n_identifications;
+  MXFUL *identifications_uids;
+  MXFMetadataIdentification **identifications;
+
+  MXFUL content_storage_uid;
+  MXFMetadataContentStorage *content_storage;
+
+  MXFUL operational_pattern;
+
+  guint32 n_essence_containers;
+  MXFUL *essence_containers;
+
+  guint32 n_dm_schemes;
+  MXFUL *dm_schemes;
+};
+
+struct _MXFMetadataIdentification {
+  MXFMetadata parent;
+
+  gchar *company_name;
+
+  gchar *product_name;
+  MXFProductVersion product_version;
+  
+  gchar *version_string;
+
+  MXFUL product_uid;
+
+  MXFTimestamp modification_date;
+
+  MXFProductVersion toolkit_version;
+
+  gchar *platform;
+};
+
+struct _MXFMetadataContentStorage {
+  MXFMetadata parent;
+
+  guint32 n_packages;
+  MXFUL *packages_uids;
+  MXFMetadataGenericPackage **packages;
+
+  guint32 n_essence_container_data;
+  MXFUL *essence_container_data_uids;
+  MXFMetadataEssenceContainerData **essence_container_data;
+};
+
+struct _MXFMetadataEssenceContainerData {
+  MXFMetadata parent;
+
+  MXFUMID linked_package_uid;
+  MXFMetadataSourcePackage *linked_package;
+
+  guint32 index_sid;
+  guint32 body_sid;
+};
+
+struct _MXFMetadataGenericPackage {
+  MXFMetadata parent;
+
+  MXFUMID package_uid;
+
+  gchar *name;
+  MXFTimestamp package_creation_date;
+  MXFTimestamp package_modified_date;
+
+  guint32 n_tracks;
+  MXFUL *tracks_uids;
+  MXFMetadataTrack **tracks;
+
+  guint n_timecode_tracks;
+  guint n_metadata_tracks;
+  guint n_essence_tracks;
+  guint n_other_tracks;
+};
+
+struct _MXFMetadataSourcePackage
+{
+  MXFMetadataGenericPackage parent;
+
+  MXFUL descriptors_uid;
+  guint32 n_descriptors;
+  MXFMetadataGenericDescriptor **descriptors;
+
+  gboolean top_level;
+};
+
+typedef enum {
+  MXF_METADATA_TRACK_UNKNOWN               = 0x00,
+  MXF_METADATA_TRACK_TIMECODE_12M_INACTIVE = 0x10,
+  MXF_METADATA_TRACK_TIMECODE_12M_ACTIVE   = 0x11,
+  MXF_METADATA_TRACK_TIMECODE_309M         = 0x12,
+  MXF_METADATA_TRACK_METADATA              = 0x20,
+  MXF_METADATA_TRACK_PICTURE_ESSENCE       = 0x30,
+  MXF_METADATA_TRACK_SOUND_ESSENCE         = 0x31,
+  MXF_METADATA_TRACK_DATA_ESSENCE          = 0x32,
+  MXF_METADATA_TRACK_AUXILIARY_DATA        = 0x40,
+  MXF_METADATA_TRACK_PARSED_TEXT           = 0x41
+} MXFMetadataTrackType;
+
+struct _MXFMetadataTrack {
+  MXFMetadata parent;
+
+  guint32 track_id;
+  guint32 track_number;
+
+  gchar *track_name;
+
+  MXFUL sequence_uid;
+  MXFMetadataSequence *sequence;
+
+  MXFMetadataTrackType type;
+
+  MXFMetadataFileDescriptor **descriptor;
+  guint n_descriptor;
+};
+
+struct _MXFMetadataTimelineTrack {
+  MXFMetadataTrack parent;
+
+  MXFFraction edit_rate;
+  gint64 origin;
+};
+
+struct _MXFMetadataEventTrack {
+  MXFMetadataTrack parent;
+
+  MXFFraction event_edit_rate;
+  gint64 event_origin;
+};
+
+struct _MXFMetadataSequence {
+  MXFMetadata parent;
+
+  MXFUL data_definition;
+
+  gint64 duration;
+
+  guint32 n_structural_components;
+  MXFUL *structural_components_uids;
+  MXFMetadataStructuralComponent **structural_components;
+};
+
+struct _MXFMetadataStructuralComponent {
+  MXFMetadata parent;
+
+  MXFUL data_definition;
+  gint64 duration;
+};
+
+struct _MXFMetadataTimecodeComponent {
+  MXFMetadataStructuralComponent parent;
+
+  gint64 start_timecode;
+  guint16 rounded_timecode_base;
+  gboolean drop_frame;
+};
+
+struct _MXFMetadataSourceClip {
+  MXFMetadataStructuralComponent parent;
+
+  gint64 start_position;
+  MXFUMID source_package_id;
+  MXFMetadataSourcePackage *source_package;
+
+  guint32 source_track_id;
+};
+
+struct _MXFMetadataDMSourceClip {
+  MXFMetadataSourceClip parent;
+
+  guint32 n_track_ids;
+  guint32 *track_ids;
+};
+
+struct _MXFMetadataDMSegment {
+  MXFMetadataStructuralComponent parent;
+
+  gint64 event_start_position;
+  gchar *event_comment;
+
+  guint32 n_track_ids;
+  guint32 *track_ids;
+      
+  MXFUL dm_framework_uid;
+  MXFMetadataBase *dm_framework;
+};
+
+struct _MXFMetadataGenericDescriptor {
+  MXFMetadata parent;
+
+  guint32 n_locators;
+  MXFUL *locators_uids;
+  MXFMetadataLocator **locators;
+};
+
+struct _MXFMetadataFileDescriptor {
+  MXFMetadataGenericDescriptor parent;
+
+  guint32 linked_track_id;
+
+  MXFFraction sample_rate;
+  gint64 container_duration;
+
+  MXFUL essence_container;
+  MXFUL codec;
+};
+
+struct _MXFMetadataGenericPictureEssenceDescriptor {
+  MXFMetadataFileDescriptor parent;
+
+  guint8 signal_standard;
+  guint8 frame_layout;
+
+  guint32 stored_width;
+  guint32 stored_height;
+  gint32 stored_f2_offset;
+  guint32 sampled_width;
+  guint32 sampled_height;
+  gint32 sampled_x_offset;
+  gint32 sampled_y_offset;
+  guint32 display_height;
+  guint32 display_width;
+  gint32 display_x_offset;
+  gint32 display_y_offset;
+  gint32 display_f2_offset;
+  MXFFraction aspect_ratio;
+
+  guint8 active_format_descriptor;
+  gint32 video_line_map[2];
+  guint8 alpha_transparency;
+  MXFUL capture_gamma;
+
+  guint32 image_alignment_offset;
+  guint32 image_start_offset;
+  guint32 image_end_offset;
+
+  guint8 field_dominance;
+
+  MXFUL picture_essence_coding;
+};
+
+struct _MXFMetadataCDCIPictureEssenceDescriptor {
+  MXFMetadataGenericPictureEssenceDescriptor parent;
+
+  guint32 component_depth;
+  guint32 horizontal_subsampling;
+  guint32 vertical_subsampling;
+  guint8 color_siting;
+  gboolean reversed_byte_order;
+  gint16 padding_bits;
+  guint32 alpha_sample_depth;
+  guint32 black_ref_level;
+  guint32 white_ref_level;
+  guint32 color_range;
+};
+
+struct _MXFMetadataRGBAPictureEssenceDescriptor {
+  MXFMetadataGenericPictureEssenceDescriptor parent;
+
+  guint32 component_max_ref;
+  guint32 component_min_ref;
+  guint32 alpha_max_ref;
+  guint32 alpha_min_ref;
+  guint8 scanning_direction;
+
+  guint32 n_pixel_layout;
+  guint8 *pixel_layout;
+
+  /* TODO: palette & palette layout */
+};
+
+struct _MXFMetadataGenericSoundEssenceDescriptor {
+  MXFMetadataFileDescriptor parent;
+
+  MXFFraction audio_sampling_rate;
+
+  gboolean locked;
+
+  gint8 audio_ref_level;
+
+  guint8 electro_spatial_formulation;
+
+  guint32 channel_count;
+  guint32 quantization_bits;
+
+  gint8 dial_norm;
+
+  MXFUL sound_essence_compression;
+};
+
+struct _MXFMetadataGenericDataEssenceDescriptor {
+  MXFMetadataFileDescriptor parent;
+
+  MXFUL data_essence_compression;
+};
+
+struct _MXFMetadataMultipleDescriptor {
+  MXFMetadataFileDescriptor parent;
+  
+  MXFUL *sub_descriptors_uids;
+  guint32 n_sub_descriptors;
+  MXFMetadataGenericDescriptor **sub_descriptors;
+};
+
+struct _MXFMetadataLocator {
+  MXFMetadata parent;
+};
+
+struct _MXFMetadataNetworkLocator {
+  MXFMetadataLocator parent;
+
+  gchar *url_string;
+};
+
+struct _MXFMetadataTextLocator {
+  MXFMetadataLocator parent;
+
+  gchar *locator_name;
+};
+
+gboolean mxf_metadata_parse (MXFMetadataBase *self, MXFPrimerPack *primer, const guint8 *data, guint size);
+gboolean mxf_metadata_resolve (MXFMetadataBase *self, MXFMetadataBase **metadata);
+
+MXFMetadata *mxf_metadata_new (guint16 type, MXFPrimerPack *primer, const guint8 *data, guint size);
+void mxf_metadata_register (guint16 type_id, GType type);
+void mxf_metadata_init_types (void);
+
+MXFMetadataTrackType mxf_metadata_track_identifier_parse (const MXFUL * track_identifier);
+
+void mxf_metadata_generic_picture_essence_descriptor_set_caps (MXFMetadataGenericPictureEssenceDescriptor * self, GstCaps * caps);
+
+#endif /* __MXF_METADATA_H__ */
index 608ecc2..7ba129f 100644 (file)
@@ -91,14 +91,18 @@ static const guint8 _profile_and_level_ul[] = {
   0x0a, 0x00, 0x00
 };
 
-gboolean
-mxf_metadata_mpeg_video_descriptor_handle_tag (MXFMetadataGenericDescriptor * d,
-    const MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
-    guint16 tag_size)
+G_DEFINE_TYPE (MXFMetadataMPEGVideoDescriptor,
+    mxf_metadata_mpeg_video_descriptor,
+    MXF_TYPE_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR);
+
+static gboolean
+mxf_metadata_mpeg_video_descriptor_handle_tag (MXFMetadataBase * metadata,
+    MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
+    guint tag_size)
 {
-  MXFMetadataMPEGVideoDescriptor *descriptor =
-      (MXFMetadataMPEGVideoDescriptor *) d;
-  gboolean ret = FALSE;
+  MXFMetadataMPEGVideoDescriptor *self =
+      MXF_METADATA_MPEG_VIDEO_DESCRIPTOR (metadata);
+  gboolean ret = TRUE;
   MXFUL *tag_ul = NULL;
 
   if (!(tag_ul =
@@ -109,91 +113,86 @@ mxf_metadata_mpeg_video_descriptor_handle_tag (MXFMetadataGenericDescriptor * d,
   if (memcmp (tag_ul, &_single_sequence_ul, 16) == 0) {
     if (tag_size != 1)
       goto error;
-    descriptor->single_sequence = GST_READ_UINT8 (tag_data);
+    self->single_sequence = GST_READ_UINT8 (tag_data);
     GST_DEBUG ("  single sequence = %s",
-        (descriptor->single_sequence) ? "yes" : "no");
-    ret = TRUE;
+        (self->single_sequence) ? "yes" : "no");
   } else if (memcmp (tag_ul, &_constant_b_frames_ul, 16) == 0) {
     if (tag_size != 1)
       goto error;
-    descriptor->const_b_frames = GST_READ_UINT8 (tag_data);
+    self->const_b_frames = GST_READ_UINT8 (tag_data);
     GST_DEBUG ("  constant b frames = %s",
-        (descriptor->single_sequence) ? "yes" : "no");
-    ret = TRUE;
+        (self->single_sequence) ? "yes" : "no");
   } else if (memcmp (tag_ul, &_coded_content_type_ul, 16) == 0) {
     if (tag_size != 1)
       goto error;
-    descriptor->coded_content_type = GST_READ_UINT8 (tag_data);
-    GST_DEBUG ("  coded content type = %u", descriptor->coded_content_type);
-    ret = TRUE;
+    self->coded_content_type = GST_READ_UINT8 (tag_data);
+    GST_DEBUG ("  coded content type = %u", self->coded_content_type);
   } else if (memcmp (tag_ul, &_low_delay_ul, 16) == 0) {
     if (tag_size != 1)
       goto error;
-    descriptor->low_delay = GST_READ_UINT8 (tag_data);
-    GST_DEBUG ("  low delay = %s", (descriptor->low_delay) ? "yes" : "no");
-    ret = TRUE;
+    self->low_delay = GST_READ_UINT8 (tag_data);
+    GST_DEBUG ("  low delay = %s", (self->low_delay) ? "yes" : "no");
   } else if (memcmp (tag_ul, &_closed_gop_ul, 16) == 0) {
     if (tag_size != 1)
       goto error;
-    descriptor->closed_gop = GST_READ_UINT8 (tag_data);
-    GST_DEBUG ("  closed gop = %s", (descriptor->closed_gop) ? "yes" : "no");
-    ret = TRUE;
+    self->closed_gop = GST_READ_UINT8 (tag_data);
+    GST_DEBUG ("  closed gop = %s", (self->closed_gop) ? "yes" : "no");
   } else if (memcmp (tag_ul, &_identical_gop_ul, 16) == 0) {
     if (tag_size != 1)
       goto error;
-    descriptor->identical_gop = GST_READ_UINT8 (tag_data);
-    GST_DEBUG ("  identical gop = %s",
-        (descriptor->identical_gop) ? "yes" : "no");
-    ret = TRUE;
+    self->identical_gop = GST_READ_UINT8 (tag_data);
+    GST_DEBUG ("  identical gop = %s", (self->identical_gop) ? "yes" : "no");
   } else if (memcmp (tag_ul, &_max_gop_ul, 16) == 0) {
     if (tag_size != 2)
       goto error;
-    descriptor->max_gop = GST_READ_UINT16_BE (tag_data);
-    GST_DEBUG ("  max gop = %u", descriptor->max_gop);
-    ret = TRUE;
+    self->max_gop = GST_READ_UINT16_BE (tag_data);
+    GST_DEBUG ("  max gop = %u", self->max_gop);
   } else if (memcmp (tag_ul, &_b_picture_count_ul, 16) == 0) {
     if (tag_size != 2)
       goto error;
-    descriptor->b_picture_count = GST_READ_UINT16_BE (tag_data);
-    GST_DEBUG ("  b picture count = %u", descriptor->b_picture_count);
-    ret = TRUE;
+    self->b_picture_count = GST_READ_UINT16_BE (tag_data);
+    GST_DEBUG ("  b picture count = %u", self->b_picture_count);
   } else if (memcmp (tag_ul, &_bitrate_ul, 16) == 0) {
     if (tag_size != 4)
       goto error;
-    descriptor->bitrate = GST_READ_UINT32_BE (tag_data);
-    GST_DEBUG ("  bitrate = %u", descriptor->bitrate);
-    ret = TRUE;
+    self->bitrate = GST_READ_UINT32_BE (tag_data);
+    GST_DEBUG ("  bitrate = %u", self->bitrate);
   } else if (memcmp (tag_ul, &_profile_and_level_ul, 16) == 0) {
     if (tag_size != 1)
       goto error;
-    descriptor->profile_and_level = GST_READ_UINT8 (tag_data);
-    GST_DEBUG ("  profile & level = %u", descriptor->profile_and_level);
-    ret = TRUE;
+    self->profile_and_level = GST_READ_UINT8 (tag_data);
+    GST_DEBUG ("  profile & level = %u", self->profile_and_level);
   } else {
     ret =
-        mxf_metadata_cdci_picture_essence_descriptor_handle_tag (d, primer, tag,
-        tag_data, tag_size);
+        MXF_METADATA_BASE_CLASS
+        (mxf_metadata_mpeg_video_descriptor_parent_class)->handle_tag (metadata,
+        primer, tag, tag_data, tag_size);
   }
 
   return ret;
 
 error:
-  GST_ERROR ("Invalid mpeg video descriptor tag 0x%04x of size %u", tag,
+
+  GST_ERROR ("Invalid MPEG video descriptor local tag 0x%04x of size %u", tag,
       tag_size);
 
   return FALSE;
 }
 
-void mxf_metadata_mpeg_video_descriptor_reset
-    (MXFMetadataMPEGVideoDescriptor * descriptor)
+static void
+mxf_metadata_mpeg_video_descriptor_init (MXFMetadataMPEGVideoDescriptor * self)
 {
-  g_return_if_fail (descriptor != NULL);
 
-  mxf_metadata_cdci_picture_essence_descriptor_reset (
-      (MXFMetadataCDCIPictureEssenceDescriptor *) descriptor);
+}
+
+static void
+    mxf_metadata_mpeg_video_descriptor_class_init
+    (MXFMetadataMPEGVideoDescriptorClass * klass)
+{
+  MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
 
-  MXF_METADATA_DESCRIPTOR_CLEAR (descriptor, MXFMetadataMPEGVideoDescriptor,
-      MXFMetadataCDCIPictureEssenceDescriptor);
+  metadata_base_class->handle_tag =
+      mxf_metadata_mpeg_video_descriptor_handle_tag;
 }
 
 gboolean
@@ -208,7 +207,12 @@ mxf_is_mpeg_essence_track (const MXFMetadataTrack * track)
 
   for (i = 0; i < track->n_descriptor; i++) {
     MXFMetadataFileDescriptor *d = track->descriptor[i];
-    MXFUL *key = &d->essence_container;
+    MXFUL *key;
+
+    if (!d)
+      continue;
+
+    key = &d->essence_container;
     /* SMPTE 381M 7 */
     if (mxf_is_generic_container_essence_container_label (key) &&
         key->u[12] == 0x02 &&
@@ -338,8 +342,8 @@ mxf_mpeg_es_create_caps (MXFMetadataGenericPackage * package,
       codec_name = "MPEG-1 Video";
     } else if (p->picture_essence_coding.u[13] == 0x20) {
       MXFLocalTag *local_tag =
-          (((MXFMetadataGenericDescriptor *) p)->other_tags) ?
-          g_hash_table_lookup (((MXFMetadataGenericDescriptor *)
+          (((MXFMetadataBase *) p)->other_tags) ?
+          g_hash_table_lookup (((MXFMetadataBase *)
               p)->other_tags, &sony_mpeg4_extradata) : NULL;
 
       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
@@ -446,17 +450,16 @@ mxf_mpeg_create_caps (MXFMetadataGenericPackage * package,
   }
 
   for (i = 0; i < track->n_descriptor; i++) {
-    if (((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_MPEG_VIDEO_DESCRIPTOR ||
-        ((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR ||
-        ((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR) {
+    if (!track->descriptor[i])
+      continue;
+
+    if (MXF_IS_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (track->
+            descriptor[i])) {
       f = track->descriptor[i];
       p = (MXFMetadataGenericPictureEssenceDescriptor *) track->descriptor[i];
       break;
-    } else if (((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR) {
+    } else if (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (track->
+            descriptor[i])) {
       f = track->descriptor[i];
       s = (MXFMetadataGenericSoundEssenceDescriptor *) track->descriptor[i];
       break;
@@ -503,3 +506,9 @@ mxf_mpeg_create_caps (MXFMetadataGenericPackage * package,
 
   return caps;
 }
+
+void
+mxf_mpeg_init (void)
+{
+  mxf_metadata_register (0x0151, MXF_TYPE_METADATA_MPEG_VIDEO_DESCRIPTOR);
+}
index 16258a5..6ab45e4 100644 (file)
 #include <gst/gst.h>
 
 #include "mxfparse.h"
-
-/* SMPTE 381M 8.1.1 */
-#define MXF_METADATA_MPEG_VIDEO_DESCRIPTOR 0x0151
+#include "mxfmetadata.h"
 
 /* SMPTE 381M 8.1 */
-typedef struct {
+#define MXF_TYPE_METADATA_MPEG_VIDEO_DESCRIPTOR \
+  (mxf_metadata_mpeg_video_descriptor_get_type())
+#define MXF_METADATA_MPEG_VIDEO_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),MXF_TYPE_METADATA_MPEG_VIDEO_DESCRIPTOR, MXFMetadataMPEGVideoDescriptor))
+#define MXF_IS_METADATA_MPEG_VIDEO_DESCRIPTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),MXF_TYPE_METADATA_MPEG_VIDEO_DESCRIPTOR))
+typedef struct _MXFMetadataMPEGVideoDescriptor MXFMetadataMPEGVideoDescriptor;
+typedef MXFMetadataBaseClass MXFMetadataMPEGVideoDescriptorClass;
+GType mxf_metadata_mpeg_video_descriptor_get_type (void);
+
+struct _MXFMetadataMPEGVideoDescriptor {
   MXFMetadataCDCIPictureEssenceDescriptor parent;
 
   gboolean single_sequence;
@@ -47,14 +55,13 @@ typedef struct {
   guint16 b_picture_count;
   guint32 bitrate;
   guint8 profile_and_level;
-} MXFMetadataMPEGVideoDescriptor;
-
-gboolean mxf_metadata_mpeg_video_descriptor_handle_tag (MXFMetadataGenericDescriptor *descriptor, const MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint16 tag_size);
-void mxf_metadata_mpeg_video_descriptor_reset (MXFMetadataMPEGVideoDescriptor *descriptor);
+};
 
 gboolean mxf_is_mpeg_essence_track (const MXFMetadataTrack *track);
 
 GstCaps *
 mxf_mpeg_create_caps (MXFMetadataGenericPackage *package, MXFMetadataTrack *track, GstTagList **tags, MXFEssenceElementHandler *handler, gpointer *mapping_data);
 
+void mxf_mpeg_init (void);
+
 #endif /* __MXF_MPEG_H__ */
index 9ee44e6..571f6f2 100644 (file)
@@ -830,7 +830,7 @@ mxf_index_table_segment_parse (const MXFUL * key,
         break;
       }
       default:
-        if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
+        if (!mxf_local_tag_add_to_hash_table (primer, tag, tag_data, tag_size,
                 &segment->other_tags))
           goto error;
         break;
@@ -974,7 +974,7 @@ gst_mxf_local_tag_free (MXFLocalTag * tag)
 }
 
 gboolean
-gst_metadata_add_custom_tag (const MXFPrimerPack * primer,
+mxf_local_tag_add_to_hash_table (const MXFPrimerPack * primer,
     guint16 tag, const guint8 * tag_data, guint16 tag_size,
     GHashTable ** hash_table)
 {
@@ -1015,2203 +1015,3 @@ gst_metadata_add_custom_tag (const MXFPrimerPack * primer,
 
   return TRUE;
 }
-
-/* All following defined in SMPTE 377M Annex A, B, C, D */
-gboolean
-mxf_metadata_preface_parse (const MXFUL * key,
-    MXFMetadataPreface * preface, const MXFPrimerPack * primer,
-    const guint8 * data, guint size)
-{
-  guint16 tag, tag_size;
-  const guint8 *tag_data;
-  gchar str[48];
-
-  g_return_val_if_fail (data != NULL, FALSE);
-
-  memset (preface, 0, sizeof (MXFMetadataPreface));
-
-  GST_DEBUG ("Parsing preface:");
-
-  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
-    if (tag_size == 0 || tag == 0x0000)
-      goto next;
-
-    switch (tag) {
-      case 0x3c0a:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&preface->instance_uid, tag_data, 16);
-        GST_DEBUG ("  instance uid = %s",
-            mxf_ul_to_string (&preface->instance_uid, str));
-        break;
-      case 0x0102:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&preface->generation_uid, tag_data, 16);
-        GST_DEBUG ("  generation uid = %s",
-            mxf_ul_to_string (&preface->generation_uid, str));
-        break;
-      case 0x3b02:
-        if (!mxf_timestamp_parse (&preface->last_modified_date, tag_data,
-                tag_size))
-          goto error;
-        GST_DEBUG ("  last modified date = %d/%u/%u %u:%u:%u.%u",
-            preface->last_modified_date.year, preface->last_modified_date.month,
-            preface->last_modified_date.day, preface->last_modified_date.hour,
-            preface->last_modified_date.minute,
-            preface->last_modified_date.second,
-            (preface->last_modified_date.quarter_msecond * 1000) / 256);
-        break;
-      case 0x3b05:
-        if (tag_size != 2)
-          goto error;
-        preface->version = GST_READ_UINT16_BE (tag_data);
-        GST_DEBUG ("  version = %u.%u", (preface->version >> 8),
-            (preface->version & 0x0f));
-        break;
-      case 0x3b07:
-        if (tag_size != 4)
-          goto error;
-        preface->object_model_version = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  object model version = %u",
-            preface->object_model_version);
-        break;
-      case 0x3b08:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&preface->primary_package_uid, tag_data, 16);
-        GST_DEBUG ("  primary package = %s",
-            mxf_ul_to_string (&preface->primary_package_uid, str));
-        break;
-      case 0x3b06:{
-        guint32 len;
-        guint i;
-
-
-        if (tag_size < 8)
-          goto error;
-        len = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  number of identifications = %u", len);
-        if (len == 0)
-          break;
-        if (GST_READ_UINT32_BE (tag_data + 4) != 16)
-          goto error;
-        if (tag_size < 8 + len * 16)
-          goto error;
-
-        preface->n_identifications = len;
-        preface->identifications_uids = g_new (MXFUL, len);
-        for (i = 0; i < len; i++) {
-          memcpy (&preface->identifications_uids[i], tag_data + 8 + i * 16, 16);
-          GST_DEBUG ("  identification %u = %s", i,
-              mxf_ul_to_string (&preface->identifications_uids[i], str));
-        }
-        break;
-      }
-      case 0x3b03:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&preface->content_storage_uid, tag_data, 16);
-        GST_DEBUG ("  content storage = %s",
-            mxf_ul_to_string (&preface->content_storage_uid, str));
-        break;
-      case 0x3b09:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&preface->operational_pattern, tag_data, 16);
-        GST_DEBUG ("  operational pattern = %s",
-            mxf_ul_to_string (&preface->operational_pattern, str));
-        break;
-      case 0x3b0a:{
-        guint32 len;
-        guint i;
-
-
-        if (tag_size < 8)
-          goto error;
-        len = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  number of essence containers = %u", len);
-        if (len == 0)
-          break;
-        if (GST_READ_UINT32_BE (tag_data + 4) != 16)
-          goto error;
-        if (tag_size < 8 + len * 16)
-          goto error;
-
-        preface->n_essence_containers = len;
-        preface->essence_containers = g_new (MXFUL, len);
-        for (i = 0; i < len; i++) {
-          memcpy (&preface->essence_containers[i], tag_data + 8 + i * 16, 16);
-          GST_DEBUG ("  essence container %u = %s", i,
-              mxf_ul_to_string (&preface->essence_containers[i], str));
-        }
-        break;
-      }
-      case 0x3b0b:{
-        guint32 len;
-        guint i;
-
-
-        if (tag_size < 8)
-          goto error;
-        len = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  number of DM schemes = %u", len);
-        if (len == 0)
-          break;
-        if (GST_READ_UINT32_BE (tag_data + 4) != 16)
-          goto error;
-        if (tag_size < 8 + len * 16)
-          goto error;
-
-        preface->n_dm_schemes = len;
-        preface->dm_schemes = g_new (MXFUL, len);
-        for (i = 0; i < len; i++) {
-          memcpy (&preface->dm_schemes[i], tag_data + 8 + i * 16, 16);
-          GST_DEBUG ("  DM schemes %u = %s", i,
-              mxf_ul_to_string (&preface->dm_schemes[i], str));
-        }
-        break;
-      }
-      default:
-        if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
-                &preface->other_tags))
-          goto error;
-        break;
-    }
-
-  next:
-    data += 4 + tag_size;
-    size -= 4 + tag_size;
-  }
-
-  return TRUE;
-
-error:
-  GST_ERROR ("Invalid preface");
-  mxf_metadata_preface_reset (preface);
-
-  return FALSE;
-}
-
-void
-mxf_metadata_preface_reset (MXFMetadataPreface * preface)
-{
-  g_return_if_fail (preface != NULL);
-
-  g_free (preface->identifications_uids);
-  g_free (preface->identifications);
-  g_free (preface->essence_containers);
-  g_free (preface->dm_schemes);
-
-  if (preface->other_tags)
-    g_hash_table_destroy (preface->other_tags);
-
-  memset (preface, 0, sizeof (MXFMetadataPreface));
-}
-
-gboolean
-mxf_metadata_identification_parse (const MXFUL * key,
-    MXFMetadataIdentification * identification,
-    const MXFPrimerPack * primer, const guint8 * data, guint size)
-{
-  guint16 tag, tag_size;
-  const guint8 *tag_data;
-  gchar str[48];
-
-  g_return_val_if_fail (data != NULL, FALSE);
-
-  memset (identification, 0, sizeof (MXFMetadataIdentification));
-
-  GST_DEBUG ("Parsing identification:");
-
-  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
-    if (tag_size == 0 || tag == 0x0000)
-      goto next;
-
-    switch (tag) {
-      case 0x3c0a:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&identification->instance_uid, tag_data, 16);
-        GST_DEBUG ("  instance uid = %s",
-            mxf_ul_to_string (&identification->instance_uid, str));
-        break;
-      case 0x3c09:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&identification->generation_uid, tag_data, 16);
-        GST_DEBUG ("  generation uid = %s",
-            mxf_ul_to_string (&identification->generation_uid, str));
-        break;
-      case 0x3c01:
-        identification->company_name = mxf_utf16_to_utf8 (tag_data, tag_size);
-        GST_DEBUG ("  company name = %s",
-            GST_STR_NULL (identification->company_name));
-        break;
-      case 0x3c02:
-        identification->product_name = mxf_utf16_to_utf8 (tag_data, tag_size);
-        GST_DEBUG ("  product name = %s",
-            GST_STR_NULL (identification->product_name));
-        break;
-      case 0x3c03:
-        if (!mxf_product_version_parse (&identification->product_version,
-                tag_data, tag_size))
-          goto error;
-        GST_DEBUG ("  product version = %u.%u.%u.%u.%u",
-            identification->product_version.major,
-            identification->product_version.minor,
-            identification->product_version.patch,
-            identification->product_version.build,
-            identification->product_version.release);
-        break;
-      case 0x3c04:
-        identification->version_string = mxf_utf16_to_utf8 (tag_data, tag_size);
-        GST_DEBUG ("  version string = %s",
-            GST_STR_NULL (identification->version_string));
-        break;
-      case 0x3c05:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&identification->product_uid, tag_data, 16);
-        GST_DEBUG ("  product uid = %s",
-            mxf_ul_to_string (&identification->product_uid, str));
-        break;
-      case 0x3c06:
-        if (!mxf_timestamp_parse (&identification->modification_date, tag_data,
-                tag_size))
-          goto error;
-        GST_DEBUG ("  modification date = %d/%u/%u %u:%u:%u.%u",
-            identification->modification_date.year,
-            identification->modification_date.month,
-            identification->modification_date.day,
-            identification->modification_date.hour,
-            identification->modification_date.minute,
-            identification->modification_date.second,
-            (identification->modification_date.quarter_msecond * 1000) / 256);
-        break;
-      case 0x3c07:
-        if (!mxf_product_version_parse (&identification->toolkit_version,
-                tag_data, tag_size))
-          goto error;
-        GST_DEBUG ("  toolkit version = %u.%u.%u.%u.%u",
-            identification->toolkit_version.major,
-            identification->toolkit_version.minor,
-            identification->toolkit_version.patch,
-            identification->toolkit_version.build,
-            identification->toolkit_version.release);
-        break;
-      case 0x3c08:
-        identification->platform = mxf_utf16_to_utf8 (tag_data, tag_size);
-        GST_DEBUG ("  platform = %s", GST_STR_NULL (identification->platform));
-        break;
-      default:
-        if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
-                &identification->other_tags))
-          goto error;
-        break;
-    }
-
-  next:
-    data += 4 + tag_size;
-    size -= 4 + tag_size;
-  }
-
-  return TRUE;
-
-error:
-  GST_ERROR ("Invalid identification");
-  mxf_metadata_identification_reset (identification);
-
-  return FALSE;
-}
-
-void mxf_metadata_identification_reset
-    (MXFMetadataIdentification * identification)
-{
-  g_return_if_fail (identification != NULL);
-
-  g_free (identification->company_name);
-  g_free (identification->product_name);
-  g_free (identification->version_string);
-  g_free (identification->platform);
-
-  if (identification->other_tags)
-    g_hash_table_destroy (identification->other_tags);
-
-  memset (identification, 0, sizeof (MXFMetadataIdentification));
-}
-
-gboolean
-mxf_metadata_content_storage_parse (const MXFUL * key,
-    MXFMetadataContentStorage * content_storage,
-    const MXFPrimerPack * primer, const guint8 * data, guint size)
-{
-  guint16 tag, tag_size;
-  const guint8 *tag_data;
-  gchar str[48];
-
-  g_return_val_if_fail (data != NULL, FALSE);
-
-  memset (content_storage, 0, sizeof (MXFMetadataContentStorage));
-
-  GST_DEBUG ("Parsing content storage:");
-
-  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
-    if (tag_size == 0 || tag == 0x0000)
-      goto next;
-
-    switch (tag) {
-      case 0x3c0a:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&content_storage->instance_uid, tag_data, 16);
-        GST_DEBUG ("  instance uid = %s",
-            mxf_ul_to_string (&content_storage->instance_uid, str));
-        break;
-      case 0x0102:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&content_storage->generation_uid, tag_data, 16);
-        GST_DEBUG ("  generation uid = %s",
-            mxf_ul_to_string (&content_storage->generation_uid, str));
-        break;
-      case 0x1901:{
-        guint32 len;
-        guint i;
-
-
-        len = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  number of packages = %u", len);
-        if (len == 0)
-          break;
-        if (GST_READ_UINT32_BE (tag_data + 4) != 16)
-          goto error;
-        if (tag_size < 8 + len * 16)
-          goto error;
-
-        content_storage->packages_uids = g_new (MXFUL, len);
-        content_storage->n_packages = len;
-        for (i = 0; i < len; i++) {
-          memcpy (&content_storage->packages_uids[i], tag_data + 8 + i * 16,
-              16);
-          GST_DEBUG ("  package %u = %s", i,
-              mxf_ul_to_string (&content_storage->packages_uids[i], str));
-        }
-        break;
-      }
-      case 0x1902:{
-        guint32 len;
-        guint i;
-
-
-        len = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  number of essence container data = %u", len);
-        if (len == 0)
-          break;
-        if (GST_READ_UINT32_BE (tag_data + 4) != 16)
-          goto error;
-        if (tag_size < 8 + len * 16)
-          goto error;
-
-        content_storage->essence_container_data_uids = g_new (MXFUL, len);
-        content_storage->n_essence_container_data = len;
-        for (i = 0; i < len; i++) {
-          memcpy (&content_storage->essence_container_data_uids[i],
-              tag_data + 8 + i * 16, 16);
-          GST_DEBUG ("  essence container data %u = %s", i,
-              mxf_ul_to_string (&content_storage->essence_container_data_uids
-                  [i], str));
-        }
-        break;
-      }
-      default:
-        if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
-                &content_storage->other_tags))
-          goto error;
-        break;
-    }
-
-  next:
-    data += 4 + tag_size;
-    size -= 4 + tag_size;
-  }
-
-  return TRUE;
-
-error:
-  GST_ERROR ("Invalid content storage");
-  mxf_metadata_content_storage_reset (content_storage);
-
-  return FALSE;
-}
-
-void mxf_metadata_content_storage_reset
-    (MXFMetadataContentStorage * content_storage)
-{
-  g_return_if_fail (content_storage != NULL);
-
-  g_free (content_storage->packages);
-  g_free (content_storage->packages_uids);
-  g_free (content_storage->essence_container_data);
-  g_free (content_storage->essence_container_data_uids);
-
-  if (content_storage->other_tags)
-    g_hash_table_destroy (content_storage->other_tags);
-
-  memset (content_storage, 0, sizeof (MXFMetadataContentStorage));
-}
-
-gboolean
-mxf_metadata_essence_container_data_parse (const MXFUL * key,
-    MXFMetadataEssenceContainerData * essence_container_data,
-    const MXFPrimerPack * primer, const guint8 * data, guint size)
-{
-  guint16 tag, tag_size;
-  const guint8 *tag_data;
-  gchar str[96];
-
-  g_return_val_if_fail (data != NULL, FALSE);
-
-  memset (essence_container_data, 0, sizeof (MXFMetadataEssenceContainerData));
-
-  GST_DEBUG ("Parsing essence container data:");
-
-  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
-    if (tag_size == 0 || tag == 0x0000)
-      goto next;
-
-    switch (tag) {
-      case 0x3c0a:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&essence_container_data->instance_uid, tag_data, 16);
-        GST_DEBUG ("  instance uid = %s",
-            mxf_ul_to_string (&essence_container_data->instance_uid, str));
-        break;
-      case 0x2701:
-        if (tag_size != 32)
-          goto error;
-        memcpy (&essence_container_data->linked_package_uid, tag_data, 32);
-        GST_DEBUG ("  linked package = %s",
-            mxf_umid_to_string (&essence_container_data->linked_package_uid,
-                str));
-        break;
-      case 0x0102:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&essence_container_data->generation_uid, tag_data, 16);
-        GST_DEBUG ("  generation uid = %s",
-            mxf_ul_to_string (&essence_container_data->generation_uid, str));
-        break;
-      case 0x3f06:
-        if (tag_size != 4)
-          goto error;
-        essence_container_data->index_sid = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  index sid = %u", essence_container_data->index_sid);
-        break;
-      case 0x3f07:
-        if (tag_size != 4)
-          goto error;
-        essence_container_data->body_sid = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  body sid = %u", essence_container_data->body_sid);
-        break;
-      default:
-        if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
-                &essence_container_data->other_tags))
-          goto error;
-        break;
-    }
-  next:
-
-    data += 4 + tag_size;
-    size -= 4 + tag_size;
-  }
-
-  return TRUE;
-
-error:
-  GST_ERROR ("Invalid essence container data");
-  mxf_metadata_essence_container_data_reset (essence_container_data);
-
-  return FALSE;
-}
-
-void mxf_metadata_essence_container_data_reset
-    (MXFMetadataEssenceContainerData * essence_container_data)
-{
-  g_return_if_fail (essence_container_data != NULL);
-
-  if (essence_container_data->other_tags)
-    g_hash_table_destroy (essence_container_data->other_tags);
-
-  memset (essence_container_data, 0, sizeof (MXFMetadataEssenceContainerData));
-}
-
-gboolean
-mxf_metadata_generic_package_parse (const MXFUL * key,
-    MXFMetadataGenericPackage * generic_package,
-    const MXFPrimerPack * primer, const guint8 * data, guint size)
-{
-  guint16 tag, tag_size;
-  const guint8 *tag_data;
-  gchar str[96];
-
-  g_return_val_if_fail (data != NULL, FALSE);
-
-  memset (generic_package, 0, sizeof (MXFMetadataGenericPackage));
-
-  GST_DEBUG ("Parsing generic package:");
-
-  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
-    if (tag_size == 0 || tag == 0x0000)
-      goto next;
-
-    switch (tag) {
-      case 0x3c0a:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&generic_package->instance_uid, tag_data, 16);
-        GST_DEBUG ("  instance uid = %s",
-            mxf_ul_to_string (&generic_package->instance_uid, str));
-        break;
-      case 0x4401:
-        if (tag_size != 32)
-          goto error;
-        memcpy (&generic_package->package_uid, tag_data, 32);
-        GST_DEBUG ("  UMID = %s",
-            mxf_umid_to_string (&generic_package->package_uid, str));
-        break;
-      case 0x0102:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&generic_package->generation_uid, tag_data, 16);
-        GST_DEBUG ("  generation uid = %s",
-            mxf_ul_to_string (&generic_package->generation_uid, str));
-        break;
-      case 0x4402:
-        generic_package->name = mxf_utf16_to_utf8 (tag_data, tag_size);
-        GST_DEBUG ("  name = %s", GST_STR_NULL (generic_package->name));
-        break;
-      case 0x4405:
-        if (!mxf_timestamp_parse (&generic_package->package_creation_date,
-                tag_data, tag_size))
-          goto error;
-        GST_DEBUG ("  creation date = %d/%u/%u %u:%u:%u.%u",
-            generic_package->package_creation_date.year,
-            generic_package->package_creation_date.month,
-            generic_package->package_creation_date.day,
-            generic_package->package_creation_date.hour,
-            generic_package->package_creation_date.minute,
-            generic_package->package_creation_date.second,
-            (generic_package->package_creation_date.quarter_msecond * 1000) /
-            256);
-        break;
-      case 0x4404:
-        if (!mxf_timestamp_parse (&generic_package->package_modified_date,
-                tag_data, tag_size))
-          goto error;
-        GST_DEBUG ("  modification date = %d/%u/%u %u:%u:%u.%u",
-            generic_package->package_modified_date.year,
-            generic_package->package_modified_date.month,
-            generic_package->package_modified_date.day,
-            generic_package->package_modified_date.hour,
-            generic_package->package_modified_date.minute,
-            generic_package->package_modified_date.second,
-            (generic_package->package_modified_date.quarter_msecond * 1000) /
-            256);
-        break;
-      case 0x4403:{
-        guint32 len;
-        guint i;
-
-
-        len = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  number of tracks = %u", len);
-        if (len == 0)
-          break;
-        if (GST_READ_UINT32_BE (tag_data + 4) != 16)
-          goto error;
-        if (tag_size < 8 + len * 16)
-          goto error;
-
-        generic_package->tracks_uids = g_new (MXFUL, len);
-        generic_package->n_tracks = len;
-        for (i = 0; i < len; i++) {
-          memcpy (&generic_package->tracks_uids[i], tag_data + 8 + i * 16, 16);
-          GST_DEBUG ("  track %u = %s", i,
-              mxf_ul_to_string (&generic_package->tracks_uids[i], str));
-        }
-        break;
-      }
-      case 0x4701:
-        if (tag_size != 16)
-          goto error;
-
-        generic_package->n_descriptors = 1;
-        memcpy (&generic_package->descriptors_uid, tag_data, 16);
-        GST_DEBUG ("  descriptor = %s",
-            mxf_ul_to_string (&generic_package->descriptors_uid, str));
-        break;
-      default:
-        if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
-                &generic_package->other_tags))
-          goto error;
-        break;
-    }
-
-  next:
-    data += 4 + tag_size;
-    size -= 4 + tag_size;
-  }
-
-  return TRUE;
-
-error:
-  GST_ERROR ("Invalid package");
-  mxf_metadata_generic_package_reset (generic_package);
-
-  return FALSE;
-}
-
-void mxf_metadata_generic_package_reset
-    (MXFMetadataGenericPackage * generic_package)
-{
-  g_return_if_fail (generic_package != NULL);
-
-  g_free (generic_package->name);
-  g_free (generic_package->tracks_uids);
-
-  g_free (generic_package->tracks);
-
-  if (generic_package->other_tags)
-    g_hash_table_destroy (generic_package->other_tags);
-
-  g_free (generic_package->descriptors);
-
-  memset (generic_package, 0, sizeof (MXFMetadataGenericPackage));
-}
-
-gboolean
-mxf_metadata_track_parse (const MXFUL * key,
-    MXFMetadataTrack * track, const MXFPrimerPack * primer,
-    guint16 type, const guint8 * data, guint size)
-{
-  guint16 tag, tag_size;
-  const guint8 *tag_data;
-  gchar str[48];
-
-  g_return_val_if_fail (data != NULL, FALSE);
-
-  memset (track, 0, sizeof (MXFMetadataTrack));
-
-  if (type == MXF_METADATA_TRACK)
-    track->variant = MXF_METADATA_TRACK_VARIANT_TIMELINE;
-  else if (type == MXF_METADATA_EVENT_TRACK)
-    track->variant = MXF_METADATA_TRACK_VARIANT_EVENT;
-  else
-    track->variant = MXF_METADATA_TRACK_VARIANT_STATIC;
-
-
-  GST_DEBUG ("Parsing track of type 0x%04x:", type);
-
-  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
-    if (tag_size == 0 || tag == 0x0000)
-      goto next;
-
-    switch (tag) {
-      case 0x3c0a:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&track->instance_uid, tag_data, 16);
-        GST_DEBUG ("  instance uid = %s",
-            mxf_ul_to_string (&track->instance_uid, str));
-        break;
-      case 0x0102:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&track->generation_uid, tag_data, 16);
-        GST_DEBUG ("  generation uid = %s",
-            mxf_ul_to_string (&track->generation_uid, str));
-        break;
-      case 0x4801:
-        if (tag_size != 4)
-          goto error;
-        track->track_id = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  track id = %u", track->track_id);
-        break;
-      case 0x4804:
-        if (tag_size != 4)
-          goto error;
-        track->track_number = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  track number = %u", track->track_number);
-        break;
-      case 0x4802:
-        track->track_name = mxf_utf16_to_utf8 (tag_data, tag_size);
-        GST_DEBUG ("  track name = %s", GST_STR_NULL (track->track_name));
-        break;
-      case 0x4b01:
-      case 0x4901:
-        if (!mxf_fraction_parse (&track->edit_rate, tag_data, tag_size))
-          goto error;
-        GST_DEBUG ("  edit rate = %d/%d", track->edit_rate.n,
-            track->edit_rate.d);
-        break;
-      case 0x4b02:
-      case 0x4902:
-        if (tag_size != 8)
-          goto error;
-        track->origin = GST_READ_UINT64_BE (tag_data);
-        GST_DEBUG ("  origin = %" G_GINT64_FORMAT, track->origin);
-        break;
-      case 0x4803:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&track->sequence_uid, tag_data, 16);
-        GST_DEBUG ("  sequence uid = %s",
-            mxf_ul_to_string (&track->sequence_uid, str));
-        break;
-      default:
-        if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
-                &track->other_tags))
-          goto error;
-        break;
-    }
-
-  next:
-    data += 4 + tag_size;
-    size -= 4 + tag_size;
-  }
-
-  return TRUE;
-
-error:
-  GST_ERROR ("Invalid track");
-  mxf_metadata_track_reset (track);
-
-  return FALSE;
-}
-
-void
-mxf_metadata_track_reset (MXFMetadataTrack * track)
-{
-  g_return_if_fail (track != NULL);
-
-  g_free (track->track_name);
-
-  if (track->descriptor)
-    g_free (track->descriptor);
-
-  if (track->other_tags)
-    g_hash_table_destroy (track->other_tags);
-
-  memset (track, 0, sizeof (MXFMetadataTrack));
-}
-
-/* SMPTE RP224 */
-static const struct
-{
-  guint8 ul[16];
-  MXFMetadataTrackType type;
-} mxf_metadata_track_identifier[] = {
-  { {
-  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01,
-          0x01, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00},
-      MXF_METADATA_TRACK_TIMECODE_12M_INACTIVE}, { {
-  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01,
-          0x02, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_TIMECODE_12M_ACTIVE}, { {
-  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01,
-          0x03, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_TIMECODE_309M}, { {
-  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01,
-          0x10, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_METADATA}, { {
-  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02,
-          0x01, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_PICTURE_ESSENCE}, { {
-  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02,
-          0x02, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_SOUND_ESSENCE}, { {
-  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02,
-          0x03, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_DATA_ESSENCE}, { {
-  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03,
-          0x01, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_AUXILIARY_DATA}, { {
-  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03,
-          0x02, 0x00, 0x00, 0x00}, MXF_METADATA_TRACK_PARSED_TEXT}
-};
-
-MXFMetadataTrackType
-mxf_metadata_track_identifier_parse (const MXFUL * track_identifier)
-{
-  guint i;
-
-  for (i = 0; i < G_N_ELEMENTS (mxf_metadata_track_identifier); i++)
-    if (memcmp (&mxf_metadata_track_identifier[i].ul, &track_identifier->u,
-            16) == 0)
-      return mxf_metadata_track_identifier[i].type;
-
-  return MXF_METADATA_TRACK_UNKNOWN;
-}
-
-gboolean
-mxf_metadata_sequence_parse (const MXFUL * key,
-    MXFMetadataSequence * sequence, const MXFPrimerPack * primer,
-    const guint8 * data, guint size)
-{
-  guint16 tag, tag_size;
-  const guint8 *tag_data;
-  gchar str[48];
-
-  g_return_val_if_fail (data != NULL, FALSE);
-
-  memset (sequence, 0, sizeof (MXFMetadataSequence));
-
-  GST_DEBUG ("Parsing sequence:");
-
-  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
-    if (tag_size == 0 || tag == 0x0000)
-      goto next;
-
-    switch (tag) {
-      case 0x3c0a:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&sequence->instance_uid, tag_data, 16);
-        GST_DEBUG ("  instance uid = %s",
-            mxf_ul_to_string (&sequence->instance_uid, str));
-        break;
-      case 0x0102:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&sequence->generation_uid, tag_data, 16);
-        GST_DEBUG ("  generation uid = %s",
-            mxf_ul_to_string (&sequence->generation_uid, str));
-        break;
-      case 0x0201:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&sequence->data_definition, tag_data, 16);
-        GST_DEBUG ("  data definition = %s",
-            mxf_ul_to_string (&sequence->data_definition, str));
-        break;
-      case 0x0202:
-        if (tag_size != 8)
-          goto error;
-        sequence->duration = GST_READ_UINT64_BE (tag_data);
-        GST_DEBUG ("  duration = %" G_GINT64_FORMAT, sequence->duration);
-        break;
-      case 0x1001:{
-        guint32 len;
-        guint i;
-
-
-        len = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  number of structural components = %u", len);
-        if (len == 0)
-          break;
-        if (GST_READ_UINT32_BE (tag_data + 4) != 16)
-          goto error;
-        if (tag_size < 8 + len * 16)
-          goto error;
-
-        sequence->structural_components_uids = g_new (MXFUL, len);
-        sequence->n_structural_components = len;
-        for (i = 0; i < len; i++) {
-          memcpy (&sequence->structural_components_uids[i],
-              tag_data + 8 + i * 16, 16);
-          GST_DEBUG ("  structural component %u = %s", i,
-              mxf_ul_to_string (&sequence->structural_components_uids[i], str));
-        }
-        break;
-      }
-      default:
-        if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
-                &sequence->other_tags))
-          goto error;
-        break;
-    }
-
-  next:
-    data += 4 + tag_size;
-    size -= 4 + tag_size;
-  }
-
-  return TRUE;
-
-error:
-  GST_ERROR ("Invalid sequence");
-  mxf_metadata_sequence_reset (sequence);
-
-  return FALSE;
-}
-
-void
-mxf_metadata_sequence_reset (MXFMetadataSequence * sequence)
-{
-  g_return_if_fail (sequence != NULL);
-
-  g_free (sequence->structural_components_uids);
-  g_free (sequence->structural_components);
-
-  if (sequence->other_tags)
-    g_hash_table_destroy (sequence->other_tags);
-
-  memset (sequence, 0, sizeof (MXFMetadataSequence));
-}
-
-gboolean
-mxf_metadata_structural_component_parse (const MXFUL * key,
-    MXFMetadataStructuralComponent * component,
-    const MXFPrimerPack * primer, guint16 type, const guint8 * data, guint size)
-{
-  guint16 tag, tag_size;
-  const guint8 *tag_data;
-  gchar str[96];
-
-  g_return_val_if_fail (data != NULL, FALSE);
-
-  memset (component, 0, sizeof (MXFMetadataStructuralComponent));
-
-  GST_DEBUG ("Parsing structural component:");
-
-  component->type = type;
-  if (type == MXF_METADATA_TIMECODE_COMPONENT)
-    GST_DEBUG ("  type = timecode component");
-  else if (type == MXF_METADATA_SOURCE_CLIP)
-    GST_DEBUG ("  type = source clip");
-  else if (type == MXF_METADATA_DM_SEGMENT)
-    GST_DEBUG ("  type = DM segment");
-  else
-    GST_DEBUG ("  type = DM source clip");
-
-  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
-    if (tag_size == 0 || tag == 0x0000)
-      goto next;
-
-    switch (tag) {
-      case 0x3c0a:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&component->instance_uid, tag_data, 16);
-        GST_DEBUG ("  instance uid = %s",
-            mxf_ul_to_string (&component->instance_uid, str));
-        break;
-      case 0x0102:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&component->generation_uid, tag_data, 16);
-        GST_DEBUG ("  generation uid = %s",
-            mxf_ul_to_string (&component->generation_uid, str));
-        break;
-      case 0x0201:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&component->data_definition, tag_data, 16);
-        GST_DEBUG ("  data definition = %s",
-            mxf_ul_to_string (&component->data_definition, str));
-        break;
-      case 0x0202:
-        if (tag_size != 8)
-          goto error;
-        component->duration = GST_READ_UINT64_BE (tag_data);
-        GST_DEBUG ("  duration = %" G_GINT64_FORMAT, component->duration);
-        break;
-        /* Timecode component specifics */
-      case 0x1502:
-        if (type != MXF_METADATA_TIMECODE_COMPONENT)
-          goto DFLT;
-        if (tag_size != 2)
-          goto error;
-        component->timecode_component.rounded_timecode_base =
-            GST_READ_UINT16_BE (tag_data);
-        GST_DEBUG ("  rounded timecode base = %u",
-            component->timecode_component.rounded_timecode_base);
-        break;
-      case 0x1501:
-        if (type != MXF_METADATA_TIMECODE_COMPONENT)
-          goto DFLT;
-        if (tag_size != 8)
-          goto error;
-        component->timecode_component.start_timecode =
-            GST_READ_UINT64_BE (tag_data);
-        GST_DEBUG ("  start timecode = %" G_GINT64_FORMAT,
-            component->timecode_component.start_timecode);
-        break;
-      case 0x1503:
-        if (type != MXF_METADATA_TIMECODE_COMPONENT)
-          goto DFLT;
-        if (tag_size != 1)
-          goto error;
-        component->timecode_component.drop_frame =
-            (GST_READ_UINT8 (tag_data) != 0);
-        GST_DEBUG ("  drop frame = %s",
-            (component->timecode_component.drop_frame) ? "yes" : "no");
-        break;
-        /* Source clip specifics */
-      case 0x1201:
-        if (type != MXF_METADATA_SOURCE_CLIP
-            && type != MXF_METADATA_DM_SOURCE_CLIP)
-          goto DFLT;
-        if (tag_size != 8)
-          goto error;
-
-        if (type == MXF_METADATA_SOURCE_CLIP) {
-          component->source_clip.start_position = GST_READ_UINT64_BE (tag_data);
-          GST_DEBUG ("  start position = %" G_GINT64_FORMAT,
-              component->source_clip.start_position);
-        } else {
-          component->dm_source_clip.start_position =
-              GST_READ_UINT64_BE (tag_data);
-          GST_DEBUG ("  start position = %" G_GINT64_FORMAT,
-              component->dm_source_clip.start_position);
-        }
-        break;
-      case 0x1101:
-        if (type != MXF_METADATA_SOURCE_CLIP
-            && type != MXF_METADATA_DM_SOURCE_CLIP)
-          goto DFLT;
-        if (tag_size != 32)
-          goto error;
-
-        if (type == MXF_METADATA_SOURCE_CLIP) {
-          memcpy (&component->source_clip.source_package_id, tag_data, 32);
-          GST_DEBUG ("  source package id = %s",
-              mxf_umid_to_string (&component->source_clip.source_package_id,
-                  str));
-        } else {
-          memcpy (&component->dm_source_clip.source_package_id, tag_data, 32);
-          GST_DEBUG ("  source package id = %s",
-              mxf_umid_to_string (&component->dm_source_clip.source_package_id,
-                  str));
-        }
-        break;
-      case 0x1102:
-        if (type != MXF_METADATA_SOURCE_CLIP
-            && type != MXF_METADATA_DM_SOURCE_CLIP)
-          goto DFLT;
-        if (tag_size != 4)
-          goto error;
-
-        if (type == MXF_METADATA_SOURCE_CLIP) {
-          component->source_clip.source_track_id =
-              GST_READ_UINT32_BE (tag_data);
-          GST_DEBUG ("  source track id = %u",
-              component->source_clip.source_track_id);
-        } else {
-          component->dm_source_clip.source_track_id =
-              GST_READ_UINT32_BE (tag_data);
-          GST_DEBUG ("  source track id = %u",
-              component->dm_source_clip.source_track_id);
-        }
-        break;
-        /* DM Segment specifics */
-      case 0x0601:
-        if (type != MXF_METADATA_DM_SEGMENT)
-          goto DFLT;
-        if (tag_size != 8)
-          goto error;
-        component->dm_segment.event_start_position =
-            GST_READ_UINT64_BE (tag_data);
-        GST_DEBUG ("  event start position = %" G_GINT64_FORMAT,
-            component->dm_segment.event_start_position);
-        break;
-      case 0x0602:
-        if (type != MXF_METADATA_DM_SEGMENT)
-          goto DFLT;
-        component->dm_segment.event_comment =
-            mxf_utf16_to_utf8 (tag_data, tag_size);
-        GST_DEBUG ("  event comment = %s",
-            GST_STR_NULL (component->dm_segment.event_comment));
-        break;
-      case 0x6102:
-      {
-        guint32 len;
-        guint i;
-
-        if (type != MXF_METADATA_DM_SEGMENT)
-          goto DFLT;
-
-        if (tag_size < 8)
-          goto error;
-        len = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  number of track ids = %u", len);
-        if (len == 0)
-          goto next;
-
-        if (GST_READ_UINT32_BE (tag_data + 4) != 4)
-          goto error;
-
-        if (len * 4 + 8 < tag_size)
-          goto error;
-
-        component->dm_segment.n_track_ids = len;
-        component->dm_segment.track_ids = g_new0 (guint32, len);
-
-        tag_data += 8;
-        tag_size -= 8;
-
-        for (i = 0; i < len; i++) {
-          component->dm_segment.track_ids[i] = GST_READ_UINT32_BE (tag_data);
-          GST_DEBUG ("    track id %u = %u", i,
-              component->dm_segment.track_ids[i]);
-          tag_data += 4;
-          tag_size -= 4;
-        }
-        break;
-      }
-      case 0x6101:
-        if (type != MXF_METADATA_DM_SEGMENT)
-          goto DFLT;
-        if (tag_size != 16)
-          goto error;
-
-        memcpy (&component->dm_segment.dm_framework, tag_data, 16);
-        GST_DEBUG ("  DM framework = %s",
-            mxf_ul_to_string (&component->dm_segment.dm_framework, str));
-        break;
-        /* DM Source Clip specifics */
-      case 0x6103:
-      {
-        guint32 len;
-        guint i;
-
-        if (type != MXF_METADATA_DM_SOURCE_CLIP)
-          goto DFLT;
-        if (tag_size < 8)
-          goto error;
-
-        len = GST_READ_UINT32_BE (tag_data);
-        GST_DEBUG ("  number of track ids = %u", len);
-        if (len == 0)
-          goto next;
-
-        if (GST_READ_UINT32_BE (tag_data + 4) != 4)
-          goto error;
-
-        if (tag_size < 8 + 4 * len)
-          goto error;
-
-        tag_data += 8;
-        tag_size -= 8;
-
-        component->dm_source_clip.n_track_ids = len;
-        component->dm_source_clip.track_ids = g_new0 (guint32, len);
-
-        for (i = 0; i < len; i++) {
-          component->dm_source_clip.track_ids[i] =
-              GST_READ_UINT32_BE (tag_data);
-          GST_DEBUG ("    track id %u = %u", i,
-              component->dm_source_clip.track_ids[i]);
-          tag_data += 4;
-          tag_size -= 4;
-        }
-        break;
-      }
-      DFLT:
-      default:
-        if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
-                &component->other_tags))
-          goto error;
-        break;
-    }
-
-  next:
-    data += 4 + tag_size;
-    size -= 4 + tag_size;
-  }
-
-  return TRUE;
-
-error:
-  GST_ERROR ("Invalid structural component");
-  mxf_metadata_structural_component_reset (component);
-
-  return FALSE;
-}
-
-void mxf_metadata_structural_component_reset
-    (MXFMetadataStructuralComponent * component)
-{
-  g_return_if_fail (component != NULL);
-
-  if (component->type == MXF_METADATA_DM_SEGMENT) {
-    g_free (component->dm_segment.event_comment);
-    g_free (component->dm_segment.track_ids);
-  } else if (component->type == MXF_METADATA_DM_SOURCE_CLIP) {
-    g_free (component->dm_source_clip.track_ids);
-  }
-
-  if (component->other_tags)
-    g_hash_table_destroy (component->other_tags);
-
-  memset (component, 0, sizeof (MXFMetadataStructuralComponent));
-}
-
-gboolean
-mxf_metadata_descriptor_parse (const MXFUL * key,
-    MXFMetadataGenericDescriptor * descriptor,
-    const MXFPrimerPack * primer, guint16 type,
-    const guint8 * data, guint size,
-    MXFMetadataDescriptorHandleTag handle_tag, MXFMetadataDescriptorReset reset)
-{
-  guint16 tag, tag_size;
-  const guint8 *tag_data;
-
-  g_return_val_if_fail (data != NULL, FALSE);
-  g_return_val_if_fail (key != NULL, FALSE);
-  g_return_val_if_fail (primer != NULL, FALSE);
-  g_return_val_if_fail (descriptor != NULL, FALSE);
-  g_return_val_if_fail (handle_tag != NULL, FALSE);
-  g_return_val_if_fail (reset != NULL, FALSE);
-
-  reset (descriptor);
-
-  descriptor->type = type;
-
-  GST_DEBUG ("Parsing descriptor of type 0x%04x:", type);
-
-  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
-    if (tag_size == 0 || tag == 0x0000)
-      goto next;
-
-    if (!handle_tag (descriptor, primer, tag, tag_data, tag_size))
-      if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
-              &((MXFMetadataGenericDescriptor *) descriptor)->other_tags))
-        goto next;
-
-  next:
-    data += 4 + tag_size;
-    size -= 4 + tag_size;
-  }
-  return TRUE;
-}
-
-gboolean
-mxf_metadata_generic_descriptor_handle_tag (MXFMetadataGenericDescriptor *
-    descriptor, const MXFPrimerPack * primer, guint16 tag,
-    const guint8 * tag_data, guint16 tag_size)
-{
-  gboolean ret = FALSE;
-  gchar str[48];
-
-  switch (tag) {
-    case 0x3c0a:
-      if (tag_size != 16)
-        goto error;
-      memcpy (&descriptor->instance_uid, tag_data, 16);
-      GST_DEBUG ("  instance uid = %s",
-          mxf_ul_to_string (&descriptor->instance_uid, str));
-      ret = TRUE;
-      break;
-    case 0x0102:
-      if (tag_size != 16)
-        goto error;
-      memcpy (&descriptor->generation_uid, tag_data, 16);
-      GST_DEBUG ("  generation uid = %s",
-          mxf_ul_to_string (&descriptor->generation_uid, str));
-      ret = TRUE;
-      break;
-    case 0x2f01:{
-      guint32 len;
-      guint i;
-
-      if (tag_size < 8)
-        goto error;
-
-      len = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  number of locators = %u", len);
-      if (len == 0)
-        return TRUE;
-
-      if (GST_READ_UINT32_BE (tag_data + 4) != 16)
-        goto error;
-
-      descriptor->locators_uids = g_new (MXFUL, len);
-      descriptor->n_locators = len;
-      for (i = 0; i < len; i++) {
-        memcpy (&descriptor->locators_uids[i], tag_data + 8 + i * 16, 16);
-        GST_DEBUG ("  locator %u = %s", i,
-            mxf_ul_to_string (&descriptor->locators_uids[i], str));
-      }
-      ret = TRUE;
-      break;
-    }
-  }
-
-  return ret;
-
-error:
-  GST_ERROR ("Invalid generic descriptor tag 0x%04x of size %u", tag, tag_size);
-
-  return TRUE;
-}
-
-void mxf_metadata_generic_descriptor_reset
-    (MXFMetadataGenericDescriptor * descriptor)
-{
-  g_return_if_fail (descriptor != NULL);
-
-  if (descriptor->locators_uids)
-    g_free (descriptor->locators_uids);
-
-  if (descriptor->locators)
-    g_free (descriptor->locators);
-
-  if (descriptor->other_tags)
-    g_hash_table_destroy (descriptor->other_tags);
-
-  memset (descriptor, 0, sizeof (MXFMetadataGenericDescriptor));
-}
-
-gboolean
-mxf_metadata_file_descriptor_handle_tag (MXFMetadataGenericDescriptor * d,
-    const MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
-    guint16 tag_size)
-{
-  MXFMetadataFileDescriptor *descriptor = (MXFMetadataFileDescriptor *) d;
-  gboolean ret = FALSE;
-  gchar str[48];
-
-  switch (tag) {
-    case 0x3006:
-      if (tag_size != 4)
-        goto error;
-      descriptor->linked_track_id = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  linked track id = %u", descriptor->linked_track_id);
-      ret = TRUE;
-      break;
-    case 0x3001:
-      if (!mxf_fraction_parse (&descriptor->sample_rate, tag_data, tag_size))
-        goto error;
-      GST_DEBUG ("  sample rate = %d/%d", descriptor->sample_rate.n,
-          descriptor->sample_rate.d);
-      ret = TRUE;
-      break;
-    case 0x3002:
-      if (tag_size != 8)
-        goto error;
-      descriptor->container_duration = GST_READ_UINT64_BE (tag_data);
-      GST_DEBUG ("  container duration = %" G_GINT64_FORMAT,
-          descriptor->container_duration);
-      ret = TRUE;
-      break;
-    case 0x3004:
-      if (tag_size != 16)
-        goto error;
-      memcpy (&descriptor->essence_container, tag_data, 16);
-      GST_DEBUG ("  essence container = %s",
-          mxf_ul_to_string (&descriptor->essence_container, str));
-      ret = TRUE;
-      break;
-    case 0x3005:
-      if (tag_size != 16)
-        goto error;
-      memcpy (&descriptor->codec, tag_data, 16);
-      GST_DEBUG ("  codec = %s", mxf_ul_to_string (&descriptor->codec, str));
-      ret = TRUE;
-      break;
-    default:
-      ret =
-          mxf_metadata_generic_descriptor_handle_tag (d, primer, tag, tag_data,
-          tag_size);
-      break;
-  }
-
-  return ret;
-
-error:
-  GST_ERROR ("Invalid file descriptor tag 0x%04x of size %u", tag, tag_size);
-
-  return TRUE;
-}
-
-void
-mxf_metadata_file_descriptor_reset (MXFMetadataFileDescriptor * descriptor)
-{
-  g_return_if_fail (descriptor != NULL);
-
-  mxf_metadata_generic_descriptor_reset ((MXFMetadataGenericDescriptor *)
-      descriptor);
-
-  MXF_METADATA_DESCRIPTOR_CLEAR (descriptor, MXFMetadataFileDescriptor,
-      MXFMetadataGenericDescriptor);
-
-  descriptor->parent.is_file_descriptor = TRUE;
-}
-
-gboolean
-    mxf_metadata_generic_sound_essence_descriptor_handle_tag
-    (MXFMetadataGenericDescriptor * d, const MXFPrimerPack * primer,
-    guint16 tag, const guint8 * tag_data, guint16 tag_size)
-{
-  MXFMetadataGenericSoundEssenceDescriptor *descriptor =
-      (MXFMetadataGenericSoundEssenceDescriptor *) d;
-  gboolean ret = FALSE;
-  gchar str[48];
-
-  switch (tag) {
-    case 0x3d03:
-      if (!mxf_fraction_parse (&descriptor->audio_sampling_rate, tag_data,
-              tag_size))
-        goto error;
-      GST_DEBUG ("  audio sampling rate = %d/%d",
-          descriptor->audio_sampling_rate.n, descriptor->audio_sampling_rate.d);
-      ret = TRUE;
-      break;
-    case 0x3d02:
-      if (tag_size != 1)
-        goto error;
-      descriptor->locked = (GST_READ_UINT8 (tag_data) != 0);
-      GST_DEBUG ("  locked = %s", (descriptor->locked) ? "yes" : "no");
-      ret = TRUE;
-      break;
-    case 0x3d04:
-      if (tag_size != 1)
-        goto error;
-      descriptor->audio_ref_level = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  audio ref level = %d", descriptor->audio_ref_level);
-      ret = TRUE;
-      break;
-    case 0x3d05:
-      if (tag_size != 1)
-        goto error;
-      descriptor->electro_spatial_formulation = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  electro spatial formulation = %u",
-          descriptor->electro_spatial_formulation);
-      ret = TRUE;
-      break;
-    case 0x3d07:
-      if (tag_size != 4)
-        goto error;
-      descriptor->channel_count = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  channel count = %u", descriptor->channel_count);
-      ret = TRUE;
-      break;
-    case 0x3d01:
-      if (tag_size != 4)
-        goto error;
-      descriptor->quantization_bits = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  quantization bits = %u", descriptor->quantization_bits);
-      ret = TRUE;
-      break;
-    case 0x3d0c:
-      if (tag_size != 1)
-        goto error;
-      descriptor->dial_norm = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  dial norm = %d", descriptor->dial_norm);
-      ret = TRUE;
-      break;
-    case 0x3d06:
-      if (tag_size != 16)
-        goto error;
-      memcpy (&descriptor->sound_essence_compression, tag_data, 16);
-      GST_DEBUG ("  sound essence compression = %s",
-          mxf_ul_to_string (&descriptor->sound_essence_compression, str));
-      ret = TRUE;
-      break;
-    default:
-      ret =
-          mxf_metadata_file_descriptor_handle_tag (d, primer, tag, tag_data,
-          tag_size);
-      break;
-  }
-
-  return ret;
-
-error:
-  GST_ERROR ("Invalid generic sound essence descriptor tag 0x%04x of size %u",
-      tag, tag_size);
-
-  return TRUE;
-}
-
-void mxf_metadata_generic_sound_essence_descriptor_reset
-    (MXFMetadataGenericSoundEssenceDescriptor * descriptor)
-{
-  g_return_if_fail (descriptor != NULL);
-
-  mxf_metadata_file_descriptor_reset ((MXFMetadataFileDescriptor *) descriptor);
-
-  MXF_METADATA_DESCRIPTOR_CLEAR (descriptor,
-      MXFMetadataGenericSoundEssenceDescriptor, MXFMetadataFileDescriptor);
-
-  descriptor->audio_sampling_rate.n = 48000;
-  descriptor->audio_sampling_rate.d = 1;
-}
-
-gboolean
-    mxf_metadata_generic_picture_essence_descriptor_handle_tag
-    (MXFMetadataGenericDescriptor * d, const MXFPrimerPack * primer,
-    guint16 tag, const guint8 * tag_data, guint16 tag_size)
-{
-  MXFMetadataGenericPictureEssenceDescriptor *descriptor =
-      (MXFMetadataGenericPictureEssenceDescriptor *) d;
-  gboolean ret = FALSE;
-  gchar str[48];
-
-  switch (tag) {
-    case 0x3215:
-      if (tag_size != 1)
-        goto error;
-      descriptor->signal_standard = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  signal standard = %u", descriptor->signal_standard);
-      ret = TRUE;
-      break;
-    case 0x320c:
-      if (tag_size != 1)
-        goto error;
-      descriptor->frame_layout = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  frame layout = %u", descriptor->frame_layout);
-      ret = TRUE;
-      break;
-    case 0x3203:
-      if (tag_size != 4)
-        goto error;
-      descriptor->stored_width = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  stored width = %u", descriptor->stored_width);
-      ret = TRUE;
-      break;
-    case 0x3202:
-      if (tag_size != 4)
-        goto error;
-      descriptor->stored_height = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  stored height = %u", descriptor->stored_height);
-      ret = TRUE;
-      break;
-    case 0x3216:
-      if (tag_size != 4)
-        goto error;
-      descriptor->stored_f2_offset = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  stored f2 offset = %d", descriptor->stored_f2_offset);
-      ret = TRUE;
-      break;
-    case 0x3205:
-      if (tag_size != 4)
-        goto error;
-      descriptor->sampled_width = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  sampled width = %u", descriptor->sampled_width);
-      ret = TRUE;
-      break;
-    case 0x3204:
-      if (tag_size != 4)
-        goto error;
-      descriptor->sampled_height = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  sampled height = %u", descriptor->sampled_height);
-      ret = TRUE;
-      break;
-    case 0x3206:
-      if (tag_size != 4)
-        goto error;
-      descriptor->sampled_x_offset = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  sampled x offset = %d", descriptor->sampled_x_offset);
-      ret = TRUE;
-      break;
-    case 0x3207:
-      if (tag_size != 4)
-        goto error;
-      descriptor->sampled_y_offset = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  sampled y offset = %d", descriptor->sampled_y_offset);
-      ret = TRUE;
-      break;
-    case 0x3208:
-      if (tag_size != 4)
-        goto error;
-      descriptor->display_height = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  display height = %u", descriptor->display_height);
-      ret = TRUE;
-      break;
-    case 0x3209:
-      if (tag_size != 4)
-        goto error;
-      descriptor->display_width = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  display width = %u", descriptor->display_width);
-      ret = TRUE;
-      break;
-    case 0x320a:
-      if (tag_size != 4)
-        goto error;
-      descriptor->display_x_offset = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  display x offset = %d", descriptor->display_x_offset);
-      ret = TRUE;
-      break;
-    case 0x320b:
-      if (tag_size != 4)
-        goto error;
-      descriptor->display_y_offset = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  display y offset = %d", descriptor->display_y_offset);
-      ret = TRUE;
-      break;
-    case 0x3217:
-      if (tag_size != 4)
-        goto error;
-      descriptor->display_f2_offset = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  display f2 offset = %d", descriptor->display_f2_offset);
-      ret = TRUE;
-      break;
-    case 0x320e:
-      if (!mxf_fraction_parse (&descriptor->aspect_ratio, tag_data, tag_size))
-        goto error;
-      GST_DEBUG ("  aspect ratio = %d/%d", descriptor->aspect_ratio.n,
-          descriptor->aspect_ratio.d);
-      ret = TRUE;
-      break;
-    case 0x3218:
-      if (tag_size != 1)
-        goto error;
-      descriptor->active_format_descriptor = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  active format descriptor = %u",
-          descriptor->active_format_descriptor);
-      ret = TRUE;
-      break;
-    case 0x320d:
-      if (tag_size < 8)
-        goto error;
-
-      if (GST_READ_UINT32_BE (tag_data) == 0)
-        return TRUE;
-
-      if (GST_READ_UINT32_BE (tag_data) != 2 &&
-          GST_READ_UINT32_BE (tag_data + 4) != 4)
-        goto error;
-
-      if (tag_size != 16)
-        goto error;
-
-      descriptor->video_line_map[0] = GST_READ_UINT32_BE (tag_data + 8);
-      descriptor->video_line_map[1] = GST_READ_UINT32_BE (tag_data + 12);
-      GST_DEBUG ("  video line map = {%i, %i}", descriptor->video_line_map[0],
-          descriptor->video_line_map[1]);
-      ret = TRUE;
-      break;
-    case 0x320f:
-      if (tag_size != 1)
-        goto error;
-      descriptor->alpha_transparency = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  alpha transparency = %u", descriptor->alpha_transparency);
-      ret = TRUE;
-      break;
-    case 0x3210:
-      if (tag_size != 16)
-        goto error;
-      memcpy (&descriptor->capture_gamma, tag_data, 16);
-      GST_DEBUG ("  capture gamma = %s",
-          mxf_ul_to_string (&descriptor->capture_gamma, str));
-      ret = TRUE;
-      break;
-    case 0x3211:
-      if (tag_size != 4)
-        goto error;
-      descriptor->image_alignment_offset = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  image alignment offset = %u",
-          descriptor->image_alignment_offset);
-      ret = TRUE;
-      break;
-    case 0x3213:
-      if (tag_size != 4)
-        goto error;
-      descriptor->image_start_offset = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  image start offset = %u", descriptor->image_start_offset);
-      ret = TRUE;
-      break;
-    case 0x3214:
-      if (tag_size != 4)
-        goto error;
-      descriptor->image_end_offset = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  image end offset = %u", descriptor->image_end_offset);
-      ret = TRUE;
-      break;
-    case 0x3212:
-      if (tag_size != 1)
-        goto error;
-      descriptor->field_dominance = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  field dominance = %u", descriptor->field_dominance);
-      ret = TRUE;
-      break;
-    case 0x3201:
-      if (tag_size != 16)
-        goto error;
-      memcpy (&descriptor->picture_essence_coding, tag_data, 16);
-      GST_DEBUG ("  picture essence coding = %s",
-          mxf_ul_to_string (&descriptor->picture_essence_coding, str));
-      ret = TRUE;
-      break;
-    default:
-      ret =
-          mxf_metadata_file_descriptor_handle_tag (d, primer, tag, tag_data,
-          tag_size);
-      break;
-  }
-
-  return ret;
-
-error:
-  GST_ERROR ("Invalid generic picture essence descriptor tag 0x%04x of size %u",
-      tag, tag_size);
-
-  return TRUE;
-}
-
-void mxf_metadata_generic_picture_essence_descriptor_reset
-    (MXFMetadataGenericPictureEssenceDescriptor * descriptor)
-{
-  g_return_if_fail (descriptor != NULL);
-
-  mxf_metadata_file_descriptor_reset ((MXFMetadataFileDescriptor *) descriptor);
-
-  MXF_METADATA_DESCRIPTOR_CLEAR (descriptor,
-      MXFMetadataGenericPictureEssenceDescriptor, MXFMetadataFileDescriptor);
-
-  descriptor->signal_standard = 1;
-}
-
-void mxf_metadata_generic_picture_essence_descriptor_set_caps
-    (MXFMetadataGenericPictureEssenceDescriptor * descriptor, GstCaps * caps)
-{
-  guint par_n, par_d;
-  guint width, height;
-  MXFMetadataFileDescriptor *f = (MXFMetadataFileDescriptor *) descriptor;
-
-  g_return_if_fail (descriptor != NULL);
-  g_return_if_fail (GST_IS_CAPS (caps));
-
-  gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, f->sample_rate.n,
-      f->sample_rate.d, NULL);
-
-  width = descriptor->stored_width;
-  height = descriptor->stored_height;
-
-  /* If the video is stored as separate fields the
-   * height is only the height of one field, i.e.
-   * half the height of the frame.
-   *
-   * See SMPTE 377M E2.2 and E1.2
-   */
-  if (descriptor->frame_layout != 0)
-    height *= 2;
-
-  if (width == 0 || height == 0)
-    return;
-
-  gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height", G_TYPE_INT,
-      height, NULL);
-
-  if (descriptor->aspect_ratio.n == 0 || descriptor->aspect_ratio.d == 0)
-    return;
-
-  par_n = height * descriptor->aspect_ratio.n;
-  par_d = width * descriptor->aspect_ratio.d;
-
-  gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
-      par_n, par_d, NULL);
-}
-
-gboolean
-    mxf_metadata_cdci_picture_essence_descriptor_handle_tag
-    (MXFMetadataGenericDescriptor * d, const MXFPrimerPack * primer,
-    guint16 tag, const guint8 * tag_data, guint16 tag_size) {
-  MXFMetadataCDCIPictureEssenceDescriptor *descriptor =
-      (MXFMetadataCDCIPictureEssenceDescriptor *) d;
-  gboolean ret = FALSE;
-
-  switch (tag) {
-    case 0x3301:
-      if (tag_size != 4)
-        goto error;
-      descriptor->component_depth = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  component depth = %u", descriptor->component_depth);
-      ret = TRUE;
-      break;
-    case 0x3302:
-      if (tag_size != 4)
-        goto error;
-      descriptor->horizontal_subsampling = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  horizontal subsampling = %u",
-          descriptor->horizontal_subsampling);
-      ret = TRUE;
-      break;
-    case 0x3308:
-      if (tag_size != 4)
-        goto error;
-      descriptor->vertical_subsampling = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  vertical subsampling = %u",
-          descriptor->vertical_subsampling);
-      ret = TRUE;
-      break;
-    case 0x3303:
-      if (tag_size != 1)
-        goto error;
-      descriptor->color_siting = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  color siting = %u", descriptor->color_siting);
-      ret = TRUE;
-      break;
-    case 0x330b:
-      if (tag_size != 1)
-        goto error;
-      descriptor->reversed_byte_order = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  reversed byte order = %s",
-          (descriptor->reversed_byte_order) ? "yes" : "no");
-      ret = TRUE;
-      break;
-    case 0x3307:
-      if (tag_size != 2)
-        goto error;
-      descriptor->padding_bits = GST_READ_UINT16_BE (tag_data);
-      GST_DEBUG ("  padding bits = %d", descriptor->padding_bits);
-      ret = TRUE;
-      break;
-    case 0x3309:
-      if (tag_size != 4)
-        goto error;
-      descriptor->alpha_sample_depth = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  alpha sample depth = %u", descriptor->alpha_sample_depth);
-      ret = TRUE;
-      break;
-    case 0x3304:
-      if (tag_size != 4)
-        goto error;
-      descriptor->black_ref_level = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  black ref level = %u", descriptor->black_ref_level);
-      ret = TRUE;
-      break;
-    case 0x3305:
-      if (tag_size != 4)
-        goto error;
-      descriptor->white_ref_level = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  white ref level = %u", descriptor->white_ref_level);
-      ret = TRUE;
-      break;
-    case 0x3306:
-      if (tag_size != 4)
-        goto error;
-      descriptor->color_range = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  color range = %u", descriptor->color_range);
-      ret = TRUE;
-      break;
-    default:
-      ret =
-          mxf_metadata_generic_picture_essence_descriptor_handle_tag (d, primer,
-          tag, tag_data, tag_size);
-      break;
-  }
-
-  return ret;
-
-error:
-  GST_ERROR ("Invalid CDCI picture essence descriptor tag 0x%04x of size %u",
-      tag, tag_size);
-
-  return TRUE;
-}
-
-void mxf_metadata_cdci_picture_essence_descriptor_reset
-    (MXFMetadataCDCIPictureEssenceDescriptor * descriptor)
-{
-  g_return_if_fail (descriptor != NULL);
-
-  mxf_metadata_generic_picture_essence_descriptor_reset (
-      (MXFMetadataGenericPictureEssenceDescriptor *) descriptor);
-
-  MXF_METADATA_DESCRIPTOR_CLEAR (descriptor,
-      MXFMetadataCDCIPictureEssenceDescriptor,
-      MXFMetadataGenericPictureEssenceDescriptor);
-}
-
-gboolean
-    mxf_metadata_rgba_picture_essence_descriptor_handle_tag
-    (MXFMetadataGenericDescriptor * d, const MXFPrimerPack * primer,
-    guint16 tag, const guint8 * tag_data, guint16 tag_size)
-{
-  MXFMetadataRGBAPictureEssenceDescriptor *descriptor =
-      (MXFMetadataRGBAPictureEssenceDescriptor *) d;
-  gboolean ret = FALSE;
-
-  switch (tag) {
-    case 0x3406:
-      if (tag_size != 4)
-        goto error;
-      descriptor->component_max_ref = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  component max ref = %u", descriptor->component_max_ref);
-      ret = TRUE;
-      break;
-    case 0x3407:
-      if (tag_size != 4)
-        goto error;
-      descriptor->component_min_ref = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  component min ref = %u", descriptor->component_min_ref);
-      ret = TRUE;
-      break;
-    case 0x3408:
-      if (tag_size != 4)
-        goto error;
-      descriptor->alpha_max_ref = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  alpha max ref = %u", descriptor->alpha_max_ref);
-      ret = TRUE;
-      break;
-    case 0x3409:
-      if (tag_size != 4)
-        goto error;
-      descriptor->alpha_min_ref = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  alpha min ref = %u", descriptor->alpha_min_ref);
-      ret = TRUE;
-      break;
-    case 0x3405:
-      if (tag_size != 1)
-        goto error;
-      descriptor->scanning_direction = GST_READ_UINT8 (tag_data);
-      GST_DEBUG ("  scanning direction = %u", descriptor->scanning_direction);
-      ret = TRUE;
-      break;
-    case 0x3401:{
-      guint i, len;
-
-      if (tag_size % 2 != 0)
-        goto error;
-
-      i = 0;
-      while (tag_data[i] != 0 && tag_data[i + 1] != 0 && i + 2 <= tag_size)
-        i += 2;
-      len = i / 2;
-
-      descriptor->n_pixel_layout = len;
-      GST_DEBUG ("  number of pixel layouts = %u", len);
-      if (len == 0)
-        return TRUE;
-
-      descriptor->pixel_layout = g_malloc0 (2 * len);
-
-      for (i = 0; i < len; i++) {
-        descriptor->pixel_layout[2 * i] = tag_data[2 * i];
-        descriptor->pixel_layout[2 * i + 1] = tag_data[2 * i + 1];
-        GST_DEBUG ("    pixel layout %u = %c : %u", i,
-            (gchar) descriptor->pixel_layout[2 * i],
-            descriptor->pixel_layout[2 * i + 1]);
-      }
-
-      ret = TRUE;
-      break;
-    }
-    case 0x3403:
-    case 0x3404:
-      /* TODO: handle this */
-      GST_WARNING ("  tag 0x%04x not implemented yet", tag);
-      ret = TRUE;
-      break;
-    default:
-      ret =
-          mxf_metadata_generic_picture_essence_descriptor_handle_tag (d, primer,
-          tag, tag_data, tag_size);
-      break;
-  }
-
-  return ret;
-
-error:
-  GST_ERROR ("Invalid RGBA picture essence descriptor tag 0x%04x of size %u",
-      tag, tag_size);
-
-  return TRUE;
-}
-
-void mxf_metadata_rgba_picture_essence_descriptor_reset
-    (MXFMetadataRGBAPictureEssenceDescriptor * descriptor)
-{
-  g_return_if_fail (descriptor != NULL);
-
-  mxf_metadata_generic_picture_essence_descriptor_reset (
-      (MXFMetadataGenericPictureEssenceDescriptor *) descriptor);
-
-  g_free (descriptor->pixel_layout);
-
-  MXF_METADATA_DESCRIPTOR_CLEAR (descriptor,
-      MXFMetadataRGBAPictureEssenceDescriptor,
-      MXFMetadataGenericPictureEssenceDescriptor);
-
-  descriptor->component_max_ref = 255;
-  descriptor->alpha_max_ref = 255;
-}
-
-gboolean
-    mxf_metadata_generic_data_essence_descriptor_handle_tag
-    (MXFMetadataGenericDescriptor * d, const MXFPrimerPack * primer,
-    guint16 tag, const guint8 * tag_data, guint16 tag_size)
-{
-  MXFMetadataGenericDataEssenceDescriptor *descriptor =
-      (MXFMetadataGenericDataEssenceDescriptor *) d;
-  gboolean ret = FALSE;
-  gchar str[48];
-
-  switch (tag) {
-    case 0x3e01:
-      if (tag_size != 16)
-        goto error;
-      memcpy (&descriptor->data_essence_compression, tag_data, 16);
-      GST_DEBUG ("  data essence compression = %s",
-          mxf_ul_to_string (&descriptor->data_essence_compression, str));
-      ret = TRUE;
-      break;
-    default:
-      ret =
-          mxf_metadata_file_descriptor_handle_tag (d, primer, tag, tag_data,
-          tag_size);
-      break;
-  }
-
-  return ret;
-
-error:
-  GST_ERROR ("Invalid generic data essence descriptor tag 0x%04x of size %u",
-      tag, tag_size);
-
-  return TRUE;
-}
-
-void mxf_metadata_generic_data_essence_descriptor_reset
-    (MXFMetadataGenericDataEssenceDescriptor * descriptor)
-{
-  g_return_if_fail (descriptor != NULL);
-
-  mxf_metadata_file_descriptor_reset ((MXFMetadataFileDescriptor *) descriptor);
-
-  MXF_METADATA_DESCRIPTOR_CLEAR (descriptor,
-      MXFMetadataGenericDataEssenceDescriptor, MXFMetadataFileDescriptor);
-}
-
-gboolean
-mxf_metadata_multiple_descriptor_handle_tag (MXFMetadataGenericDescriptor * d,
-    const MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
-    guint16 tag_size)
-{
-  MXFMetadataMultipleDescriptor *descriptor =
-      (MXFMetadataMultipleDescriptor *) d;
-  gboolean ret = FALSE;
-  gchar str[48];
-
-  switch (tag) {
-    case 0x3f01:{
-      guint32 len;
-      guint i;
-
-      if (tag_size < 8)
-        goto error;
-      len = GST_READ_UINT32_BE (tag_data);
-      GST_DEBUG ("  number of sub descriptors = %u", len);
-      if (len == 0)
-        return TRUE;
-
-      if (GST_READ_UINT32_BE (tag_data + 4) != 16)
-        goto error;
-
-      descriptor->n_sub_descriptors = len;
-      descriptor->sub_descriptors_uids = g_new0 (MXFUL, len);
-      for (i = 0; i < len; i++) {
-        memcpy (&descriptor->sub_descriptors_uids[i], tag_data + 8 + i * 16,
-            16);
-        GST_DEBUG ("  sub descriptor %u = %s", i,
-            mxf_ul_to_string (&descriptor->sub_descriptors_uids[i], str));
-      }
-      ret = TRUE;
-      break;
-    }
-    default:
-      ret =
-          mxf_metadata_file_descriptor_handle_tag (d, primer, tag, tag_data,
-          tag_size);
-      break;
-  }
-
-  return ret;
-
-error:
-  GST_ERROR ("Invalid multiple descriptor tag 0x%04x of size %u", tag,
-      tag_size);
-
-  return TRUE;
-}
-
-void mxf_metadata_multiple_descriptor_reset
-    (MXFMetadataMultipleDescriptor * descriptor)
-{
-  g_return_if_fail (descriptor != NULL);
-
-  g_free (descriptor->sub_descriptors_uids);
-  g_free (descriptor->sub_descriptors);
-
-  mxf_metadata_file_descriptor_reset ((MXFMetadataFileDescriptor *) descriptor);
-
-  MXF_METADATA_DESCRIPTOR_CLEAR (descriptor, MXFMetadataMultipleDescriptor,
-      MXFMetadataFileDescriptor);
-}
-
-gboolean
-mxf_metadata_locator_parse (const MXFUL * key,
-    MXFMetadataLocator * locator, const MXFPrimerPack * primer,
-    guint16 type, const guint8 * data, guint size)
-{
-  guint16 tag, tag_size;
-  const guint8 *tag_data;
-  gchar str[48];
-
-  g_return_val_if_fail (data != NULL, FALSE);
-
-  memset (locator, 0, sizeof (MXFMetadataLocator));
-
-  locator->type = type;
-
-  GST_DEBUG ("Parsing locator of type 0x%04x:", type);
-
-  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
-    if (tag_size == 0 || tag == 0x0000)
-      goto next;
-
-    switch (tag) {
-      case 0x3c0a:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&locator->instance_uid, tag_data, 16);
-        GST_DEBUG ("  instance uid = %s",
-            mxf_ul_to_string (&locator->instance_uid, str));
-        break;
-      case 0x0102:
-        if (tag_size != 16)
-          goto error;
-        memcpy (&locator->generation_uid, tag_data, 16);
-        GST_DEBUG ("  generation uid = %s",
-            mxf_ul_to_string (&locator->generation_uid, str));
-        break;
-      case 0x4101:
-        if (type != MXF_METADATA_TEXT_LOCATOR
-            && type != MXF_METADATA_NETWORK_LOCATOR)
-          goto DFLT;
-        locator->location = mxf_utf16_to_utf8 (tag_data, tag_size);
-        GST_DEBUG ("  location = %s", GST_STR_NULL (locator->location));
-        break;
-      DFLT:
-      default:
-        if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
-                &locator->other_tags))
-          goto error;
-        break;
-    }
-
-  next:
-    data += 4 + tag_size;
-    size -= 4 + tag_size;
-  }
-
-  return TRUE;
-
-error:
-  GST_ERROR ("Invalid locator");
-  mxf_metadata_locator_reset (locator);
-
-  return FALSE;
-}
-
-void
-mxf_metadata_locator_reset (MXFMetadataLocator * locator)
-{
-  g_return_if_fail (locator != NULL);
-
-  if (locator->location)
-    g_free (locator->location);
-
-  if (locator->other_tags)
-    g_hash_table_destroy (locator->other_tags);
-
-  memset (locator, 0, sizeof (MXFMetadataLocator));
-}
index 200fc78..3e68f67 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+/* Handling of the basic MXF types */
+
 #ifndef __MXF_PARSE_H__
 #define __MXF_PARSE_H__
 
 #include <string.h>
 
 #include "mxftypes.h"
+#include "mxfmetadata.h"
 
 typedef GstFlowReturn (*MXFEssenceElementHandler) (const MXFUL *key, GstBuffer *buffer, GstCaps *caps, MXFMetadataGenericPackage *package, MXFMetadataTrack *track, MXFMetadataStructuralComponent *component, gpointer mapping_data, GstBuffer **outbuf);
 
-typedef gboolean (*MXFMetadataDescriptorHandleTag) (MXFMetadataGenericDescriptor *descriptor,
-    const MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint16 tag_size);
-typedef void (*MXFMetadataDescriptorReset) (MXFMetadataGenericDescriptor *descriptor);
-
 gchar * mxf_ul_to_string (const MXFUL *ul, gchar str[48]);
 gboolean mxf_ul_is_equal (const MXFUL *a, const MXFUL *b);
 gboolean mxf_ul_is_zero (const MXFUL *ul);
@@ -87,80 +86,9 @@ gboolean mxf_local_tag_parse (const guint8 * data, guint size, guint16 * tag,
     guint16 * tag_size, const guint8 ** tag_data);
 void gst_mxf_local_tag_free (MXFLocalTag *tag);
 
-gboolean gst_metadata_add_custom_tag (const MXFPrimerPack *primer,
+gboolean mxf_local_tag_add_to_hash_table (const MXFPrimerPack *primer,
   guint16 tag, const guint8 *tag_data, guint16 tag_size,
   GHashTable **hash_table);
 
-gboolean mxf_metadata_preface_parse (const MXFUL *key, MXFMetadataPreface *preface, const MXFPrimerPack *primer, const guint8 *data, guint size);
-void mxf_metadata_preface_reset (MXFMetadataPreface *preface);
-
-gboolean mxf_metadata_identification_parse (const MXFUL *key, MXFMetadataIdentification *identification, const MXFPrimerPack *primer, const guint8 *data, guint size);
-void mxf_metadata_identification_reset (MXFMetadataIdentification *identification);
-
-gboolean mxf_metadata_content_storage_parse (const MXFUL *key, MXFMetadataContentStorage *content_storage, const MXFPrimerPack *primer, const guint8 *data, guint size);
-void mxf_metadata_content_storage_reset (MXFMetadataContentStorage *content_storage);
-
-gboolean mxf_metadata_essence_container_data_parse (const MXFUL *key, MXFMetadataEssenceContainerData *essence_container_data, const MXFPrimerPack *primer, const guint8 *data, guint size);
-void mxf_metadata_essence_container_data_reset (MXFMetadataEssenceContainerData *essence_container_data);
-
-gboolean mxf_metadata_generic_package_parse (const MXFUL *key, MXFMetadataGenericPackage *generic_package, const MXFPrimerPack *primer, const guint8 *data, guint size);
-void mxf_metadata_generic_package_reset (MXFMetadataGenericPackage *generic_package);
-
-gboolean mxf_metadata_track_parse (const MXFUL *key, MXFMetadataTrack *track, const MXFPrimerPack *primer, guint16 type, const guint8 *data, guint size);
-void mxf_metadata_track_reset (MXFMetadataTrack *track);
-
-MXFMetadataTrackType mxf_metadata_track_identifier_parse (const MXFUL *track_identifier);
-
-gboolean mxf_metadata_sequence_parse (const MXFUL *key, MXFMetadataSequence *sequence, const MXFPrimerPack *primer, const guint8 *data, guint size);
-void mxf_metadata_sequence_reset (MXFMetadataSequence *sequence);
-
-gboolean mxf_metadata_structural_component_parse (const MXFUL *key, MXFMetadataStructuralComponent *component, const MXFPrimerPack *primer, guint16 type, const guint8 *data, guint size);
-void mxf_metadata_structural_component_reset (MXFMetadataStructuralComponent *component);
-
-gboolean
-mxf_metadata_descriptor_parse (const MXFUL * key, MXFMetadataGenericDescriptor * descriptor, const MXFPrimerPack * primer, guint16 type, const guint8 * data, guint size, MXFMetadataDescriptorHandleTag handle_tag, MXFMetadataDescriptorReset reset);
-
-#define MXF_METADATA_DESCRIPTOR_CLEAR(descriptor, type, parent_type) \
-  G_STMT_START { \
-    guint8 *___data = (guint8 *) descriptor + sizeof (parent_type); \
-    memset (___data, 0, sizeof (type) - sizeof (parent_type)); \
-  } G_STMT_END
-
-gboolean mxf_metadata_generic_descriptor_handle_tag (MXFMetadataGenericDescriptor *descriptor,
-    const MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint16 tag_size);
-void mxf_metadata_generic_descriptor_reset (MXFMetadataGenericDescriptor *descriptor);
-
-gboolean mxf_metadata_file_descriptor_handle_tag (MXFMetadataGenericDescriptor *descriptor,
-    const MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint16 tag_size);
-void mxf_metadata_file_descriptor_reset (MXFMetadataFileDescriptor *descriptor);
-
-gboolean mxf_metadata_generic_sound_essence_descriptor_handle_tag (MXFMetadataGenericDescriptor *descriptor,
-    const MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint16 tag_size);
-void mxf_metadata_generic_sound_essence_descriptor_reset (MXFMetadataGenericSoundEssenceDescriptor *descriptor);
-
-gboolean mxf_metadata_generic_picture_essence_descriptor_handle_tag (MXFMetadataGenericDescriptor *descriptor,
-    const MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint16 tag_size);
-void mxf_metadata_generic_picture_essence_descriptor_reset (MXFMetadataGenericPictureEssenceDescriptor *descriptor);
-void mxf_metadata_generic_picture_essence_descriptor_set_caps (MXFMetadataGenericPictureEssenceDescriptor *descriptor, GstCaps *caps);
-
-gboolean mxf_metadata_cdci_picture_essence_descriptor_handle_tag (MXFMetadataGenericDescriptor *descriptor,
-    const MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint16 tag_size);
-void mxf_metadata_cdci_picture_essence_descriptor_reset (MXFMetadataCDCIPictureEssenceDescriptor *descriptor);
-
-gboolean mxf_metadata_rgba_picture_essence_descriptor_handle_tag (MXFMetadataGenericDescriptor *descriptor,
-    const MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint16 tag_size);
-void mxf_metadata_rgba_picture_essence_descriptor_reset (MXFMetadataRGBAPictureEssenceDescriptor *descriptor);
-
-gboolean mxf_metadata_generic_data_essence_descriptor_handle_tag (MXFMetadataGenericDescriptor *descriptor,
-    const MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint16 tag_size);
-void mxf_metadata_generic_data_essence_descriptor_reset (MXFMetadataGenericDataEssenceDescriptor *descriptor);
-
-gboolean mxf_metadata_multiple_descriptor_handle_tag (MXFMetadataGenericDescriptor *descriptor,
-    const MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint16 tag_size);
-void mxf_metadata_multiple_descriptor_reset (MXFMetadataMultipleDescriptor *descriptor);
-
-gboolean mxf_metadata_locator_parse (const MXFUL *key, MXFMetadataLocator *locator, const MXFPrimerPack *primer, guint16 type, const guint8 *data, guint size);
-void mxf_metadata_locator_reset (MXFMetadataLocator *locator);
-
 #endif /* __MXF_PARSE_H__ */
 
index 241efd4..d6f374d 100644 (file)
@@ -17,6 +17,8 @@
  * Boston, MA 02111-1307, USA.
  */
 
+/* Definitions of the basic MXF types, excluding structural metadata */
+
 #ifndef __MXF_TYPES_H__
 #define __MXF_TYPES_H__
 
@@ -153,408 +155,4 @@ typedef struct {
   GHashTable *other_tags;
 } MXFIndexTableSegment;
 
-/* SMPTE 377M 8.6 table 14 */
-#define MXF_METADATA_PREFACE (0x012f)
-#define MXF_METADATA_IDENTIFICATION (0x0130)
-#define MXF_METADATA_CONTENT_STORAGE (0x0118)
-#define MXF_METADATA_ESSENCE_CONTAINER_DATA (0x0123)
-#define MXF_METADATA_MATERIAL_PACKAGE (0x0136)
-#define MXF_METADATA_SOURCE_PACKAGE (0x0137)
-#define MXF_METADATA_TRACK (0x013b)
-#define MXF_METADATA_EVENT_TRACK (0x0139)
-#define MXF_METADATA_STATIC_TRACK (0x013a)
-#define MXF_METADATA_SEQUENCE (0x010f)
-#define MXF_METADATA_SOURCE_CLIP (0x0111)
-#define MXF_METADATA_TIMECODE_COMPONENT (0x0114)
-#define MXF_METADATA_DM_SEGMENT (0x0141)
-#define MXF_METADATA_DM_SOURCE_CLIP (0x0145)
-#define MXF_METADATA_FILE_DESCRIPTOR (0x0125)
-#define MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (0x0127)
-#define MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR (0x0128)
-#define MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (0x0129)
-#define MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (0x0142)
-#define MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR (0x0143)
-#define MXF_METADATA_MULTIPLE_DESCRIPTOR (0x0144)
-#define MXF_METADATA_NETWORK_LOCATOR (0x0132)
-#define MXF_METADATA_TEXT_LOCATOR (0x0133)
-
-/* SMPTE 377M Annex A, B, C, D */
-typedef struct _MXFMetadataPreface MXFMetadataPreface;
-typedef struct _MXFMetadataIdentification MXFMetadataIdentification;
-typedef struct _MXFMetadataContentStorage MXFMetadataContentStorage;
-typedef struct _MXFMetadataEssenceContainerData MXFMetadataEssenceContainerData;
-typedef struct _MXFMetadataGenericPackage MXFMetadataGenericPackage;
-typedef MXFMetadataGenericPackage MXFMetadataMaterialPackage;
-typedef MXFMetadataGenericPackage MXFMetadataSourcePackage;
-typedef struct _MXFMetadataTrack MXFMetadataTrack;
-typedef struct _MXFMetadataSequence MXFMetadataSequence;
-typedef struct _MXFMetadataStructuralComponent MXFMetadataStructuralComponent;
-typedef struct _MXFMetadataGenericDescriptor MXFMetadataGenericDescriptor;
-typedef struct _MXFMetadataFileDescriptor MXFMetadataFileDescriptor;
-typedef struct _MXFMetadataGenericPictureEssenceDescriptor MXFMetadataGenericPictureEssenceDescriptor;
-typedef struct _MXFMetadataCDCIPictureEssenceDescriptor MXFMetadataCDCIPictureEssenceDescriptor;
-typedef struct _MXFMetadataRGBAPictureEssenceDescriptor MXFMetadataRGBAPictureEssenceDescriptor;
-typedef struct _MXFMetadataGenericSoundEssenceDescriptor MXFMetadataGenericSoundEssenceDescriptor;
-typedef struct _MXFMetadataGenericDataEssenceDescriptor MXFMetadataGenericDataEssenceDescriptor;
-typedef struct _MXFMetadataMultipleDescriptor MXFMetadataMultipleDescriptor;
-typedef struct _MXFMetadataLocator MXFMetadataLocator;
-
-struct _MXFMetadataPreface {
-  MXFUL instance_uid;
-  MXFUL generation_uid;
-
-  MXFTimestamp last_modified_date;
-  guint16 version;
-
-  guint32 object_model_version;
-
-  MXFUL primary_package_uid;
-  MXFMetadataGenericPackage *primary_package;
-
-  guint32 n_identifications;
-  MXFUL *identifications_uids;
-  MXFMetadataIdentification **identifications;
-
-  MXFUL content_storage_uid;
-  MXFMetadataContentStorage *content_storage;
-
-  MXFUL operational_pattern;
-
-  guint32 n_essence_containers;
-  MXFUL *essence_containers;
-
-  guint32 n_dm_schemes;
-  MXFUL *dm_schemes;
-
-  GHashTable *other_tags;
-};
-
-struct _MXFMetadataIdentification {
-  MXFUL instance_uid;
-  MXFUL generation_uid;
-
-  gchar *company_name;
-
-  gchar *product_name;
-  MXFProductVersion product_version;
-  
-  gchar *version_string;
-
-  MXFUL product_uid;
-
-  MXFTimestamp modification_date;
-
-  MXFProductVersion toolkit_version;
-
-  gchar *platform;
-
-  GHashTable *other_tags;
-};
-
-struct _MXFMetadataContentStorage {
-  MXFUL instance_uid;
-  MXFUL generation_uid;
-
-  guint32 n_packages;
-  MXFUL *packages_uids;
-  MXFMetadataGenericPackage **packages;
-
-  guint32 n_essence_container_data;
-  MXFUL *essence_container_data_uids;
-  MXFMetadataEssenceContainerData **essence_container_data;
-
-  GHashTable *other_tags;
-};
-
-struct _MXFMetadataEssenceContainerData {
-  MXFUL instance_uid;
-
-  MXFUMID linked_package_uid;
-  MXFMetadataGenericPackage *linked_package;
-
-  MXFUL generation_uid;
-
-  guint32 index_sid;
-  guint32 body_sid;
-
-  GHashTable *other_tags;
-};
-
-typedef enum {
-  MXF_METADATA_GENERIC_PACKAGE_SOURCE = 0,
-  MXF_METADATA_GENERIC_PACKAGE_MATERIAL = 1,
-  MXF_METADATA_GENERIC_PACKAGE_TOP_LEVEL_SOURCE = 2
-} MXFMetadataGenericPackageType;
-
-struct _MXFMetadataGenericPackage {
-  MXFUL instance_uid;
-  MXFUMID package_uid;
-  MXFUL generation_uid;
-
-  MXFMetadataGenericPackageType type;
-
-  gchar *name;
-  MXFTimestamp package_creation_date;
-  MXFTimestamp package_modified_date;
-
-  guint32 n_tracks;
-  MXFUL *tracks_uids;
-  MXFMetadataTrack **tracks;
-
-  guint n_timecode_tracks;
-  guint n_metadata_tracks;
-  guint n_essence_tracks;
-  guint n_other_tracks;
-
-  /* Only in Source packages */
-  MXFUL descriptors_uid;
-  guint32 n_descriptors;
-  MXFMetadataGenericDescriptor **descriptors;
-  
-  GHashTable *other_tags;
-};
-
-typedef enum {
-  MXF_METADATA_TRACK_UNKNOWN               = 0x00,
-  MXF_METADATA_TRACK_TIMECODE_12M_INACTIVE = 0x10,
-  MXF_METADATA_TRACK_TIMECODE_12M_ACTIVE   = 0x11,
-  MXF_METADATA_TRACK_TIMECODE_309M         = 0x12,
-  MXF_METADATA_TRACK_METADATA              = 0x20,
-  MXF_METADATA_TRACK_PICTURE_ESSENCE       = 0x30,
-  MXF_METADATA_TRACK_SOUND_ESSENCE         = 0x31,
-  MXF_METADATA_TRACK_DATA_ESSENCE          = 0x32,
-  MXF_METADATA_TRACK_AUXILIARY_DATA        = 0x40,
-  MXF_METADATA_TRACK_PARSED_TEXT           = 0x41
-} MXFMetadataTrackType;
-
-typedef enum {
-  MXF_METADATA_TRACK_VARIANT_TIMELINE,
-  MXF_METADATA_TRACK_VARIANT_EVENT,
-  MXF_METADATA_TRACK_VARIANT_STATIC
-} MXFMetadataTrackVariant;
-
-struct _MXFMetadataTrack {
-  MXFUL instance_uid;
-  MXFUL generation_uid;
-
-  guint32 track_id;
-  guint32 track_number;
-
-  MXFMetadataTrackType type;
-  MXFMetadataTrackVariant variant;
-
-  gchar *track_name;
-
-  MXFFraction edit_rate;
-
-  gint64 origin;
-
-  MXFUL sequence_uid;
-  MXFMetadataSequence *sequence;
-
-  MXFMetadataFileDescriptor **descriptor;
-  guint n_descriptor;
-  
-  GHashTable *other_tags;
-};
-
-struct _MXFMetadataSequence {
-  MXFUL instance_uid;
-  MXFUL generation_uid;
-
-  MXFUL data_definition;
-
-  gint64 duration;
-
-  guint32 n_structural_components;
-  MXFUL *structural_components_uids;
-  MXFMetadataStructuralComponent **structural_components;
-  
-  GHashTable *other_tags;
-};
-
-struct _MXFMetadataStructuralComponent {
-  guint16 type;
-
-  MXFUL instance_uid;
-  MXFUL generation_uid;
-
-  MXFUL data_definition;
-
-  gint64 duration;
-
-  union {
-    struct {
-      gint64 start_timecode;
-      guint16 rounded_timecode_base;
-      gboolean drop_frame;
-    } timecode_component;
-
-    struct {
-      gint64 start_position;
-      MXFUMID source_package_id;
-      MXFMetadataGenericPackage *source_package;
-
-      guint32 source_track_id;
-    } source_clip;
-
-    struct {
-      gint64 event_start_position;
-      gchar *event_comment;
-
-      guint32 n_track_ids;
-      guint32 *track_ids;
-      
-      MXFUL dm_framework;
-    } dm_segment;
-
-    struct {
-      gint64 start_position;
-      MXFUMID source_package_id;
-      MXFMetadataGenericPackage *source_package;
-
-      guint32 source_track_id;
-
-      guint32 n_track_ids;
-      guint32 *track_ids;
-    } dm_source_clip;
-  };
-
-  GHashTable *other_tags;
-};
-
-struct _MXFMetadataGenericDescriptor {
-  guint16 type;
-
-  MXFUL instance_uid;
-  MXFUL generation_uid;
-
-  guint32 n_locators;
-  MXFUL *locators_uids;
-  MXFMetadataLocator **locators;
-
-  gboolean is_file_descriptor;
-
-  GHashTable *other_tags;
-};
-
-struct _MXFMetadataFileDescriptor {
-  MXFMetadataGenericDescriptor parent;
-
-  guint32 linked_track_id;
-
-  MXFFraction sample_rate;
-  gint64 container_duration;
-  MXFUL essence_container;
-  MXFUL codec;
-};
-
-struct _MXFMetadataGenericPictureEssenceDescriptor {
-  MXFMetadataFileDescriptor parent;
-
-  guint8 signal_standard;
-  guint8 frame_layout;
-
-  guint32 stored_width;
-  guint32 stored_height;
-  gint32 stored_f2_offset;
-  guint32 sampled_width;
-  guint32 sampled_height;
-  gint32 sampled_x_offset;
-  gint32 sampled_y_offset;
-  guint32 display_height;
-  guint32 display_width;
-  gint32 display_x_offset;
-  gint32 display_y_offset;
-  gint32 display_f2_offset;
-  MXFFraction aspect_ratio;
-
-  guint8 active_format_descriptor;
-  gint32 video_line_map[2];
-  guint8 alpha_transparency;
-  MXFUL capture_gamma;
-
-  guint32 image_alignment_offset;
-  guint32 image_start_offset;
-  guint32 image_end_offset;
-
-  guint8 field_dominance;
-
-  MXFUL picture_essence_coding;
-};
-
-struct _MXFMetadataCDCIPictureEssenceDescriptor {
-  MXFMetadataGenericPictureEssenceDescriptor parent;
-
-  guint32 component_depth;
-  guint32 horizontal_subsampling;
-  guint32 vertical_subsampling;
-  guint8 color_siting;
-  gboolean reversed_byte_order;
-  gint16 padding_bits;
-  guint32 alpha_sample_depth;
-  guint32 black_ref_level;
-  guint32 white_ref_level;
-  guint32 color_range;
-};
-
-struct _MXFMetadataRGBAPictureEssenceDescriptor {
-  MXFMetadataGenericPictureEssenceDescriptor parent;
-
-  guint32 component_max_ref;
-  guint32 component_min_ref;
-  guint32 alpha_max_ref;
-  guint32 alpha_min_ref;
-  guint8 scanning_direction;
-
-  guint32 n_pixel_layout;
-  guint8 *pixel_layout;
-
-  /* TODO: palette & palette layout */
-};
-
-struct _MXFMetadataGenericSoundEssenceDescriptor {
-  MXFMetadataFileDescriptor parent;
-
-  MXFFraction audio_sampling_rate;
-
-  gboolean locked;
-
-  gint8 audio_ref_level;
-
-  guint8 electro_spatial_formulation;
-
-  guint32 channel_count;
-  guint32 quantization_bits;
-
-  gint8 dial_norm;
-
-  MXFUL sound_essence_compression;
-};
-
-struct _MXFMetadataGenericDataEssenceDescriptor {
-  MXFMetadataFileDescriptor parent;
-
-  MXFUL data_essence_compression;
-};
-
-struct _MXFMetadataMultipleDescriptor {
-  MXFMetadataFileDescriptor parent;
-  
-  MXFUL *sub_descriptors_uids;
-  guint32 n_sub_descriptors;
-  MXFMetadataGenericDescriptor **sub_descriptors;
-};
-
-struct _MXFMetadataLocator {
-  guint16 type;
-
-  MXFUL instance_uid;
-  MXFUL generation_uid;
-
-  gchar *location;
-
-  GHashTable *other_tags;
-};
-
 #endif /* __MXF_TYPES_H__ */
index 3b5259e..3827042 100644 (file)
@@ -61,7 +61,12 @@ mxf_is_up_essence_track (const MXFMetadataTrack * track)
 
   for (i = 0; i < track->n_descriptor; i++) {
     MXFMetadataFileDescriptor *d = track->descriptor[i];
-    MXFUL *key = &d->essence_container;
+    MXFUL *key;
+
+    if (!d)
+      continue;
+
+    key = &d->essence_container;
     /* SMPTE 384M 8 */
     if (mxf_is_generic_container_essence_container_label (key) &&
         key->u[12] == 0x02 && key->u[13] == 0x05 && key->u[15] <= 0x03)
@@ -216,13 +221,15 @@ mxf_up_create_caps (MXFMetadataGenericPackage * package,
   }
 
   for (i = 0; i < track->n_descriptor; i++) {
-    if (((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR) {
+    if (!track->descriptor[i])
+      continue;
+
+    if (MXF_IS_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (track->descriptor[i])) {
       p = (MXFMetadataGenericPictureEssenceDescriptor *) track->descriptor[i];
       r = (MXFMetadataRGBAPictureEssenceDescriptor *) track->descriptor[i];
       break;
-    } else if (((MXFMetadataGenericDescriptor *) track->descriptor[i])->type ==
-        MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR) {
+    } else if (MXF_IS_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR (track->
+            descriptor[i])) {
       p = (MXFMetadataGenericPictureEssenceDescriptor *) track->descriptor[i];
       c = (MXFMetadataCDCIPictureEssenceDescriptor *) track->descriptor[i];
     }
@@ -250,3 +257,8 @@ mxf_up_create_caps (MXFMetadataGenericPackage * package,
 
   return caps;
 }
+
+void
+mxf_up_init (void)
+{
+}
index 66fc849..b575811 100644 (file)
@@ -33,4 +33,6 @@ gboolean mxf_is_up_essence_track (const MXFMetadataTrack *track);
 GstCaps *
 mxf_up_create_caps (MXFMetadataGenericPackage *package, MXFMetadataTrack *track, GstTagList **tags, MXFEssenceElementHandler *handler, gpointer *mapping_data);
 
+void mxf_up_init (void);
+
 #endif /* __MXF_UP_H__ */