gst/mxf/: Implement parsing of the random index pack, which provides a seek table (including body sid) to the start o...

Original commit message from CVS:
* gst/mxf/mxfdemux.c: (gst_mxf_demux_reset),
(gst_mxf_demux_handle_random_index_pack),
(gst_mxf_demux_pull_random_index_pack), (gst_mxf_demux_loop):
* gst/mxf/mxfdemux.h:
* gst/mxf/mxfparse.c: (mxf_random_index_pack_parse):
* gst/mxf/mxfparse.h:
* gst/mxf/mxftypes.h:
Implement parsing of the random index pack, which provides a seek
table (including body sid) to the start of partition packs.
Later this will be used for reading all index table segments of
the complete file efficiently.
This commit is contained in:
Sebastian Dröge 2008-11-27 16:26:39 +00:00
parent 9e6654352e
commit a926db34ad
6 changed files with 156 additions and 3 deletions

View file

@ -1,3 +1,17 @@
2008-11-27 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* gst/mxf/mxfdemux.c: (gst_mxf_demux_reset),
(gst_mxf_demux_handle_random_index_pack),
(gst_mxf_demux_pull_random_index_pack), (gst_mxf_demux_loop):
* gst/mxf/mxfdemux.h:
* gst/mxf/mxfparse.c: (mxf_random_index_pack_parse):
* gst/mxf/mxfparse.h:
* gst/mxf/mxftypes.h:
Implement parsing of the random index pack, which provides a seek
table (including body sid) to the start of partition packs.
Later this will be used for reading all index table segments of
the complete file efficiently.
2008-11-27 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* gst/mxf/Makefile.am:

View file

@ -389,6 +389,11 @@ gst_mxf_demux_reset (GstMXFDemux * demux)
demux->src = NULL;
}
if (demux->partition_index) {
g_array_free (demux->partition_index, TRUE);
demux->partition_index = NULL;
}
gst_mxf_demux_reset_mxf_state (demux);
gst_mxf_demux_reset_metadata (demux);
}
@ -1275,8 +1280,9 @@ 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;
}
@ -2136,7 +2142,17 @@ gst_mxf_demux_handle_random_index_pack (GstMXFDemux * demux, const MXFUL * key,
"Handling random index pack of size %u at offset %"
G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer), demux->offset);
/* TODO: Parse this */
if (demux->partition_index) {
GST_DEBUG_OBJECT (demux, "Already parsed random index pack");
return GST_FLOW_OK;
}
if (!mxf_random_index_pack_parse (key, GST_BUFFER_DATA (buffer),
GST_BUFFER_SIZE (buffer), &demux->partition_index)) {
GST_ERROR_OBJECT (demux, "Parsing random index pack failed");
return GST_FLOW_ERROR;
}
return GST_FLOW_OK;
}
@ -2235,6 +2251,74 @@ beach:
return ret;
}
void
gst_mxf_demux_pull_random_index_pack (GstMXFDemux * demux)
{
GstBuffer *buffer;
GstFlowReturn ret;
gint64 filesize = -1;
GstFormat fmt = GST_FORMAT_BYTES;
guint32 pack_size;
MXFUL key;
if (!gst_pad_query_peer_duration (demux->sinkpad, &fmt, &filesize) ||
fmt != GST_FORMAT_BYTES || filesize == -1) {
GST_DEBUG_OBJECT (demux, "Can't query upstream size");
return;
}
g_assert (filesize > 4);
if ((ret =
gst_mxf_demux_pull_range (demux, filesize - 4, 4,
&buffer)) != GST_FLOW_OK) {
GST_DEBUG_OBJECT (demux, "Failed pulling last 4 bytes");
return;
}
pack_size = GST_READ_UINT32_BE (GST_BUFFER_DATA (buffer));
gst_buffer_unref (buffer);
if (pack_size < 20) {
GST_DEBUG_OBJECT (demux, "Too small pack size");
return;
} else if (pack_size > filesize - 20) {
GST_DEBUG_OBJECT (demux, "Too large pack size");
return;
}
if ((ret =
gst_mxf_demux_pull_range (demux, filesize - pack_size, 16,
&buffer)) != GST_FLOW_OK) {
GST_DEBUG_OBJECT (demux, "Failed pulling random index pack key");
return;
}
memcpy (&key, GST_BUFFER_DATA (buffer), 16);
gst_buffer_unref (buffer);
if (!mxf_is_random_index_pack (&key)) {
GST_DEBUG_OBJECT (demux, "No random index pack");
return;
}
if ((ret =
gst_mxf_demux_pull_klv_packet (demux, filesize - pack_size, &key,
&buffer, NULL)) != GST_FLOW_OK) {
GST_DEBUG_OBJECT (demux, "Failed pulling random index pack");
return;
}
gst_mxf_demux_handle_random_index_pack (demux, &key, buffer);
gst_buffer_unref (buffer);
if (!demux->partition_index)
demux->partition_index =
g_array_new (FALSE, FALSE, sizeof (MXFRandomIndexPackEntry));
}
static void
gst_mxf_demux_parse_footer_metadata (GstMXFDemux * demux)
{
@ -2521,6 +2605,11 @@ gst_mxf_demux_loop (GstPad * pad)
goto pause;
}
/* First of all pull&parse the random index pack at EOF */
if (!demux->partition_index) {
gst_mxf_demux_pull_random_index_pack (demux);
}
/* Now actually do something */
ret = gst_mxf_demux_pull_and_handle_klv_packet (demux);

View file

@ -67,6 +67,8 @@ struct _GstMXFDemux
MXFPartitionPack partition;
MXFPrimerPack primer;
GArray *partition_index;
/* Structural metadata */
gboolean update_metadata;
gboolean final_metadata;

View file

@ -556,6 +556,46 @@ mxf_partition_pack_reset (MXFPartitionPack * pack)
memset (pack, 0, sizeof (MXFPartitionPack));
}
/* SMPTE 377M 11.1 */
gboolean
mxf_random_index_pack_parse (const MXFUL * key, const guint8 * data, guint size,
GArray ** array)
{
guint len, i;
MXFRandomIndexPackEntry entry;
g_return_val_if_fail (data != NULL, FALSE);
g_return_val_if_fail (array != NULL, FALSE);
if (size < 4)
return FALSE;
if ((size - 4) % 12 != 0)
return FALSE;
GST_DEBUG ("Parsing random index pack:");
len = (size - 4) / 12;
GST_DEBUG (" number of entries = %u", len);
*array =
g_array_sized_new (FALSE, FALSE, sizeof (MXFRandomIndexPackEntry), len);
for (i = 0; i < len; i++) {
entry.body_sid = GST_READ_UINT32_BE (data);
entry.offset = GST_READ_UINT64_BE (data + 4);
data += 12;
GST_DEBUG (" entry %u = body sid %u at offset %" G_GUINT64_FORMAT, i,
entry.body_sid, entry.offset);
g_array_append_val (*array, entry);
}
return TRUE;
}
/* SMPTE 377M 8.2 Table 1 and 2 */
static void

View file

@ -77,6 +77,8 @@ void mxf_partition_pack_reset (MXFPartitionPack *pack);
gboolean mxf_primer_pack_parse (const MXFUL *key, MXFPrimerPack *pack, const guint8 *data, guint size);
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_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);

View file

@ -63,6 +63,12 @@ typedef struct {
guint8 *data;
} MXFLocalTag;
/* SMPTE 377M 11.1 */
typedef struct {
guint32 body_sid;
guint64 offset;
} MXFRandomIndexPackEntry;
typedef enum {
MXF_PARTITION_PACK_HEADER,
MXF_PARTITION_PACK_BODY,