gst/mxf/: Implement parsing of index table segments, which will later be used for...
authorSebastian Dröge <slomo@circular-chaos.org>
Fri, 28 Nov 2008 11:24:24 +0000 (11:24 +0000)
committerSebastian Dröge <slomo@circular-chaos.org>
Fri, 28 Nov 2008 11:24:24 +0000 (11:24 +0000)
Original commit message from CVS:
* gst/mxf/mxfdemux.c: (gst_mxf_demux_reset),
(gst_mxf_demux_handle_index_table_segment):
* gst/mxf/mxfdemux.h:
* gst/mxf/mxfparse.c: (mxf_index_table_segment_parse),
(mxf_index_table_segment_reset):
* gst/mxf/mxfparse.h:
* gst/mxf/mxftypes.h:
Implement parsing of index table segments, which will later be
used for seeking.

ChangeLog
gst/mxf/mxfdemux.c
gst/mxf/mxfdemux.h
gst/mxf/mxfparse.c
gst/mxf/mxfparse.h
gst/mxf/mxftypes.h

index d161448..6476033 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2008-11-28  Sebastian Dröge  <sebastian.droege@collabora.co.uk>
 
+       * gst/mxf/mxfdemux.c: (gst_mxf_demux_reset),
+       (gst_mxf_demux_handle_index_table_segment):
+       * gst/mxf/mxfdemux.h:
+       * gst/mxf/mxfparse.c: (mxf_index_table_segment_parse),
+       (mxf_index_table_segment_reset):
+       * gst/mxf/mxfparse.h:
+       * gst/mxf/mxftypes.h:
+       Implement parsing of index table segments, which will later be
+       used for seeking.
+
+2008-11-28  Sebastian Dröge  <sebastian.droege@collabora.co.uk>
+
        * docs/plugins/gst-plugins-bad-plugins.args:
        * docs/plugins/gst-plugins-bad-plugins.hierarchy:
        * docs/plugins/gst-plugins-bad-plugins.interfaces:
index 07151b5..9813b3a 100644 (file)
@@ -394,6 +394,17 @@ gst_mxf_demux_reset (GstMXFDemux * demux)
     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);
 }
@@ -1280,9 +1291,8 @@ gst_mxf_demux_handle_header_metadata_resolve_references (GstMXFDemux * demux)
           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)) {
+        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;
         }
@@ -2160,11 +2170,32 @@ static GstFlowReturn
 gst_mxf_demux_handle_index_table_segment (GstMXFDemux * demux,
     const MXFUL * key, GstBuffer * buffer)
 {
+  MXFIndexTableSegment segment;
+
+  memset (&segment, 0, sizeof (segment));
+
   GST_DEBUG_OBJECT (demux,
       "Handling index table segment of size %u at offset %"
       G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
 
-  /* TODO: Parse this */
+  if (!demux->primer.valid) {
+    GST_WARNING_OBJECT (demux, "Invalid primer pack");
+    return GST_FLOW_OK;
+  }
+
+  if (!mxf_index_table_segment_parse (key, &segment, &demux->primer,
+          GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
+
+    GST_ERROR_OBJECT (demux, "Parsing index table segment failed");
+    return GST_FLOW_ERROR;
+  }
+
+  if (!demux->index_table)
+    demux->index_table =
+        g_array_new (FALSE, FALSE, sizeof (MXFIndexTableSegment));
+
+  g_array_append_val (demux->index_table, segment);
+
   return GST_FLOW_OK;
 }
 
index 674e6c3..887200c 100644 (file)
@@ -68,6 +68,7 @@ struct _GstMXFDemux
   MXFPrimerPack primer;
 
   GArray *partition_index;
+  GArray *index_table;
 
   /* Structural metadata */
   gboolean update_metadata;
index aceebc9..ba6d969 100644 (file)
@@ -596,6 +596,246 @@ mxf_random_index_pack_parse (const MXFUL * key, const guint8 * data, guint size,
   return TRUE;
 }
 
+/* SMPTE 377M 10.2.3 */
+gboolean
+mxf_index_table_segment_parse (const MXFUL * key,
+    MXFIndexTableSegment * segment, const MXFPrimerPack * primer,
+    const guint8 * data, guint size)
+{
+  gchar str[48];
+  guint16 tag, tag_size;
+  const guint8 *tag_data;
+
+  g_return_val_if_fail (key != NULL, FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+  g_return_val_if_fail (primer != NULL, FALSE);
+
+  memset (segment, 0, sizeof (MXFIndexTableSegment));
+
+  if (size < 70)
+    return FALSE;
+
+  GST_DEBUG ("Parsing index table segment:");
+
+  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 (&segment->instance_id, tag_data, 16);
+        GST_DEBUG ("  instance id = %s",
+            mxf_ul_to_string (&segment->instance_id, str));
+        break;
+      case 0x3f0b:
+        if (!mxf_fraction_parse (&segment->index_edit_rate, tag_data, tag_size))
+          goto error;
+        GST_DEBUG ("  index edit rate = %d/%d", segment->index_edit_rate.n,
+            segment->index_edit_rate.d);
+        break;
+      case 0x3f0c:
+        if (tag_size != 8)
+          goto error;
+        segment->index_start_position = GST_READ_UINT64_BE (tag_data);
+        GST_DEBUG ("  index start position = %" G_GINT64_FORMAT,
+            segment->index_start_position);
+        break;
+      case 0x3f0d:
+        if (tag_size != 8)
+          goto error;
+        segment->index_duration = GST_READ_UINT64_BE (tag_data);
+        GST_DEBUG ("  index duration = %" G_GINT64_FORMAT,
+            segment->index_duration);
+        break;
+      case 0x3f05:
+        if (tag_size != 4)
+          goto error;
+        segment->edit_unit_byte_count = GST_READ_UINT32_BE (tag_data);
+        GST_DEBUG ("  edit unit byte count = %u",
+            segment->edit_unit_byte_count);
+        break;
+      case 0x3f06:
+        if (tag_size != 4)
+          goto error;
+        segment->index_sid = GST_READ_UINT32_BE (tag_data);
+        GST_DEBUG ("  index sid = %u", segment->index_sid);
+        break;
+      case 0x3f07:
+        if (tag_size != 4)
+          goto error;
+        segment->body_sid = GST_READ_UINT32_BE (tag_data);
+        GST_DEBUG ("  body sid = %u", segment->body_sid);
+        break;
+      case 0x3f08:
+        if (tag_size != 1)
+          goto error;
+        segment->slice_count = GST_READ_UINT8 (tag_data);
+        GST_DEBUG ("  slice count = %u", segment->slice_count);
+        break;
+      case 0x3f0e:
+        if (tag_size != 1)
+          goto error;
+        segment->pos_table_count = GST_READ_UINT8 (tag_data);
+        GST_DEBUG ("  pos table count = %u", segment->pos_table_count);
+        break;
+      case 0x3f09:{
+        guint len, i;
+
+        if (tag_size < 8)
+          goto error;
+
+        len = GST_READ_UINT32_BE (tag_data);
+        segment->n_delta_entries = len;
+        GST_DEBUG ("  number of delta entries = %u", segment->n_delta_entries);
+        if (len == 0)
+          goto next;
+        tag_data += 4;
+        tag_size -= 4;
+
+        if (GST_READ_UINT32_BE (tag_data) != 6)
+          goto error;
+
+        tag_data += 4;
+        tag_size -= 4;
+
+        if (tag_size < len * 6)
+          goto error;
+
+        segment->delta_entries = g_new (MXFDeltaEntry, len);
+
+        for (i = 0; i < len; i++) {
+          GST_DEBUG ("    delta entry %u:", i);
+
+          segment->delta_entries[i].pos_table_index = GST_READ_UINT8 (tag_data);
+          tag_data += 1;
+          tag_size -= 1;
+          GST_DEBUG ("    pos table index = %d",
+              segment->delta_entries[i].pos_table_index);
+
+          segment->delta_entries[i].slice = GST_READ_UINT8 (tag_data);
+          tag_data += 1;
+          tag_size -= 1;
+          GST_DEBUG ("    slice = %u", segment->delta_entries[i].slice);
+
+          segment->delta_entries[i].element_delta =
+              GST_READ_UINT32_BE (tag_data);
+          tag_data += 4;
+          tag_size -= 4;
+          GST_DEBUG ("    element delta = %u",
+              segment->delta_entries[i].element_delta);
+        }
+        break;
+      }
+      case 0x3f0a:{
+        guint len, i, j;
+
+        if (tag_size < 8)
+          goto error;
+
+        len = GST_READ_UINT32_BE (tag_data);
+        segment->n_index_entries = len;
+        GST_DEBUG ("  number of index entries = %u", segment->n_index_entries);
+        if (len == 0)
+          goto next;
+        tag_data += 4;
+        tag_size -= 4;
+
+        if (GST_READ_UINT32_BE (tag_data) !=
+            (11 + 4 * segment->slice_count + 8 * segment->pos_table_count))
+          goto error;
+
+        tag_data += 4;
+        tag_size -= 4;
+
+        if (tag_size <
+            len * (11 + 4 * segment->slice_count +
+                8 * segment->pos_table_count))
+          goto error;
+
+        segment->index_entries = g_new (MXFIndexEntry, len);
+
+        for (i = 0; i < len; i++) {
+          MXFIndexEntry *entry = &segment->index_entries[i];
+
+          GST_DEBUG ("    index entry %u:", i);
+
+          entry->temporal_offset = GST_READ_UINT8 (tag_data);
+          tag_data += 1;
+          tag_size -= 1;
+          GST_DEBUG ("    temporal offset = %d", entry->temporal_offset);
+
+          entry->key_frame_offset = GST_READ_UINT8 (tag_data);
+          tag_data += 1;
+          tag_size -= 1;
+          GST_DEBUG ("    keyframe offset = %d", entry->key_frame_offset);
+
+          entry->flags = GST_READ_UINT8 (tag_data);
+          tag_data += 1;
+          tag_size -= 1;
+          GST_DEBUG ("    flags = 0x%02x", entry->flags);
+
+          entry->stream_offset = GST_READ_UINT64_BE (tag_data);
+          tag_data += 8;
+          tag_size -= 8;
+          GST_DEBUG ("    stream offset = %" G_GUINT64_FORMAT,
+              entry->stream_offset);
+
+          for (j = 0; j < segment->slice_count; j++) {
+            entry->slice_offset[j] = GST_READ_UINT32_BE (tag_data);
+            tag_data += 4;
+            tag_size -= 4;
+            GST_DEBUG ("    slice %u offset = %u", j, entry->slice_offset[j]);
+          }
+
+          for (j = 0; j < segment->pos_table_count; j++) {
+            mxf_fraction_parse (&entry->pos_table[j], tag_data, tag_size);
+            tag_data += 8;
+            tag_size -= 8;
+            GST_DEBUG ("    pos table %u = %d/%d", j, entry->pos_table[j].n,
+                entry->pos_table[j].d);
+          }
+        }
+        break;
+      }
+      default:
+        if (!gst_metadata_add_custom_tag (primer, tag, tag_data, tag_size,
+                &segment->other_tags))
+          goto error;
+        break;
+    }
+
+  next:
+    data += 4 + tag_size;
+    size -= 4 + tag_size;
+  }
+  return TRUE;
+
+error:
+  GST_ERROR ("Invalid index table segment");
+  return FALSE;
+}
+
+void
+mxf_index_table_segment_reset (MXFIndexTableSegment * segment)
+{
+  guint i;
+  g_return_if_fail (segment != NULL);
+
+  for (i = 0; i < segment->n_index_entries; i++) {
+    g_free (segment->index_entries[i].slice_offset);
+    g_free (segment->index_entries[i].pos_table);
+  }
+  g_free (segment->index_entries);
+  g_free (segment->delta_entries);
+
+  if (segment->other_tags)
+    g_hash_table_destroy (segment->other_tags);
+
+  memset (segment, 0, sizeof (MXFIndexTableSegment));
+}
+
 /* SMPTE 377M 8.2 Table 1 and 2 */
 
 static void
index 6cace26..54b4c0d 100644 (file)
@@ -79,6 +79,9 @@ void mxf_primer_pack_reset (MXFPrimerPack *pack);
 
 gboolean mxf_random_index_pack_parse (const MXFUL *key, const guint8 *data, guint size, GArray **array);
 
+gboolean mxf_index_table_segment_parse (const MXFUL *key, MXFIndexTableSegment *segment, const MXFPrimerPack *primer, const guint8 *data, guint size);
+void mxf_index_table_segment_reset (MXFIndexTableSegment *segment);
+
 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);
index f6ca345..4b2a6e7 100644 (file)
@@ -115,6 +115,44 @@ typedef struct {
   GHashTable *mappings;
 } MXFPrimerPack;
 
+/* SMPTE 377M 10.2.3 */
+typedef struct {
+  gint8 pos_table_index;
+  guint8 slice;
+  guint32 element_delta;
+} MXFDeltaEntry;
+
+typedef struct {
+  gint8 temporal_offset;
+  gint8 key_frame_offset;
+
+  guint8 flags;
+  guint64 stream_offset;
+  
+  guint32 *slice_offset;
+  MXFFraction *pos_table;
+} MXFIndexEntry;
+
+typedef struct {
+  MXFUL instance_id;
+  MXFFraction index_edit_rate;
+  gint64 index_start_position;
+  gint64 index_duration;
+  guint32 edit_unit_byte_count;
+  guint32 index_sid;
+  guint32 body_sid;
+  guint8 slice_count;
+  guint8 pos_table_count;
+
+  guint32 n_delta_entries;
+  MXFDeltaEntry *delta_entries;
+
+  guint32 n_index_entries;
+  MXFIndexEntry *index_entries;
+
+  GHashTable *other_tags;
+} MXFIndexTableSegment;
+
 /* SMPTE 377M 8.6 table 14 */
 #define MXF_METADATA_PREFACE (0x012f)
 #define MXF_METADATA_IDENTIFICATION (0x0130)