From a926db34ad8b983c95ef72ed9a5cb884c55430d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 27 Nov 2008 16:26:39 +0000 Subject: 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. --- ChangeLog | 14 ++++++++ gst/mxf/mxfdemux.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- gst/mxf/mxfdemux.h | 2 ++ gst/mxf/mxfparse.c | 40 +++++++++++++++++++++++ gst/mxf/mxfparse.h | 2 ++ gst/mxf/mxftypes.h | 6 ++++ 6 files changed, 156 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3bd1573c..c242ee44 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-11-27 Sebastian Dröge + + * 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 * gst/mxf/Makefile.am: diff --git a/gst/mxf/mxfdemux.c b/gst/mxf/mxfdemux.c index 0098951e..07151b5e 100644 --- a/gst/mxf/mxfdemux.c +++ b/gst/mxf/mxfdemux.c @@ -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); diff --git a/gst/mxf/mxfdemux.h b/gst/mxf/mxfdemux.h index 83426d67..674e6c35 100644 --- a/gst/mxf/mxfdemux.h +++ b/gst/mxf/mxfdemux.h @@ -67,6 +67,8 @@ struct _GstMXFDemux MXFPartitionPack partition; MXFPrimerPack primer; + GArray *partition_index; + /* Structural metadata */ gboolean update_metadata; gboolean final_metadata; diff --git a/gst/mxf/mxfparse.c b/gst/mxf/mxfparse.c index 90fa6348..aceebc97 100644 --- a/gst/mxf/mxfparse.c +++ b/gst/mxf/mxfparse.c @@ -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 diff --git a/gst/mxf/mxfparse.h b/gst/mxf/mxfparse.h index 99295762..6cace267 100644 --- a/gst/mxf/mxfparse.h +++ b/gst/mxf/mxfparse.h @@ -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); diff --git a/gst/mxf/mxftypes.h b/gst/mxf/mxftypes.h index 6fd15fae..f6ca345e 100644 --- a/gst/mxf/mxftypes.h +++ b/gst/mxf/mxftypes.h @@ -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, -- cgit v1.2.1