From 65587b80f51d6ab80bdc076ee4e375b61e7371c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 28 Nov 2008 11:24:24 +0000 Subject: gst/mxf/: Implement parsing of index table segments, which will later be used for seeking. 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. --- gst/mxf/mxfdemux.c | 39 ++++++++- gst/mxf/mxfdemux.h | 1 + gst/mxf/mxfparse.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++++++ gst/mxf/mxfparse.h | 3 + gst/mxf/mxftypes.h | 38 +++++++++ 5 files changed, 317 insertions(+), 4 deletions(-) (limited to 'gst') diff --git a/gst/mxf/mxfdemux.c b/gst/mxf/mxfdemux.c index 07151b5e..9813b3a3 100644 --- a/gst/mxf/mxfdemux.c +++ b/gst/mxf/mxfdemux.c @@ -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; } diff --git a/gst/mxf/mxfdemux.h b/gst/mxf/mxfdemux.h index 674e6c35..887200cd 100644 --- a/gst/mxf/mxfdemux.h +++ b/gst/mxf/mxfdemux.h @@ -68,6 +68,7 @@ struct _GstMXFDemux MXFPrimerPack primer; GArray *partition_index; + GArray *index_table; /* Structural metadata */ gboolean update_metadata; diff --git a/gst/mxf/mxfparse.c b/gst/mxf/mxfparse.c index aceebc97..ba6d9691 100644 --- a/gst/mxf/mxfparse.c +++ b/gst/mxf/mxfparse.c @@ -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 diff --git a/gst/mxf/mxfparse.h b/gst/mxf/mxfparse.h index 6cace267..54b4c0dd 100644 --- a/gst/mxf/mxfparse.h +++ b/gst/mxf/mxfparse.h @@ -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); diff --git a/gst/mxf/mxftypes.h b/gst/mxf/mxftypes.h index f6ca345e..4b2a6e7e 100644 --- a/gst/mxf/mxftypes.h +++ b/gst/mxf/mxftypes.h @@ -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) -- cgit v1.2.1