summaryrefslogtreecommitdiffstats
path: root/gst/mxf/mxfparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/mxf/mxfparse.c')
-rw-r--r--gst/mxf/mxfparse.c2692
1 files changed, 2692 insertions, 0 deletions
diff --git a/gst/mxf/mxfparse.c b/gst/mxf/mxfparse.c
new file mode 100644
index 00000000..49f5d685
--- /dev/null
+++ b/gst/mxf/mxfparse.c
@@ -0,0 +1,2692 @@
+/* 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"
+
+GST_DEBUG_CATEGORY_EXTERN (mxf_debug);
+#define GST_CAT_DEFAULT mxf_debug
+
+/* SMPTE 377M 3.3: A value of 0 for every field means unknown timestamp */
+static const MXFTimestamp mxf_timestamp_unknown = { 0, 0, 0, 0, 0, 0, 0 };
+
+/* FIXME: are zero UMID/UL invalid? Should be in SMPTE 298M, 330M or 336M */
+static const MXFUMID umid_zero = { {0,} };
+static const MXFUL key_zero = { {0,} };
+
+/* UL common to all MXF UL */
+static const guint8 mxf_key[] = { 0x06, 0x0e, 0x2b, 0x34 };
+
+/* SMPTE 377M 6.1 */
+static const guint8 partition_pack_key[] =
+ { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01,
+ 0x01
+};
+
+/* SMPTE 336M */
+static const guint8 fill_key[] =
+ { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x02, 0x10,
+ 0x01, 0x00, 0x00, 0x00
+};
+
+/* SMPTE 377M 8.1 */
+static const guint8 primer_pack_key[] =
+ { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01,
+ 0x01, 0x05, 0x01, 0x00
+};
+
+/* SMPTE 377M 8.6 */
+static const guint8 metadata_key[] =
+ { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01,
+ 0x01
+};
+
+static const guint8 random_index_pack_key[] =
+ { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01,
+ 0x01, 0x11, 0x01, 0x00
+};
+
+static const guint8 index_table_segment_key[] =
+ { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01,
+ 0x01, 0x10, 0x01, 0x00
+};
+
+gboolean
+mxf_is_mxf_packet (const MXFUL * key)
+{
+ return (memcmp (key, mxf_key, 4) == 0);
+}
+
+/* SMPTE 377M 6.1: Check if this is a valid partition pack */
+gboolean
+mxf_is_partition_pack (const MXFUL * key)
+{
+ if (memcmp (key, partition_pack_key, 13) == 0 && key->u[13] >= 0x02
+ && key->u[13] <= 0x04 && key->u[14] < 0x05 && key->u[15] == 0x00)
+ return TRUE;
+
+ return FALSE;
+}
+
+/* SMPTE 377M 6.2: header partition pack has byte 14 == 0x02 */
+gboolean
+mxf_is_header_partition_pack (const MXFUL * key)
+{
+ if (memcmp (key, partition_pack_key, 13) == 0 && key->u[13] == 0x02 &&
+ key->u[14] < 0x05 && key->u[15] == 0x00)
+ return TRUE;
+
+ return FALSE;
+}
+
+/* SMPTE 377M 6.3: body partition pack has byte 14 == 0x03 */
+gboolean
+mxf_is_body_partition_pack (const MXFUL * key)
+{
+ if (memcmp (key, partition_pack_key, 13) == 0 && key->u[13] == 0x03 &&
+ key->u[14] < 0x05 && key->u[15] == 0x00)
+ return TRUE;
+
+ return FALSE;
+}
+
+/* SMPTE 377M 6.4: footer partition pack has byte 14 == 0x04 */
+gboolean
+mxf_is_footer_partition_pack (const MXFUL * key)
+{
+ if (memcmp (key, partition_pack_key, 13) == 0 && key->u[13] == 0x04 &&
+ key->u[14] < 0x05 && key->u[15] == 0x00)
+ return TRUE;
+
+ return FALSE;
+}
+
+gboolean
+mxf_is_fill (const MXFUL * key)
+{
+ return (memcmp (key, fill_key, 16) == 0);
+}
+
+gboolean
+mxf_is_primer_pack (const MXFUL * key)
+{
+ return (memcmp (key, primer_pack_key, 16) == 0);
+}
+
+gboolean
+mxf_is_metadata (const MXFUL * key)
+{
+ return (memcmp (key, metadata_key, 13) == 0 && key->u[15] == 0x00);
+}
+
+gboolean
+mxf_is_random_index_pack (const MXFUL * key)
+{
+ return (memcmp (key, random_index_pack_key, 16) == 0);
+}
+
+gboolean
+mxf_is_index_table_segment (const MXFUL * key)
+{
+ return (memcmp (key, index_table_segment_key, 16) == 0);
+}
+
+/* SMPTE 379M 6.2.1 */
+gboolean
+mxf_is_generic_container_system_item (const MXFUL * key)
+{
+ return (memcmp (key, mxf_key, 4) == 0 && key->u[4] == 0x02
+ && key->u[6] == 0x01 && key->u[8] == 0x0d && key->u[9] == 0x01
+ && key->u[10] == 0x03 && key->u[11] == 0x01 && (key->u[12] == 0x04
+ || key->u[12] == 0x14));
+}
+
+/* SMPTE 379M 7.1 */
+gboolean
+mxf_is_generic_container_essence_element (const MXFUL * key)
+{
+ return (memcmp (key, mxf_key, 4) == 0 && key->u[4] == 0x01
+ && key->u[5] == 0x02 && key->u[6] == 0x01 && key->u[8] == 0x0d
+ && key->u[9] == 0x01 && key->u[10] == 0x03 && key->u[11] == 0x01
+ && (key->u[12] == 0x05 || key->u[12] == 0x06 || key->u[12] == 0x07
+ || key->u[12] == 0x15 || key->u[12] == 0x16 || key->u[12] == 0x17
+ || key->u[12] == 0x18));
+}
+
+/* SMPTE 379M 8 */
+gboolean
+mxf_is_generic_container_essence_container_label (const MXFUL * key)
+{
+ return (key->u[0] == 0x06 &&
+ key->u[1] == 0x0e &&
+ key->u[2] == 0x2b &&
+ key->u[3] == 0x34 &&
+ key->u[4] == 0x04 &&
+ key->u[5] == 0x01 &&
+ key->u[6] == 0x01 &&
+ key->u[8] == 0x0d &&
+ key->u[9] == 0x01 &&
+ key->u[10] == 0x03 &&
+ key->u[11] == 0x01 && (key->u[12] == 0x01 || key->u[12] == 0x02));
+}
+
+gboolean
+mxf_ul_is_equal (const MXFUL * a, const MXFUL * b)
+{
+ return (memcmp (a, b, 16) == 0);
+}
+
+gboolean
+mxf_ul_is_zero (const MXFUL * key)
+{
+ return (memcmp (key, &key_zero, 16) == 0);
+}
+
+gchar *
+mxf_ul_to_string (const MXFUL * key, gchar str[48])
+{
+ g_return_val_if_fail (key != NULL, NULL);
+ g_return_val_if_fail (str != NULL, NULL);
+
+ g_snprintf (str, 48,
+ "%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x",
+ key->u[0], key->u[1], key->u[2], key->u[3], key->u[4], key->u[5],
+ key->u[6], key->u[7], key->u[8], key->u[9], key->u[10], key->u[11],
+ key->u[12], key->u[13], key->u[14], key->u[15]);
+
+ return str;
+}
+
+gboolean
+mxf_umid_is_equal (const MXFUMID * a, const MXFUMID * b)
+{
+ return (memcmp (a, b, 32) == 0);
+}
+
+gboolean
+mxf_umid_is_zero (const MXFUMID * umid)
+{
+ return (memcmp (umid, &umid_zero, 32) == 0);
+}
+
+gchar *
+mxf_umid_to_string (const MXFUMID * key, gchar str[96])
+{
+ g_return_val_if_fail (key != NULL, NULL);
+ g_return_val_if_fail (str != NULL, NULL);
+
+ g_snprintf (str, 96,
+ "%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x."
+ "%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x",
+ key->u[0], key->u[1], key->u[2], key->u[3], key->u[4], key->u[5],
+ key->u[6], key->u[7], key->u[8], key->u[9], key->u[10], key->u[11],
+ key->u[12], key->u[13], key->u[14], key->u[15],
+ key->u[16],
+ key->u[17],
+ key->u[18],
+ key->u[19],
+ key->u[20],
+ key->u[21],
+ key->u[22],
+ key->u[23],
+ key->u[24],
+ key->u[25],
+ key->u[26], key->u[27], key->u[28], key->u[29], key->u[30], key->u[31]
+ );
+
+ return str;
+}
+
+
+static guint
+gst_mxf_ul_hash (const MXFUL * key)
+{
+ guint32 ret = 0;
+ gint i;
+
+ for (i = 0; i < 4; i++)
+ ret ^=
+ (key->u[i * 4 + 0] << 24) | (key->u[i * 4 + 1] << 16) | (key->u[i * 4 +
+ 2] << 8) | (key->u[i * 4 + 3] << 0);
+
+ return ret;
+}
+
+static gboolean
+gst_mxf_ul_equal (const MXFUL * a, const MXFUL * b)
+{
+ return (memcmp (a, b, 16) == 0);
+}
+
+gboolean
+mxf_timestamp_parse (MXFTimestamp * timestamp, const guint8 * data, gsize size)
+{
+ g_return_val_if_fail (data != NULL, FALSE);
+ g_return_val_if_fail (timestamp != NULL, FALSE);
+
+ memset (timestamp, 0, sizeof (MXFTimestamp));
+
+ if (size < 8)
+ return FALSE;
+
+ timestamp->year = GST_READ_UINT16_BE (data);
+ timestamp->month = GST_READ_UINT8 (data + 2);
+ timestamp->day = GST_READ_UINT8 (data + 3);
+ timestamp->hour = GST_READ_UINT8 (data + 4);
+ timestamp->minute = GST_READ_UINT8 (data + 5);
+ timestamp->second = GST_READ_UINT8 (data + 6);
+ timestamp->quarter_msecond = GST_READ_UINT8 (data + 7);
+
+ return TRUE;
+}
+
+gboolean
+mxf_timestamp_is_unknown (const MXFTimestamp * a)
+{
+ return (memcmp (a, &mxf_timestamp_unknown, sizeof (MXFTimestamp)) == 0);
+}
+
+gint
+mxf_timestamp_compare (const MXFTimestamp * a, const MXFTimestamp * b)
+{
+ gint diff;
+
+ if ((diff = a->year - b->year) != 0)
+ return diff;
+ else if ((diff = a->month - b->month) != 0)
+ return diff;
+ else if ((diff = a->day - b->day) != 0)
+ return diff;
+ else if ((diff = a->hour - b->hour) != 0)
+ return diff;
+ else if ((diff = a->minute - b->minute) != 0)
+ return diff;
+ else if ((diff = a->second - b->second) != 0)
+ return diff;
+ else if ((diff = a->quarter_msecond - b->quarter_msecond) != 0)
+ return diff;
+ else
+ return 0;
+}
+
+gboolean
+mxf_fraction_parse (MXFFraction * fraction, const guint8 * data, guint16 size)
+{
+ g_return_val_if_fail (fraction != NULL, FALSE);
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ memset (fraction, 0, sizeof (MXFFraction));
+
+ if (size < 8)
+ return FALSE;
+
+ fraction->n = GST_READ_UINT32_BE (data);
+ fraction->d = GST_READ_UINT32_BE (data + 4);
+
+ return TRUE;
+}
+
+gchar *
+mxf_utf16_to_utf8 (const guint8 * data, guint16 size)
+{
+ gchar *ret;
+ GError *error = NULL;
+
+ ret =
+ g_convert ((const gchar *) data, size, "UTF-8", "UTF-16BE", NULL, NULL,
+ &error);
+
+ if (ret == NULL) {
+ GST_WARNING ("UTF-16-BE to UTF-8 conversion failed: %s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ return ret;
+}
+
+gboolean
+mxf_product_version_parse (MXFProductVersion * product_version,
+ const guint8 * data, gsize size)
+{
+ g_return_val_if_fail (product_version != NULL, FALSE);
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ memset (product_version, 0, sizeof (MXFProductVersion));
+
+ if (size < 10)
+ return FALSE;
+
+ product_version->major = GST_READ_UINT16_BE (data);
+ product_version->minor = GST_READ_UINT16_BE (data + 2);
+ product_version->patch = GST_READ_UINT16_BE (data + 4);
+ product_version->build = GST_READ_UINT16_BE (data + 6);
+ product_version->release = GST_READ_UINT16_BE (data + 8);
+
+ return TRUE;
+}
+
+/* SMPTE 377M 6.1, Table 2 */
+gboolean
+mxf_partition_pack_parse (const MXFUL * key, MXFPartitionPack * pack,
+ const guint8 * data, gsize size)
+{
+ gint i;
+ gchar str[48];
+
+ g_return_val_if_fail (data != NULL, FALSE);
+ g_return_val_if_fail (size >= 84, FALSE);
+
+ memset (pack, 0, sizeof (MXFPartitionPack));
+
+ if (key->u[13] == 0x02)
+ pack->type = MXF_PARTITION_PACK_HEADER;
+ else if (key->u[13] == 0x03)
+ pack->type = MXF_PARTITION_PACK_BODY;
+ else if (key->u[13] == 0x04)
+ pack->type = MXF_PARTITION_PACK_FOOTER;
+
+ pack->closed = (key->u[14] == 0x02 || key->u[14] == 0x04);
+ pack->complete = (key->u[14] == 0x03 || key->u[14] == 0x04);
+
+ pack->major_version = GST_READ_UINT16_BE (data);
+ if (pack->major_version != 1)
+ goto error;
+ data += 2;
+ size -= 2;
+
+ pack->minor_version = GST_READ_UINT16_BE (data);
+ data += 2;
+ size -= 2;
+
+ pack->kag_size = GST_READ_UINT32_BE (data);
+ data += 4;
+ size -= 4;
+
+ pack->this_partition = GST_READ_UINT64_BE (data);
+ data += 8;
+ size -= 8;
+
+ pack->prev_partition = GST_READ_UINT64_BE (data);
+ data += 8;
+ size -= 8;
+
+ pack->footer_partition = GST_READ_UINT64_BE (data);
+ data += 8;
+ size -= 8;
+
+ pack->header_byte_count = GST_READ_UINT64_BE (data);
+ data += 8;
+ size -= 8;
+
+ pack->index_byte_count = GST_READ_UINT64_BE (data);
+ data += 8;
+ size -= 8;
+
+ pack->index_sid = GST_READ_UINT32_BE (data);
+ data += 4;
+ size -= 4;
+
+ pack->body_offset = GST_READ_UINT64_BE (data);
+ data += 8;
+ size -= 8;
+
+ pack->body_sid = GST_READ_UINT32_BE (data);
+ data += 4;
+ size -= 4;
+
+ memcpy (&pack->operational_pattern, data, 16);
+ data += 16;
+ size -= 16;
+
+ pack->n_essence_containers = GST_READ_UINT32_BE (data);
+ data += 4;
+ size -= 4;
+
+ if (GST_READ_UINT32_BE (data) != 16)
+ goto error;
+ data += 4;
+ size -= 4;
+
+ if (size < 16 * pack->n_essence_containers)
+ goto error;
+
+ if (pack->n_essence_containers) {
+ pack->essence_containers = g_new (MXFUL, pack->n_essence_containers);
+ for (i = 0; i < pack->n_essence_containers; i++)
+ memcpy (&pack->essence_containers[i], data + i * 16, 16);
+ }
+
+ pack->valid = TRUE;
+ GST_DEBUG ("Parsed partition pack: \n"
+ " type = %s, closed = %s, complete = %s\n"
+ " MXF version = %u.%u\n"
+ " KAG size = %u\n"
+ " this partition offset = %" G_GUINT64_FORMAT "\n"
+ " previous partition offset = %" G_GUINT64_FORMAT "\n"
+ " footer partition offset = %" G_GUINT64_FORMAT "\n"
+ " header size = %" G_GUINT64_FORMAT "\n"
+ " index sid = %u, size %" G_GUINT64_FORMAT "\n"
+ " body sid = %u, offset %" G_GUINT64_FORMAT "\n"
+ " operational pattern = %s\n"
+ " number of essence containers = %u",
+ (pack->type == MXF_PARTITION_PACK_HEADER) ? "header" : (pack->type ==
+ MXF_PARTITION_PACK_BODY) ? "body" : "footer",
+ (pack->closed) ? "yes" : "no", (pack->complete) ? "yes" : "no",
+ pack->major_version, pack->minor_version, pack->kag_size,
+ pack->this_partition, pack->prev_partition, pack->footer_partition,
+ pack->header_byte_count, pack->index_sid, pack->index_byte_count,
+ pack->body_sid, pack->body_offset,
+ mxf_ul_to_string (&pack->operational_pattern, str),
+ pack->n_essence_containers);
+
+ for (i = 0; i < pack->n_essence_containers; i++) {
+ GST_DEBUG (" essence container %d = %s", i,
+ mxf_ul_to_string (&pack->essence_containers[i], str));
+ }
+
+ return TRUE;
+
+error:
+ GST_ERROR ("Invalid partition pack");
+
+ mxf_partition_pack_reset (pack);
+ return FALSE;
+}
+
+void
+mxf_partition_pack_reset (MXFPartitionPack * pack)
+{
+ g_return_if_fail (pack != NULL);
+
+ g_free (pack->essence_containers);
+
+ memset (pack, 0, sizeof (MXFPartitionPack));
+}
+
+/* SMPTE 377M 8.2 Table 1 and 2 */
+
+static void
+_mxf_mapping_ul_free (MXFUL * ul)
+{
+ g_slice_free (MXFUL, ul);
+}
+
+gboolean
+mxf_primer_pack_parse (const MXFUL * key, MXFPrimerPack * pack,
+ const guint8 * data, gsize size)
+{
+ gint i;
+ guint32 n;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+ g_return_val_if_fail (size >= 8, FALSE);
+
+ memset (pack, 0, sizeof (MXFPrimerPack));
+
+ pack->mappings =
+ g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ (GDestroyNotify) NULL, (GDestroyNotify) _mxf_mapping_ul_free);
+
+ n = GST_READ_UINT32_BE (data);
+ data += 4;
+
+ if (GST_READ_UINT32_BE (data) != 18)
+ goto error;
+ data += 4;
+
+ if (size < 8 + n * 18)
+ goto error;
+
+ GST_DEBUG ("Parsed primer pack:");
+ for (i = 0; i < n; i++) {
+ guint local_tag;
+ gchar str[48];
+ MXFUL *uid;
+
+ local_tag = GST_READ_UINT16_BE (data);
+ data += 2;
+
+ if (g_hash_table_lookup (pack->mappings, GUINT_TO_POINTER (local_tag)))
+ continue;
+
+ uid = g_slice_new (MXFUL);
+ memcpy (uid, data, 16);
+ data += 16;
+
+ g_hash_table_insert (pack->mappings, GUINT_TO_POINTER (local_tag), uid);
+ GST_DEBUG (" Adding primer pack association: 0x%04x -> %s", local_tag,
+ mxf_ul_to_string (uid, str));
+ }
+
+ pack->valid = TRUE;
+
+ return TRUE;
+
+error:
+ GST_DEBUG ("Invalid primer pack");
+ mxf_primer_pack_reset (pack);
+ return FALSE;
+}
+
+void
+mxf_primer_pack_reset (MXFPrimerPack * pack)
+{
+ g_return_if_fail (pack != NULL);
+
+ if (pack->mappings)
+ g_hash_table_destroy (pack->mappings);
+ memset (pack, 0, sizeof (MXFPrimerPack));
+}
+
+/* structural metadata parsing */
+
+gboolean
+mxf_local_tag_parse (const guint8 * data, gsize size, guint16 * tag,
+ guint16 * tag_size, const guint8 ** tag_data)
+{
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ if (size < 4)
+ return FALSE;
+
+ *tag = GST_READ_UINT16_BE (data);
+ *tag_size = GST_READ_UINT16_BE (data + 2);
+
+ if (size < 4 + *tag_size)
+ return FALSE;
+
+ *tag_data = data + 4;
+
+ return TRUE;
+}
+
+void
+gst_mxf_local_tag_free (MXFLocalTag * tag)
+{
+ g_free (tag->data);
+ g_slice_free (MXFLocalTag, tag);
+}
+
+gboolean
+gst_metadata_add_custom_tag (const MXFPrimerPack * primer,
+ guint16 tag, const guint8 * tag_data, guint16 tag_size,
+ GHashTable ** hash_table)
+{
+ MXFLocalTag *local_tag;
+ MXFUL *key;
+
+ g_return_val_if_fail (primer != NULL, FALSE);
+ g_return_val_if_fail (tag_data != NULL, FALSE);
+ g_return_val_if_fail (hash_table != NULL, FALSE);
+ g_return_val_if_fail (primer->mappings != NULL, FALSE);
+
+ if (*hash_table == NULL)
+ *hash_table =
+ g_hash_table_new_full ((GHashFunc) gst_mxf_ul_hash,
+ (GEqualFunc) gst_mxf_ul_equal, (GDestroyNotify) NULL,
+ (GDestroyNotify) gst_mxf_local_tag_free);
+
+ g_return_val_if_fail (*hash_table != NULL, FALSE);
+
+ key = (MXFUL *) g_hash_table_lookup (primer->mappings,
+ GUINT_TO_POINTER (((guint) tag)));
+
+ if (key) {
+ gchar str[48];
+
+ GST_DEBUG ("Adding local tag 0x%04x with UL %s and size %u", tag,
+ mxf_ul_to_string (key, str), tag_size);
+
+ local_tag = g_slice_new (MXFLocalTag);
+ memcpy (&local_tag->key, key, sizeof (MXFUL));
+ local_tag->size = tag_size;
+ local_tag->data = g_memdup (tag_data, tag_size);
+
+ g_hash_table_insert (*hash_table, &local_tag->key, local_tag);
+ } else {
+ GST_WARNING ("Local tag with no entry in primer pack: 0x%04x", tag);
+ }
+
+ 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, gsize size)
+{
+ guint16 tag, tag_size;
+ const guint8 *tag_data;
+ gchar str[48];
+ gint i;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ memset (preface, 0, sizeof (MXFMetadataPreface));
+
+ while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+ if (tag_size == 0 || tag == 0x0000)
+ goto next;
+
+ switch (tag) {
+ case 0x3c0a:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&preface->instance_uid, tag_data, 16);
+ break;
+ case 0x0102:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&preface->generation_uid, tag_data, 16);
+ break;
+ case 0x3b02:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (!mxf_timestamp_parse (&preface->last_modified_date, tag_data,
+ tag_size))
+ goto error;
+ break;
+ case 0x3b05:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 2)
+ goto error;
+ preface->version = GST_READ_UINT16_BE (tag_data);
+ break;
+ case 0x3b07:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ preface->object_model_version = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3b08:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&preface->primary_package_uid, tag_data, 16);
+ break;
+ case 0x3b06:{
+ guint32 len;
+ guint i;
+
+ GST_WRITE_UINT16_BE (data, 0x0000);
+
+ if (tag_size < 8)
+ goto error;
+ len = GST_READ_UINT32_BE (tag_data);
+ 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);
+ break;
+ }
+ case 0x3b03:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&preface->content_storage_uid, tag_data, 16);
+ break;
+ case 0x3b09:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&preface->operational_pattern, tag_data, 16);
+ break;
+ case 0x3b0a:{
+ guint32 len;
+ guint i;
+
+ GST_WRITE_UINT16_BE (data, 0x0000);
+
+ if (tag_size < 8)
+ goto error;
+ len = GST_READ_UINT32_BE (tag_data);
+ 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);
+ break;
+ }
+ case 0x3b0b:{
+ guint32 len;
+ guint i;
+
+ GST_WRITE_UINT16_BE (data, 0x0000);
+
+ if (tag_size < 8)
+ goto error;
+ len = GST_READ_UINT32_BE (tag_data);
+ 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);
+ break;
+ }
+ default:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ 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;
+ }
+
+ GST_DEBUG ("Parsed preface:");
+ GST_DEBUG (" instance uid = %s", mxf_ul_to_string (&preface->instance_uid,
+ str));
+ GST_DEBUG (" generation uid = %s",
+ mxf_ul_to_string (&preface->generation_uid, str));
+ 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);
+ GST_DEBUG (" version = %u.%u", (preface->version >> 8),
+ (preface->version & 0x0f));
+ GST_DEBUG (" object model version = %u", preface->object_model_version);
+ GST_DEBUG (" primary package = %s",
+ mxf_ul_to_string (&preface->primary_package_uid, str));
+ GST_DEBUG (" content storage = %s",
+ mxf_ul_to_string (&preface->content_storage_uid, str));
+ GST_DEBUG (" operational pattern = %s",
+ mxf_ul_to_string (&preface->operational_pattern, str));
+ GST_DEBUG (" number of identifications = %u", preface->n_identifications);
+ GST_DEBUG (" number of essence containers = %u",
+ preface->n_essence_containers);
+ GST_DEBUG (" number of DM schemes = %u", preface->n_dm_schemes);
+
+ for (i = 0; i < preface->n_identifications; i++)
+ GST_DEBUG (" identification %d = %s", i,
+ mxf_ul_to_string (&preface->identifications_uids[i], str));
+
+ for (i = 0; i < preface->n_essence_containers; i++)
+ GST_DEBUG (" essence container %d = %s", i,
+ mxf_ul_to_string (&preface->essence_containers[i], str));
+
+ for (i = 0; i < preface->n_dm_schemes; i++)
+ GST_DEBUG (" DM schemes %d = %s", i,
+ mxf_ul_to_string (&preface->dm_schemes[i], str));
+
+ 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, gsize 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));
+
+ while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+ if (tag_size == 0 || tag == 0x0000)
+ goto next;
+
+ switch (tag) {
+ case 0x3c0a:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&identification->instance_uid, tag_data, 16);
+ break;
+ case 0x3c09:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&identification->generation_uid, tag_data, 16);
+ break;
+ case 0x3c01:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ identification->company_name = mxf_utf16_to_utf8 (tag_data, tag_size);
+ break;
+ case 0x3c02:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ identification->product_name = mxf_utf16_to_utf8 (tag_data, tag_size);
+ break;
+ case 0x3c03:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 10)
+ goto error;
+ if (!mxf_product_version_parse (&identification->product_version,
+ tag_data, tag_size))
+ goto error;
+ break;
+ case 0x3c04:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ identification->version_string = mxf_utf16_to_utf8 (tag_data, tag_size);
+ break;
+ case 0x3c05:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&identification->product_uid, tag_data, 16);
+ break;
+ case 0x3c06:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 8)
+ goto error;
+ if (!mxf_timestamp_parse (&identification->modification_date, tag_data,
+ tag_size))
+ goto error;
+ break;
+ case 0x3c07:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 10)
+ goto error;
+ if (!mxf_product_version_parse (&identification->toolkit_version,
+ tag_data, tag_size))
+ goto error;
+ break;
+ case 0x3c08:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ identification->platform = mxf_utf16_to_utf8 (tag_data, tag_size);
+ break;
+ default:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ 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;
+ }
+
+ GST_DEBUG ("Parsed identification:");
+ GST_DEBUG (" instance uid = %s",
+ mxf_ul_to_string (&identification->instance_uid, str));
+ GST_DEBUG (" generation uid = %s",
+ mxf_ul_to_string (&identification->generation_uid, str));
+ GST_DEBUG (" company name = %s",
+ GST_STR_NULL (identification->company_name));
+ 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);
+ GST_DEBUG (" version string = %s",
+ GST_STR_NULL (identification->version_string));
+ GST_DEBUG (" product uid = %s",
+ mxf_ul_to_string (&identification->product_uid, str));
+ 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);
+ 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);
+ GST_DEBUG (" platform = %s", GST_STR_NULL (identification->platform));
+
+ 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, gsize size)
+{
+ guint16 tag, tag_size;
+ const guint8 *tag_data;
+ gchar str[48];
+ gint i;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ memset (content_storage, 0, sizeof (MXFMetadataContentStorage));
+
+ while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+ if (tag_size == 0 || tag == 0x0000)
+ goto next;
+
+ switch (tag) {
+ case 0x3c0a:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&content_storage->instance_uid, tag_data, 16);
+ break;
+ case 0x0102:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&content_storage->generation_uid, tag_data, 16);
+ break;
+ case 0x1901:{
+ guint32 len;
+ guint i;
+
+ GST_WRITE_UINT16_BE (data, 0x0000);
+
+ len = GST_READ_UINT32_BE (tag_data);
+ 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);
+ break;
+ }
+ case 0x1902:{
+ guint32 len;
+ guint i;
+
+ GST_WRITE_UINT16_BE (data, 0x0000);
+
+ len = GST_READ_UINT32_BE (tag_data);
+ 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);
+ break;
+ }
+ default:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ 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;
+ }
+
+ GST_DEBUG ("Parsed content storage:");
+ GST_DEBUG (" instance uid = %s",
+ mxf_ul_to_string (&content_storage->instance_uid, str));
+ GST_DEBUG (" generation uid = %s",
+ mxf_ul_to_string (&content_storage->generation_uid, str));
+ GST_DEBUG (" number of packages = %u", content_storage->n_packages);
+ GST_DEBUG (" number of essence container data = %u",
+ content_storage->n_essence_container_data);
+
+ for (i = 0; i < content_storage->n_packages; i++)
+ GST_DEBUG (" package %i = %s", i,
+ mxf_ul_to_string (&content_storage->packages_uids[i], str));
+ for (i = 0; i < content_storage->n_packages; i++)
+ GST_DEBUG (" essence container data %i = %s", i,
+ mxf_ul_to_string (&content_storage->essence_container_data_uids[i],
+ str));
+
+ 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, gsize 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));
+
+ while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+ if (tag_size == 0 || tag == 0x0000)
+ goto next;
+
+ switch (tag) {
+ case 0x3c0a:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&essence_container_data->instance_uid, tag_data, 16);
+ break;
+ case 0x2701:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 32)
+ goto error;
+ memcpy (&essence_container_data->linked_package_uid, tag_data, 32);
+ break;
+ case 0x0102:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&essence_container_data->generation_uid, tag_data, 16);
+ break;
+ case 0x3f06:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ essence_container_data->index_sid = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3f07:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ essence_container_data->body_sid = GST_READ_UINT32_BE (tag_data);
+ break;
+ default:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ 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;
+ }
+
+ GST_DEBUG ("Parsed essence container data:");
+ GST_DEBUG (" instance uid = %s",
+ mxf_ul_to_string (&essence_container_data->instance_uid, str));
+ GST_DEBUG (" generation uid = %s",
+ mxf_ul_to_string (&essence_container_data->generation_uid, str));
+ GST_DEBUG (" linked package = %s",
+ mxf_umid_to_string (&essence_container_data->linked_package_uid, str));
+ GST_DEBUG (" index sid = %u", essence_container_data->index_sid);
+ GST_DEBUG (" body sid = %u", essence_container_data->body_sid);
+
+ 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, gsize size)
+{
+ guint16 tag, tag_size;
+ const guint8 *tag_data;
+ gchar str[96];
+ gint i;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ memset (generic_package, 0, sizeof (MXFMetadataGenericPackage));
+
+ while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+ if (tag_size == 0 || tag == 0x0000)
+ goto next;
+
+ switch (tag) {
+ case 0x3c0a:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&generic_package->instance_uid, tag_data, 16);
+ break;
+ case 0x4401:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 32)
+ goto error;
+ memcpy (&generic_package->package_uid, tag_data, 32);
+ break;
+ case 0x0102:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&generic_package->generation_uid, tag_data, 16);
+ break;
+ case 0x4402:
+ generic_package->name = mxf_utf16_to_utf8 (tag_data, tag_size);
+ break;
+ case 0x4405:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (!mxf_timestamp_parse (&generic_package->package_creation_date,
+ tag_data, tag_size))
+ goto error;
+ break;
+ case 0x4404:
+ if (!mxf_timestamp_parse (&generic_package->package_modified_date,
+ tag_data, tag_size))
+ goto error;
+ break;
+ case 0x4403:{
+ guint32 len;
+ guint i;
+
+ GST_WRITE_UINT16_BE (data, 0x0000);
+
+ len = GST_READ_UINT32_BE (tag_data);
+ 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);
+ break;
+ }
+ case 0x4701:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+
+ generic_package->n_descriptors = 1;
+ memcpy (&generic_package->descriptors_uid, tag_data, 16);
+ break;
+ default:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ 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;
+ }
+
+ GST_DEBUG ("Parsed package:");
+ GST_DEBUG (" instance uid = %s",
+ mxf_ul_to_string (&generic_package->instance_uid, str));
+ GST_DEBUG (" generation uid = %s",
+ mxf_ul_to_string (&generic_package->generation_uid, str));
+ GST_DEBUG (" UMID = %s", mxf_umid_to_string (&generic_package->package_uid,
+ str));
+ GST_DEBUG (" name = %s", GST_STR_NULL (generic_package->name));
+ 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);
+ 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);
+ GST_DEBUG (" descriptor = %s",
+ mxf_ul_to_string (&generic_package->descriptors_uid, str));
+ GST_DEBUG (" number of tracks = %u", generic_package->n_tracks);
+
+ for (i = 0; i < generic_package->n_tracks; i++)
+ GST_DEBUG (" track %d = %s", i,
+ mxf_ul_to_string (&generic_package->tracks_uids[i], str));
+
+ 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,
+ const guint8 * data, gsize 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));
+
+ while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+ if (tag_size == 0 || tag == 0x0000)
+ goto next;
+
+ switch (tag) {
+ case 0x3c0a:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&track->instance_uid, tag_data, 16);
+ break;
+ case 0x0102:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&track->generation_uid, tag_data, 16);
+ break;
+ case 0x4801:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ track->track_id = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x4804:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ track->track_number = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x4802:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ track->track_name = mxf_utf16_to_utf8 (tag_data, tag_size);
+ break;
+ case 0x4b01:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (!mxf_fraction_parse (&track->edit_rate, tag_data, tag_size))
+ goto error;
+ break;
+ case 0x4b02:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 8)
+ goto error;
+ track->origin = GST_READ_UINT64_BE (tag_data);
+ break;
+ case 0x4803:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&track->sequence_uid, tag_data, 16);
+ break;
+ default:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ 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;
+ }
+
+ GST_DEBUG ("Parsed track:");
+ GST_DEBUG (" instance uid = %s", mxf_ul_to_string (&track->instance_uid,
+ str));
+ GST_DEBUG (" generation uid = %s", mxf_ul_to_string (&track->generation_uid,
+ str));
+ GST_DEBUG (" track id = %u", track->track_id);
+ GST_DEBUG (" track number = %u", track->track_number);
+ GST_DEBUG (" track name = %s", GST_STR_NULL (track->track_name));
+ GST_DEBUG (" edit rate = %d/%d", track->edit_rate.n, track->edit_rate.d);
+ GST_DEBUG (" origin = %" G_GINT64_FORMAT, track->origin);
+ GST_DEBUG (" sequence uid = %s", mxf_ul_to_string (&track->sequence_uid,
+ str));
+
+ 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, gsize size)
+{
+ guint16 tag, tag_size;
+ const guint8 *tag_data;
+ gchar str[48];
+ gint i;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ memset (sequence, 0, sizeof (MXFMetadataSequence));
+
+ while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+ if (tag_size == 0 || tag == 0x0000)
+ goto next;
+
+ switch (tag) {
+ case 0x3c0a:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&sequence->instance_uid, tag_data, 16);
+ break;
+ case 0x0102:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&sequence->generation_uid, tag_data, 16);
+ break;
+ case 0x0201:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&sequence->data_definition, tag_data, 16);
+ break;
+ case 0x0202:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 8)
+ goto error;
+ sequence->duration = GST_READ_UINT64_BE (tag_data);
+ break;
+ case 0x1001:{
+ guint32 len;
+ guint i;
+
+ GST_WRITE_UINT16_BE (data, 0x0000);
+
+ len = GST_READ_UINT32_BE (tag_data);
+ 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);
+ break;
+ }
+ default:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ 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;
+ }
+
+ GST_DEBUG ("Parsed sequence:");
+ GST_DEBUG (" instance uid = %s", mxf_ul_to_string (&sequence->instance_uid,
+ str));
+ GST_DEBUG (" generation uid = %s",
+ mxf_ul_to_string (&sequence->generation_uid, str));
+ GST_DEBUG (" data definition = %s",
+ mxf_ul_to_string (&sequence->data_definition, str));
+ GST_DEBUG (" duration = %" G_GINT64_FORMAT, sequence->duration);
+ GST_DEBUG (" number of structural components = %u",
+ sequence->n_structural_components);
+
+ for (i = 0; i < sequence->n_structural_components; i++)
+ GST_DEBUG (" structural component %d = %s", i,
+ mxf_ul_to_string (&sequence->structural_components_uids[i], str));
+
+
+ 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, gsize 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));
+
+ component->type = 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:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&component->instance_uid, tag_data, 16);
+ break;
+ case 0x0102:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&component->generation_uid, tag_data, 16);
+ break;
+ case 0x0201:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&component->data_definition, tag_data, 16);
+ break;
+ case 0x0202:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 8)
+ goto error;
+ component->duration = GST_READ_UINT64_BE (tag_data);
+ break;
+ /* Timecode component specifics */
+ case 0x1502:
+ if (type != MXF_METADATA_TIMECODE_COMPONENT)
+ goto DFLT;
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 2)
+ goto error;
+ component->timecode_component.rounded_timecode_base =
+ GST_READ_UINT16_BE (tag_data);
+ break;
+ case 0x1501:
+ if (type != MXF_METADATA_TIMECODE_COMPONENT)
+ goto DFLT;
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 8)
+ goto error;
+ component->timecode_component.start_timecode =
+ GST_READ_UINT64_BE (tag_data);
+ break;
+ case 0x1503:
+ if (type != MXF_METADATA_TIMECODE_COMPONENT)
+ goto DFLT;
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 1)
+ goto error;
+ component->timecode_component.drop_frame =
+ (GST_READ_UINT8 (tag_data) != 0);
+ break;
+ /* Source clip specifics */
+ case 0x1201:
+ if (type != MXF_METADATA_SOURCE_CLIP)
+ goto DFLT;
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 8)
+ goto error;
+ component->source_clip.start_position = GST_READ_UINT64_BE (tag_data);
+ break;
+ case 0x1101:
+ if (type != MXF_METADATA_SOURCE_CLIP)
+ goto DFLT;
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 32)
+ goto error;
+ memcpy (&component->source_clip.source_package_id, tag_data, 32);
+ break;
+ case 0x1102:
+ if (type != MXF_METADATA_SOURCE_CLIP)
+ goto DFLT;
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ component->source_clip.source_track_id = GST_READ_UINT32_BE (tag_data);
+ break;
+ DFLT:
+ default:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ 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;
+ }
+
+ GST_DEBUG ("Parsed structural component:");
+ GST_DEBUG (" instance uid = %s", mxf_ul_to_string (&component->instance_uid,
+ str));
+ GST_DEBUG (" generation uid = %s",
+ mxf_ul_to_string (&component->generation_uid, str));
+ GST_DEBUG (" type = %s",
+ (component->type ==
+ MXF_METADATA_TIMECODE_COMPONENT) ? "timecode component" :
+ "source clip");
+ GST_DEBUG (" data definition = %s",
+ mxf_ul_to_string (&component->data_definition, str));
+ GST_DEBUG (" duration = %" G_GINT64_FORMAT, component->duration);
+
+ if (component->type == MXF_METADATA_TIMECODE_COMPONENT) {
+ GST_DEBUG (" start timecode = %" G_GINT64_FORMAT,
+ component->timecode_component.start_timecode);
+ GST_DEBUG (" rounded timecode base = %u",
+ component->timecode_component.rounded_timecode_base);
+ GST_DEBUG (" drop frame = %s",
+ (component->timecode_component.drop_frame) ? "yes" : "no");
+ } else {
+ GST_DEBUG (" start position = %" G_GINT64_FORMAT,
+ component->source_clip.start_position);
+ GST_DEBUG (" source package id = %s",
+ mxf_umid_to_string (&component->source_clip.source_package_id, str));
+ GST_DEBUG (" source track id = %u",
+ component->source_clip.source_track_id);
+ }
+
+ 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->other_tags)
+ g_hash_table_destroy (component->other_tags);
+
+ memset (component, 0, sizeof (MXFMetadataStructuralComponent));
+}
+
+gboolean
+mxf_metadata_generic_descriptor_parse (const MXFUL * key,
+ MXFMetadataGenericDescriptor * descriptor,
+ const MXFPrimerPack * primer, guint16 type, const guint8 * data, gsize size)
+{
+ guint16 tag, tag_size;
+ const guint8 *tag_data;
+ gchar str[48];
+ gint i;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ memset (descriptor, 0, sizeof (MXFMetadataGenericDescriptor));
+
+ descriptor->type = 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:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&descriptor->instance_uid, tag_data, 16);
+ break;
+ case 0x0102:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&descriptor->generation_uid, tag_data, 16);
+ break;
+ case 0x2f01:{
+ guint32 len;
+ guint i;
+
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size < 8)
+ goto error;
+
+ len = GST_READ_UINT32_BE (tag_data);
+ if (len == 0)
+ goto next;
+
+ 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);
+ break;
+ }
+ }
+ next:
+
+ data += 4 + tag_size;
+ size -= 4 + tag_size;
+ }
+
+ GST_DEBUG ("Parsed generic descriptor:");
+ GST_DEBUG (" instance uid = %s", mxf_ul_to_string (&descriptor->instance_uid,
+ str));
+ GST_DEBUG (" generation uid = %s",
+ mxf_ul_to_string (&descriptor->generation_uid, str));
+ GST_DEBUG (" type = %u", descriptor->type);
+ GST_DEBUG (" number of locators = %u", descriptor->n_locators);
+
+ for (i = 0; i < descriptor->n_locators; i++)
+ GST_DEBUG (" locator %d = %s", i,
+ mxf_ul_to_string (&descriptor->locators_uids[i], str));
+
+ return TRUE;
+
+error:
+ GST_ERROR ("Invalid generic descriptor");
+ mxf_metadata_generic_descriptor_reset (descriptor);
+
+ return FALSE;
+}
+
+void mxf_metadata_generic_descriptor_reset
+ (MXFMetadataGenericDescriptor * descriptor)
+{
+ g_return_if_fail (descriptor != NULL);
+
+ switch (descriptor->type) {
+ case MXF_METADATA_FILE_DESCRIPTOR:
+ break;
+ }
+
+ 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_parse (const MXFUL * key,
+ MXFMetadataFileDescriptor * descriptor,
+ const MXFPrimerPack * primer, guint16 type, const guint8 * data, gsize size)
+{
+ guint16 tag, tag_size;
+ const guint8 *tag_data;
+ gchar str[48];
+
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ memset (descriptor, 0, sizeof (MXFMetadataFileDescriptor));
+
+ if (!mxf_metadata_generic_descriptor_parse (key,
+ (MXFMetadataGenericDescriptor *) descriptor, primer, type, data,
+ size))
+ goto error;
+
+ descriptor->parent.is_file_descriptor = TRUE;
+
+ while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+ if (tag_size == 0 || tag == 0x0000)
+ goto next;
+
+ switch (tag) {
+ case 0x3006:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->linked_track_id = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3001:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (!mxf_fraction_parse (&descriptor->sample_rate, tag_data, tag_size))
+ goto error;
+ break;
+ case 0x3002:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 8)
+ goto error;
+ descriptor->container_duration = GST_READ_UINT64_BE (tag_data);
+ break;
+ case 0x3004:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&descriptor->essence_container, tag_data, 16);
+ break;
+ case 0x3005:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&descriptor->codec, tag_data, 16);
+ break;
+ default:
+ if (type != MXF_METADATA_FILE_DESCRIPTOR)
+ goto next;
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
+ &((MXFMetadataGenericDescriptor *) descriptor)->other_tags))
+ goto error;
+ break;
+ }
+
+ next:
+ data += 4 + tag_size;
+ size -= 4 + tag_size;
+ }
+
+ GST_DEBUG ("Parsed file descriptor:");
+ GST_DEBUG (" linked track id = %u", descriptor->linked_track_id);
+ GST_DEBUG (" sample rate = %d/%d", descriptor->sample_rate.n,
+ descriptor->sample_rate.d);
+ GST_DEBUG (" container duration = %" G_GINT64_FORMAT,
+ descriptor->container_duration);
+ GST_DEBUG (" essence container = %s",
+ mxf_ul_to_string (&descriptor->essence_container, str));
+ GST_DEBUG (" codec = %s", mxf_ul_to_string (&descriptor->codec, str));
+
+ return TRUE;
+
+error:
+ GST_ERROR ("Invalid file descriptor");
+ mxf_metadata_file_descriptor_reset (descriptor);
+
+ return FALSE;
+}
+
+void
+mxf_metadata_file_descriptor_reset (MXFMetadataFileDescriptor * descriptor)
+{
+ g_return_if_fail (descriptor != NULL);
+
+ mxf_metadata_generic_descriptor_reset ((MXFMetadataGenericDescriptor *)
+ descriptor);
+
+ memset (descriptor, 0, sizeof (MXFMetadataFileDescriptor));
+}
+
+gboolean
+mxf_metadata_generic_sound_essence_descriptor_parse (const MXFUL * key,
+ MXFMetadataGenericSoundEssenceDescriptor * descriptor,
+ const MXFPrimerPack * primer, guint16 type, const guint8 * data, gsize size)
+{
+ guint16 tag, tag_size;
+ const guint8 *tag_data;
+ gchar str[48];
+
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ memset (descriptor, 0, sizeof (MXFMetadataGenericSoundEssenceDescriptor));
+
+ if (!mxf_metadata_file_descriptor_parse (key,
+ (MXFMetadataFileDescriptor *) descriptor, primer, type, data, size))
+ goto error;
+
+ while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+ if (tag_size == 0 || tag == 0x0000)
+ goto next;
+
+ switch (tag) {
+ case 0x3d03:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (!mxf_fraction_parse (&descriptor->audio_sampling_rate, tag_data,
+ tag_size))
+ goto error;
+ break;
+ case 0x3d02:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 1)
+ goto error;
+ descriptor->locked = (GST_READ_UINT8 (tag_data) != 0);
+ break;
+ case 0x3d04:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 1)
+ goto error;
+ descriptor->audio_ref_level = GST_READ_UINT8 (tag_data);
+ break;
+ case 0x3d05:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 1)
+ goto error;
+ descriptor->electro_spatial_formulation = GST_READ_UINT8 (tag_data);
+ break;
+ case 0x3d07:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->channel_count = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3d01:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->quantization_bits = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3d0c:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 1)
+ goto error;
+ descriptor->dial_norm = GST_READ_UINT8 (tag_data);
+ break;
+ case 0x3d06:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&descriptor->sound_essence_compression, tag_data, 16);
+ break;
+ default:
+ if (type != MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR)
+ goto next;
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
+ &((MXFMetadataGenericDescriptor *) descriptor)->other_tags))
+ goto error;
+ break;
+ }
+
+ next:
+ data += 4 + tag_size;
+ size -= 4 + tag_size;
+ }
+
+ GST_DEBUG ("Parsed generic sound essence descriptor:");
+ GST_DEBUG (" audio sampling rate = %d/%d", descriptor->audio_sampling_rate.n,
+ descriptor->audio_sampling_rate.d);
+ GST_DEBUG (" locked = %s", (descriptor->locked) ? "yes" : "no");
+ GST_DEBUG (" audio ref level = %d", descriptor->audio_ref_level);
+ GST_DEBUG (" electro spatial formulation = %u",
+ descriptor->electro_spatial_formulation);
+ GST_DEBUG (" channel count = %u", descriptor->channel_count);
+ GST_DEBUG (" quantization bits = %u", descriptor->quantization_bits);
+ GST_DEBUG (" dial norm = %d", descriptor->dial_norm);
+ GST_DEBUG (" sound essence compression = %s",
+ mxf_ul_to_string (&descriptor->sound_essence_compression, str));
+
+ return TRUE;
+
+error:
+ GST_ERROR ("Invalid generic sound essence descriptor");
+ mxf_metadata_generic_sound_essence_descriptor_reset (descriptor);
+
+ return FALSE;
+}
+
+void mxf_metadata_generic_sound_essence_descriptor_reset
+ (MXFMetadataGenericSoundEssenceDescriptor * descriptor)
+{
+ g_return_if_fail (descriptor != NULL);
+
+ mxf_metadata_file_descriptor_reset ((MXFMetadataFileDescriptor *) descriptor);
+
+ memset (descriptor, 0, sizeof (MXFMetadataGenericSoundEssenceDescriptor));
+}
+
+gboolean
+mxf_metadata_generic_picture_essence_descriptor_parse (const MXFUL * key,
+ MXFMetadataGenericPictureEssenceDescriptor * descriptor,
+ const MXFPrimerPack * primer, guint16 type, const guint8 * data, gsize size)
+{
+ guint16 tag, tag_size;
+ const guint8 *tag_data;
+ gchar str[48];
+
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ memset (descriptor, 0, sizeof (MXFMetadataGenericPictureEssenceDescriptor));
+
+ if (!mxf_metadata_file_descriptor_parse (key,
+ (MXFMetadataFileDescriptor *) descriptor, primer, type, data, size))
+ goto error;
+
+ while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+ if (tag_size == 0 || tag == 0x0000)
+ goto next;
+
+ switch (tag) {
+ case 0x3215:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 1)
+ goto error;
+ descriptor->signal_standard = GST_READ_UINT8 (tag_data);
+ break;
+ case 0x320c:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 1)
+ goto error;
+ descriptor->frame_layout = GST_READ_UINT8 (tag_data);
+ break;
+ case 0x3203:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->stored_width = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3202:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->stored_height = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3216:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->stored_f2_offset = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3205:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->sampled_width = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3204:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->sampled_height = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3206:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->sampled_x_offset = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3207:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->sampled_y_offset = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3208:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->display_height = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3209:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->display_width = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x320a:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->display_x_offset = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x320b:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->display_y_offset = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3217:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->display_f2_offset = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x320e:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (!mxf_fraction_parse (&descriptor->aspect_ratio, tag_data, tag_size))
+ goto error;
+ break;
+ case 0x3218:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 1)
+ goto error;
+ descriptor->active_format_descriptor = GST_READ_UINT8 (tag_data);
+ break;
+ case 0x320d:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size < 8)
+ goto error;
+
+ if (GST_READ_UINT32_BE (tag_data) == 0)
+ goto next;
+
+ 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);
+ break;
+ case 0x320f:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 1)
+ goto error;
+ descriptor->alpha_transparency = GST_READ_UINT8 (tag_data);
+ break;
+ case 0x3210:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&descriptor->capture_gamma, tag_data, 16);
+ break;
+ case 0x3211:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->image_alignment_offset = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3213:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->image_start_offset = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3214:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->image_end_offset = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3212:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 1)
+ goto error;
+ descriptor->field_dominance = GST_READ_UINT8 (tag_data);
+ break;
+ case 0x3201:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&descriptor->picture_essence_coding, tag_data, 16);
+ break;
+ default:
+ if (type != MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR)
+ goto next;
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
+ &((MXFMetadataGenericDescriptor *) descriptor)->other_tags))
+ goto error;
+ break;
+ }
+
+ next:
+ data += 4 + tag_size;
+ size -= 4 + tag_size;
+ }
+
+ GST_DEBUG ("Parsed generic picture essence descriptor:");
+ GST_DEBUG (" signal standard = %u", descriptor->signal_standard);
+ GST_DEBUG (" frame layout = %u", descriptor->frame_layout);
+ GST_DEBUG (" stored size = %ux%u (f2 = %d)", descriptor->stored_width,
+ descriptor->stored_height, descriptor->stored_f2_offset);
+ GST_DEBUG (" sampled size = %ux%u (offset = %d x %d)",
+ descriptor->sampled_width, descriptor->sampled_height,
+ descriptor->sampled_x_offset, descriptor->sampled_y_offset);
+ GST_DEBUG (" display size = %ux%u (f2 = %d, offset = %d x %d)",
+ descriptor->display_height, descriptor->display_width,
+ descriptor->display_x_offset, descriptor->display_y_offset,
+ descriptor->display_f2_offset);
+ GST_DEBUG (" aspect ratio = %d/%d", descriptor->aspect_ratio.n,
+ descriptor->aspect_ratio.d);
+ GST_DEBUG (" active format descriptor = %u",
+ descriptor->active_format_descriptor);
+ GST_DEBUG (" video line map = {%i, %i}", descriptor->video_line_map[0],
+ descriptor->video_line_map[1]);
+ GST_DEBUG (" alpha transparency = %u", descriptor->alpha_transparency);
+ GST_DEBUG (" capture gamma = %s",
+ mxf_ul_to_string (&descriptor->capture_gamma, str));
+ GST_DEBUG (" image alignment offset = %u",
+ descriptor->image_alignment_offset);
+ GST_DEBUG (" image start offset = %u", descriptor->image_start_offset);
+ GST_DEBUG (" image end offset = %u", descriptor->image_end_offset);
+ GST_DEBUG (" field dominance = %u", descriptor->field_dominance);
+ GST_DEBUG (" picture essence coding = %s",
+ mxf_ul_to_string (&descriptor->picture_essence_coding, str));
+
+ return TRUE;
+
+error:
+ GST_ERROR ("Invalid generic picture essence descriptor");
+ mxf_metadata_generic_picture_essence_descriptor_reset (descriptor);
+
+ return FALSE;
+}
+
+void mxf_metadata_generic_picture_essence_descriptor_reset
+ (MXFMetadataGenericPictureEssenceDescriptor * descriptor)
+{
+ g_return_if_fail (descriptor != NULL);
+
+ mxf_metadata_file_descriptor_reset ((MXFMetadataFileDescriptor *) descriptor);
+
+ memset (descriptor, 0, sizeof (MXFMetadataGenericPictureEssenceDescriptor));
+}
+
+gboolean
+mxf_metadata_cdci_picture_essence_descriptor_parse (const MXFUL * key,
+ MXFMetadataCDCIPictureEssenceDescriptor * descriptor,
+ const MXFPrimerPack * primer, guint16 type, const guint8 * data, gsize size)
+{
+ guint16 tag, tag_size;
+ const guint8 *tag_data;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ memset (descriptor, 0, sizeof (MXFMetadataCDCIPictureEssenceDescriptor));
+
+ if (!mxf_metadata_generic_picture_essence_descriptor_parse (key,
+ (MXFMetadataGenericPictureEssenceDescriptor *) descriptor, primer,
+ type, data, size))
+ goto error;
+
+ while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+ if (tag_size == 0 || tag == 0x0000)
+ goto next;
+
+ switch (tag) {
+ case 0x3301:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->component_depth = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3302:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->horizontal_subsampling = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3308:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->vertical_subsampling = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3303:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 1)
+ goto error;
+ descriptor->color_siting = GST_READ_UINT8 (tag_data);
+ break;
+ case 0x330b:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 1)
+ goto error;
+ descriptor->reversed_byte_order = GST_READ_UINT8 (tag_data);
+ break;
+ case 0x3307:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 2)
+ goto error;
+ descriptor->padding_bits = GST_READ_UINT16_BE (tag_data);
+ break;
+ case 0x3309:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->alpha_sample_depth = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3304:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->black_ref_level = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3305:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->white_ref_level = GST_READ_UINT32_BE (tag_data);
+ break;
+ case 0x3306:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 4)
+ goto error;
+ descriptor->color_range = GST_READ_UINT32_BE (tag_data);
+ break;
+ default:
+ if (type != MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR)
+ goto next;
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
+ &((MXFMetadataGenericDescriptor *) descriptor)->other_tags))
+ goto error;
+ break;
+ }
+
+ next:
+ data += 4 + tag_size;
+ size -= 4 + tag_size;
+ }
+
+ GST_DEBUG ("Parsed CDCI picture essence descriptor:");
+ GST_DEBUG (" component depth = %u", descriptor->component_depth);
+ GST_DEBUG (" horizontal subsampling = %u",
+ descriptor->horizontal_subsampling);
+ GST_DEBUG (" vertical subsampling = %u", descriptor->vertical_subsampling);
+ GST_DEBUG (" color siting = %u", descriptor->color_siting);
+ GST_DEBUG (" reversed byte order = %s",
+ (descriptor->reversed_byte_order) ? "yes" : "no");
+ GST_DEBUG (" padding bits = %d", descriptor->padding_bits);
+ GST_DEBUG (" alpha sample depth = %u", descriptor->alpha_sample_depth);
+ GST_DEBUG (" black ref level = %u", descriptor->black_ref_level);
+ GST_DEBUG (" white ref level = %u", descriptor->white_ref_level);
+ GST_DEBUG (" color range = %u", descriptor->color_range);
+
+ return TRUE;
+
+error:
+ GST_ERROR ("Invalid CDCI picture essence descriptor");
+ mxf_metadata_cdci_picture_essence_descriptor_reset (descriptor);
+
+ return FALSE;
+}
+
+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);
+
+ memset (descriptor, 0, sizeof (MXFMetadataCDCIPictureEssenceDescriptor));
+}
+
+gboolean
+mxf_metadata_multiple_descriptor_parse (const MXFUL * key,
+ MXFMetadataMultipleDescriptor * descriptor,
+ const MXFPrimerPack * primer, guint16 type, const guint8 * data, gsize size)
+{
+ guint16 tag, tag_size;
+ const guint8 *tag_data;
+ gchar str[48];
+ gint i;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ memset (descriptor, 0, sizeof (MXFMetadataMultipleDescriptor));
+
+ if (!mxf_metadata_file_descriptor_parse (key,
+ (MXFMetadataFileDescriptor *) descriptor, primer, type, data, size))
+ goto error;
+
+ while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+ if (tag_size == 0 || tag == 0x0000)
+ goto next;
+
+ switch (tag) {
+ case 0x3f01:{
+ guint32 len;
+ guint i;
+
+ GST_WRITE_UINT16_BE (data, 0x0000);
+
+ if (tag_size < 8)
+ goto error;
+ len = GST_READ_UINT32_BE (tag_data);
+ if (len == 0)
+ goto next;
+
+ 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);
+ break;
+ }
+ default:
+ if (type != MXF_METADATA_MULTIPLE_DESCRIPTOR)
+ goto next;
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
+ &((MXFMetadataGenericDescriptor *) descriptor)->other_tags))
+ goto error;
+ break;
+ }
+
+ next:
+ data += 4 + tag_size;
+ size -= 4 + tag_size;
+ }
+
+ GST_DEBUG ("Parsed multiple descriptor:");
+ GST_DEBUG (" number of sub descriptors = %u", descriptor->n_sub_descriptors);
+ for (i = 0; i < descriptor->n_sub_descriptors; i++)
+ GST_DEBUG (" sub descriptor %d = %s", i,
+ mxf_ul_to_string (&descriptor->sub_descriptors_uids[i], str));
+
+ return TRUE;
+
+error:
+ GST_ERROR ("Invalid multiple descriptor");
+ mxf_metadata_multiple_descriptor_reset (descriptor);
+
+ return FALSE;
+}
+
+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);
+
+ memset (descriptor, 0, sizeof (MXFMetadataMultipleDescriptor));
+}
+
+gboolean
+mxf_metadata_locator_parse (const MXFUL * key,
+ MXFMetadataLocator * locator, const MXFPrimerPack * primer,
+ guint16 type, const guint8 * data, gsize 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;
+
+ while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
+ if (tag_size == 0 || tag == 0x0000)
+ goto next;
+
+ switch (tag) {
+ case 0x3c0a:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&locator->instance_uid, tag_data, 16);
+ break;
+ case 0x0102:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ if (tag_size != 16)
+ goto error;
+ memcpy (&locator->generation_uid, tag_data, 16);
+ break;
+ case 0x4101:
+ if (type != MXF_METADATA_TEXT_LOCATOR
+ && type != MXF_METADATA_NETWORK_LOCATOR)
+ goto DFLT;
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ locator->location = mxf_utf16_to_utf8 (tag_data, tag_size);
+ break;
+ DFLT:
+ default:
+ GST_WRITE_UINT16_BE (data, 0x0000);
+ 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;
+ }
+
+ GST_DEBUG ("Parsed locator:");
+ GST_DEBUG (" instance uid = %s", mxf_ul_to_string (&locator->instance_uid,
+ str));
+ GST_DEBUG (" generation uid = %s",
+ mxf_ul_to_string (&locator->generation_uid, str));
+ GST_DEBUG (" location = %s", GST_STR_NULL (locator->location));
+
+ 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));
+}