mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-23 15:48:23 +00:00
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.
This commit is contained in:
parent
6ff76898aa
commit
65587b80f5
6 changed files with 329 additions and 4 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ struct _GstMXFDemux
|
|||
MXFPrimerPack primer;
|
||||
|
||||
GArray *partition_index;
|
||||
GArray *index_table;
|
||||
|
||||
/* Structural metadata */
|
||||
gboolean update_metadata;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue