Store MXF metadata in a hash table, keyed by UID

Store the MXF metadata in a hash table, keyed by the
instance UID. This simplifies resolval of the metadata
and makes looping over all metadata sets unnecessary
in most cases.

Additionally parse metadata always. If we already have
a metadata set with the same UID replace it only if
the new metadata set is from a later offset. This
fixes metadata parsing of files where following partitions
don't have a complete copy of the previous metadata.
This commit is contained in:
Sebastian Dröge 2009-01-22 11:47:48 +01:00
parent 52028f2e11
commit 716ce72e46
7 changed files with 802 additions and 818 deletions

View file

@ -216,17 +216,10 @@ gst_mxf_demux_reset_mxf_state (GstMXFDemux * demux)
}
static void
gst_mxf_demux_reset_metadata (GstMXFDemux * demux)
gst_mxf_demux_reset_track_metadata (GstMXFDemux *demux)
{
guint i;
GST_DEBUG_OBJECT (demux, "Resetting metadata");
demux->update_metadata = TRUE;
demux->metadata_resolved = FALSE;
demux->current_package = NULL;
if (demux->src) {
for (i = 0; i < demux->src->len; i++) {
GstMXFDemuxPad *pad = g_ptr_array_index (demux->src, i);
@ -241,19 +234,24 @@ gst_mxf_demux_reset_metadata (GstMXFDemux * demux)
pad->source_package = NULL;
}
}
}
static void
gst_mxf_demux_reset_metadata (GstMXFDemux * demux)
{
GST_DEBUG_OBJECT (demux, "Resetting metadata");
demux->update_metadata = TRUE;
demux->metadata_resolved = FALSE;
gst_mxf_demux_reset_track_metadata (demux);
demux->current_package = NULL;
demux->preface = NULL;
if (demux->metadata) {
guint i;
for (i = 0; i < demux->metadata->len; i++) {
GstMiniObject *o = g_ptr_array_index (demux->metadata, i);
if (o)
gst_mini_object_unref (o);
}
g_ptr_array_free (demux->metadata, TRUE);
g_hash_table_destroy (demux->metadata);
demux->metadata = NULL;
}
}
@ -476,8 +474,9 @@ gst_mxf_demux_handle_primer_pack (GstMXFDemux * demux, const MXFUL * key,
static GstFlowReturn
gst_mxf_demux_handle_header_metadata_resolve_references (GstMXFDemux * demux)
{
guint i;
GstFlowReturn ret = GST_FLOW_OK;
GHashTableIter iter;
MXFMetadataBase *m = NULL;
GST_DEBUG_OBJECT (demux, "Resolve metadata references");
demux->update_metadata = FALSE;
@ -487,17 +486,16 @@ gst_mxf_demux_handle_header_metadata_resolve_references (GstMXFDemux * demux)
return GST_FLOW_ERROR;
}
/* Append NULL terminator */
g_ptr_array_add (demux->metadata, NULL);
g_hash_table_iter_init (&iter, demux->metadata);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) & m)) {
m->resolved = MXF_METADATA_BASE_RESOLVE_STATE_NONE;
}
for (i = 0; i < demux->metadata->len - 1; i++) {
MXFMetadataBase *m =
MXF_METADATA_BASE (g_ptr_array_index (demux->metadata, i));
g_hash_table_iter_init (&iter, demux->metadata);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) & m)) {
gboolean resolved;
resolved =
mxf_metadata_base_resolve (m,
(MXFMetadataBase **) demux->metadata->pdata);
resolved = mxf_metadata_base_resolve (m, demux->metadata);
/* Resolving can fail for anything but the preface, as the preface
* will resolve everything required */
@ -865,7 +863,7 @@ gst_mxf_demux_handle_metadata (GstMXFDemux * demux, const MXFUL * key,
GstBuffer * buffer)
{
guint16 type;
MXFMetadata *metadata = NULL;
MXFMetadata *metadata = NULL, *old = NULL;
GstFlowReturn ret = GST_FLOW_OK;
type = GST_READ_UINT16_BE (key->u + 13);
@ -886,44 +884,43 @@ gst_mxf_demux_handle_metadata (GstMXFDemux * demux, const MXFUL * key,
}
metadata =
mxf_metadata_new (type, &demux->primer, GST_BUFFER_DATA (buffer),
GST_BUFFER_SIZE (buffer));
if (metadata && !MXF_IS_METADATA_PREFACE (metadata)
&& !demux->update_metadata) {
GST_DEBUG_OBJECT (demux,
"Skipping parsing of metadata because it's older than what we have");
gst_mini_object_unref ((GstMiniObject *) metadata);
return GST_FLOW_OK;
}
mxf_metadata_new (type, &demux->primer, demux->offset,
GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
if (!metadata) {
GST_ERROR_OBJECT (demux, "Parsing metadata failed");
return GST_FLOW_ERROR;
}
if (MXF_IS_METADATA_PREFACE (metadata)) {
MXFMetadataPreface *preface = MXF_METADATA_PREFACE (metadata);
if (!demux->metadata)
demux->metadata = mxf_metadata_hash_table_new ();
old =
g_hash_table_lookup (demux->metadata,
&MXF_METADATA_BASE (metadata)->instance_uid);
if (old
&& MXF_METADATA_BASE (old)->offset >=
MXF_METADATA_BASE (metadata)->offset) {
#ifndef GST_DISABLE_GST_DEBUG
gchar str[48];
#endif
if (!demux->preface
|| (!mxf_timestamp_is_unknown (&preface->last_modified_date)
&& mxf_timestamp_compare (&demux->preface->last_modified_date,
&preface->last_modified_date) < 0)) {
GST_DEBUG_OBJECT (demux,
"Timestamp of new preface is newer than old, updating metadata");
gst_mxf_demux_reset_metadata (demux);
demux->preface = preface;
} else {
GST_DEBUG_OBJECT (demux, "Preface is older than already parsed preface");
gst_mini_object_unref ((GstMiniObject *) metadata);
"Metadata with instance uid %s already exists and is newer",
mxf_ul_to_string (&MXF_METADATA_BASE (metadata)->instance_uid, str));
gst_mini_object_unref (GST_MINI_OBJECT (metadata));
return GST_FLOW_OK;
}
if (MXF_IS_METADATA_PREFACE (metadata)) {
demux->preface = MXF_METADATA_PREFACE (metadata);
}
if (!demux->metadata)
demux->metadata = g_ptr_array_new ();
demux->update_metadata = TRUE;
gst_mxf_demux_reset_track_metadata (demux);
g_ptr_array_add (demux->metadata, metadata);
g_hash_table_replace (demux->metadata,
&MXF_METADATA_BASE (metadata)->instance_uid, metadata);
return ret;
}
@ -935,7 +932,7 @@ gst_mxf_demux_handle_descriptive_metadata (GstMXFDemux * demux,
guint32 type;
guint8 scheme;
GstFlowReturn ret = GST_FLOW_OK;
MXFDescriptiveMetadata *m = NULL;
MXFDescriptiveMetadata *m = NULL, *old = NULL;
scheme = GST_READ_UINT8 (key->u + 12);
type = GST_READ_UINT24_BE (key->u + 13);
@ -955,14 +952,7 @@ gst_mxf_demux_handle_descriptive_metadata (GstMXFDemux * demux,
return GST_FLOW_ERROR;
}
if (!demux->update_metadata) {
GST_DEBUG_OBJECT (demux,
"Skipping parsing of metadata because it's older than what we have");
return GST_FLOW_OK;
}
m = mxf_descriptive_metadata_new (scheme, type, &demux->primer,
m = mxf_descriptive_metadata_new (scheme, type, &demux->primer, demux->offset,
GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
if (!m) {
@ -973,10 +963,28 @@ gst_mxf_demux_handle_descriptive_metadata (GstMXFDemux * demux,
}
if (!demux->metadata)
demux->metadata = g_ptr_array_new ();
demux->metadata = mxf_metadata_hash_table_new ();
g_ptr_array_add (demux->metadata, m);
old =
g_hash_table_lookup (demux->metadata,
&MXF_METADATA_BASE (m)->instance_uid);
if (old && MXF_METADATA_BASE (old)->offset >= MXF_METADATA_BASE (m)->offset) {
#ifndef GST_DISABLE_GST_DEBUG
gchar str[48];
#endif
GST_DEBUG_OBJECT (demux,
"Metadata with instance uid %s already exists and is newer",
mxf_ul_to_string (&MXF_METADATA_BASE (m)->instance_uid, str));
gst_mini_object_unref (GST_MINI_OBJECT (m));
return GST_FLOW_OK;
}
demux->update_metadata = TRUE;
gst_mxf_demux_reset_track_metadata (demux);
g_hash_table_replace (demux->metadata, &MXF_METADATA_BASE (m)->instance_uid,
m);
return ret;
}
@ -1502,7 +1510,7 @@ gst_mxf_demux_parse_footer_metadata (GstMXFDemux * demux)
{
MXFPartitionPack partition;
MXFPrimerPack primer;
guint64 offset, old_offset = demux->offset;
guint64 old_offset = demux->offset;
MXFUL key;
GstBuffer *buffer = NULL;
guint read = 0;
@ -1516,21 +1524,23 @@ gst_mxf_demux_parse_footer_metadata (GstMXFDemux * demux)
gst_mxf_demux_reset_metadata (demux);
if (demux->footer_partition_pack_offset != 0) {
offset =
demux->offset =
demux->header_partition_pack_offset +
demux->footer_partition_pack_offset;
} else {
MXFRandomIndexPackEntry *entry =
&g_array_index (demux->partition_index, MXFRandomIndexPackEntry,
demux->partition_index->len - 1);
offset = entry->offset;
demux->offset = entry->offset;
}
next_try:
mxf_partition_pack_reset (&demux->partition);
mxf_primer_pack_reset (&demux->primer);
ret = gst_mxf_demux_pull_klv_packet (demux, offset, &key, &buffer, &read);
ret =
gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buffer,
&read);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto out;
@ -1541,7 +1551,7 @@ next_try:
GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)))
goto out;
offset += read;
demux->offset += read;
gst_buffer_unref (buffer);
buffer = NULL;
@ -1550,44 +1560,46 @@ next_try:
|| demux->partition.this_partition == 0)
goto out;
offset =
demux->offset =
demux->header_partition_pack_offset + demux->partition.this_partition -
demux->partition.prev_partition;
goto next_try;
}
while (TRUE) {
ret = gst_mxf_demux_pull_klv_packet (demux, offset, &key, &buffer, &read);
ret =
gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buffer,
&read);
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
offset =
demux->offset =
demux->header_partition_pack_offset +
demux->partition.this_partition - demux->partition.prev_partition;
goto next_try;
}
if (mxf_is_fill (&key)) {
offset += read;
demux->offset += read;
gst_buffer_unref (buffer);
buffer = NULL;
} else if (mxf_is_primer_pack (&key)) {
if (!mxf_primer_pack_parse (&key, &demux->primer,
GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
offset += read;
demux->offset += read;
gst_buffer_unref (buffer);
buffer = NULL;
offset =
demux->offset =
demux->header_partition_pack_offset +
demux->partition.this_partition - demux->partition.prev_partition;
goto next_try;
}
offset += read;
demux->offset += read;
gst_buffer_unref (buffer);
buffer = NULL;
break;
} else {
gst_buffer_unref (buffer);
buffer = NULL;
offset =
demux->offset =
demux->header_partition_pack_offset +
demux->partition.this_partition - demux->partition.prev_partition;
goto next_try;
@ -1596,9 +1608,11 @@ next_try:
/* parse metadata */
while (TRUE) {
ret = gst_mxf_demux_pull_klv_packet (demux, offset, &key, &buffer, &read);
ret =
gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buffer,
&read);
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
offset =
demux->offset =
demux->header_partition_pack_offset +
demux->partition.this_partition - demux->partition.prev_partition;
goto next_try;
@ -1606,19 +1620,24 @@ next_try:
if (mxf_is_metadata (&key)) {
ret = gst_mxf_demux_handle_metadata (demux, &key, buffer);
offset += read;
demux->offset += read;
gst_buffer_unref (buffer);
buffer = NULL;
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
gst_mxf_demux_reset_metadata (demux);
offset =
demux->offset =
demux->header_partition_pack_offset +
demux->partition.this_partition - demux->partition.prev_partition;
goto next_try;
}
} else if (mxf_is_descriptive_metadata (&key) || mxf_is_fill (&key)) {
offset += read;
} else if (mxf_is_descriptive_metadata (&key)) {
ret = gst_mxf_demux_handle_descriptive_metadata (demux, &key, buffer);
demux->offset += read;
gst_buffer_unref (buffer);
buffer = NULL;
} else if (mxf_is_fill (&key)) {
demux->offset += read;
gst_buffer_unref (buffer);
buffer = NULL;
} else {
@ -1632,7 +1651,7 @@ next_try:
GST_FLOW_OK
|| gst_mxf_demux_handle_header_metadata_update_streams (demux) !=
GST_FLOW_OK) {
offset =
demux->offset =
demux->header_partition_pack_offset + demux->partition.this_partition -
demux->partition.prev_partition;
goto next_try;

View file

@ -81,7 +81,7 @@ struct _GstMXFDemux
gboolean metadata_resolved;
MXFMetadataPreface *preface;
GPtrArray *metadata;
GHashTable *metadata;
MXFUMID current_package_uid;
MXFMetadataGenericPackage *current_package;

File diff suppressed because it is too large Load diff

View file

@ -56,7 +56,7 @@ mxf_metadata_base_handle_tag (MXFMetadataBase * self, MXFPrimerPack * primer,
static gboolean
mxf_metadata_base_resolve_default (MXFMetadataBase * self,
MXFMetadataBase ** metadata)
GHashTable * metadata)
{
return TRUE;
}
@ -104,7 +104,7 @@ mxf_metadata_base_parse (MXFMetadataBase * self, MXFPrimerPack * primer,
}
gboolean
mxf_metadata_base_resolve (MXFMetadataBase * self, MXFMetadataBase ** metadata)
mxf_metadata_base_resolve (MXFMetadataBase * self, GHashTable * metadata)
{
MXFMetadataBaseClass *klass;
gboolean ret = TRUE;
@ -262,8 +262,8 @@ mxf_metadata_register (guint16 type_id, GType type)
}
MXFMetadata *
mxf_metadata_new (guint16 type, MXFPrimerPack * primer, const guint8 * data,
guint size)
mxf_metadata_new (guint16 type, MXFPrimerPack * primer, guint64 offset,
const guint8 * data, guint size)
{
GSList *l;
GType t = G_TYPE_INVALID;
@ -289,6 +289,10 @@ mxf_metadata_new (guint16 type, MXFPrimerPack * primer, const guint8 * data,
t = MXF_TYPE_METADATA;
}
GST_DEBUG ("Metadata type 0x%06x is handled by type %s", type,
g_type_name (t));
ret = (MXFMetadata *) g_type_create_instance (t);
if (!mxf_metadata_base_parse (MXF_METADATA_BASE (ret), primer, data, size)) {
GST_ERROR ("Parsing metadata failed");
@ -297,6 +301,7 @@ mxf_metadata_new (guint16 type, MXFPrimerPack * primer, const guint8 * data,
}
ret->type = type;
ret->parent.offset = offset;
return ret;
}
@ -445,48 +450,49 @@ error:
}
static gboolean
mxf_metadata_preface_resolve (MXFMetadataBase * m, MXFMetadataBase ** metadata)
mxf_metadata_preface_resolve (MXFMetadataBase * m, GHashTable * metadata)
{
MXFMetadataPreface *self = MXF_METADATA_PREFACE (m);
MXFMetadataBase **p = metadata, *current;
MXFMetadataBase *current = NULL;
guint i;
while (*p && (self->primary_package == NULL || self->content_storage == NULL)) {
current = *p;
if (MXF_IS_METADATA_GENERIC_PACKAGE (current) &&
mxf_ul_is_equal (&self->primary_package_uid, &current->instance_uid)) {
if (mxf_metadata_base_resolve (current, metadata))
current = g_hash_table_lookup (metadata, &self->primary_package_uid);
if (!current || !MXF_IS_METADATA_GENERIC_PACKAGE (current)) {
GST_ERROR ("Primary package not found");
} else {
if (mxf_metadata_base_resolve (current, metadata)) {
self->primary_package = MXF_METADATA_GENERIC_PACKAGE (current);
} else if (MXF_IS_METADATA_CONTENT_STORAGE (current) &&
mxf_ul_is_equal (&self->content_storage_uid, &current->instance_uid)) {
if (mxf_metadata_base_resolve (current, metadata))
self->content_storage = MXF_METADATA_CONTENT_STORAGE (current);
}
p++;
}
current = NULL;
current = g_hash_table_lookup (metadata, &self->content_storage_uid);
if (!current || !MXF_IS_METADATA_CONTENT_STORAGE (current)) {
GST_ERROR ("Content storage not found");
return FALSE;
} else {
if (mxf_metadata_base_resolve (current, metadata)) {
self->content_storage = MXF_METADATA_CONTENT_STORAGE (current);
} else {
GST_ERROR ("Couldn't resolve content storage");
return FALSE;
}
}
current = NULL;
if (self->identifications)
memset (self->identifications, 0,
sizeof (gpointer) * self->n_identifications);
else
self->identifications =
g_new0 (MXFMetadataIdentification *, self->n_identifications);
for (i = 0; i < self->n_identifications; i++) {
p = metadata;
while (*p) {
current = *p;
if (MXF_IS_METADATA_IDENTIFICATION (current) &&
mxf_ul_is_equal (&self->identifications_uids[i],
&current->instance_uid)) {
if (mxf_metadata_base_resolve (current, metadata))
current = g_hash_table_lookup (metadata, &self->identifications_uids[i]);
if (current && MXF_IS_METADATA_IDENTIFICATION (current)) {
if (mxf_metadata_base_resolve (m, metadata))
self->identifications[i] = MXF_METADATA_IDENTIFICATION (current);
break;
}
p++;
}
}
if (!self->content_storage) {
GST_ERROR ("Couldn't resolve content storage");
return FALSE;
current = NULL;
}
return
@ -727,49 +733,53 @@ error:
static gboolean
mxf_metadata_content_storage_resolve (MXFMetadataBase * m,
MXFMetadataBase ** metadata)
GHashTable * metadata)
{
MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (m);
MXFMetadataBase **p = metadata, *current;
MXFMetadataBase *current = NULL;
guint i;
gboolean have_package = FALSE;
gboolean have_ecd = FALSE;
if (self->packages)
memset (self->packages, 0, sizeof (gpointer) * self->n_packages);
else
self->packages = g_new0 (MXFMetadataGenericPackage *, self->n_packages);
for (i = 0; i < self->n_packages; i++) {
p = metadata;
while (*p) {
current = *p;
if (MXF_IS_METADATA_GENERIC_PACKAGE (current) &&
mxf_ul_is_equal (&current->instance_uid, &self->packages_uids[i])) {
current = g_hash_table_lookup (metadata, &self->packages_uids[i]);
if (current && MXF_IS_METADATA_GENERIC_PACKAGE (current)) {
if (mxf_metadata_base_resolve (current, metadata)) {
self->packages[i] = MXF_METADATA_GENERIC_PACKAGE (current);
have_package = TRUE;
} else {
GST_ERROR ("Couldn't resolve package");
}
break;
}
p++;
} else {
GST_ERROR ("Package not found");
}
}
if (self->essence_container_data)
memset (self->essence_container_data, 0,
sizeof (gpointer) * self->n_essence_container_data);
else
self->essence_container_data =
g_new0 (MXFMetadataEssenceContainerData *,
self->n_essence_container_data);
for (i = 0; i < self->n_essence_container_data; i++) {
p = metadata;
while (*p) {
current = *p;
if (MXF_IS_METADATA_ESSENCE_CONTAINER_DATA (current) &&
mxf_ul_is_equal (&current->instance_uid,
&self->essence_container_data_uids[i])) {
current =
g_hash_table_lookup (metadata, &self->essence_container_data_uids[i]);
if (current && MXF_IS_METADATA_ESSENCE_CONTAINER_DATA (current)) {
if (mxf_metadata_base_resolve (current, metadata)) {
self->essence_container_data[i] =
MXF_METADATA_ESSENCE_CONTAINER_DATA (current);
have_ecd = TRUE;
} else {
GST_ERROR ("Couldn't resolve essence container data");
}
break;
}
p++;
} else {
GST_ERROR ("Essence container data not found");
}
}
@ -858,15 +868,16 @@ error:
static gboolean
mxf_metadata_essence_container_data_resolve (MXFMetadataBase * m,
MXFMetadataBase ** metadata)
GHashTable * metadata)
{
MXFMetadataEssenceContainerData *self =
MXF_METADATA_ESSENCE_CONTAINER_DATA (m);
MXFMetadataBase **p = metadata, *current;
MXFMetadataBase *current = NULL;
GHashTableIter iter;
while (*p) {
current = *p;
g_hash_table_iter_init (&iter, metadata);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) & current)) {
if (MXF_IS_METADATA_SOURCE_PACKAGE (current)) {
MXFMetadataSourcePackage *package = MXF_METADATA_SOURCE_PACKAGE (current);
@ -878,7 +889,6 @@ mxf_metadata_essence_container_data_resolve (MXFMetadataBase * m,
break;
}
}
p++;
}
if (!self->linked_package) {
@ -1013,27 +1023,25 @@ error:
static gboolean
mxf_metadata_generic_package_resolve (MXFMetadataBase * m,
MXFMetadataBase ** metadata)
GHashTable * metadata)
{
MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (m);
MXFMetadataBase **p, *current;
MXFMetadataBase *current = NULL;
guint i;
gboolean have_track = FALSE;
if (self->tracks)
memset (self->tracks, 0, sizeof (gpointer) * self->n_tracks);
else
self->tracks = g_new0 (MXFMetadataTrack *, self->n_tracks);
for (i = 0; i < self->n_tracks; i++) {
p = metadata;
while (*p) {
current = *p;
if (MXF_IS_METADATA_TRACK (current)) {
current = g_hash_table_lookup (metadata, &self->tracks_uids[i]);
if (current && MXF_IS_METADATA_TRACK (current)) {
if (mxf_metadata_base_resolve (current, metadata)) {
MXFMetadataTrack *track = MXF_METADATA_TRACK (current);
if (mxf_ul_is_equal (&current->instance_uid, &self->tracks_uids[i])) {
if (mxf_metadata_base_resolve (current, metadata)) {
self->tracks[i] = track;
have_track = TRUE;
if ((track->type & 0xf0) == 0x10)
self->n_timecode_tracks++;
else if ((track->type & 0xf0) == 0x20)
@ -1042,13 +1050,11 @@ mxf_metadata_generic_package_resolve (MXFMetadataBase * m,
self->n_essence_tracks++;
else if ((track->type & 0xf0) == 0x40)
self->n_other_tracks++;
} else {
GST_ERROR ("Track couldn't be resolved");
}
break;
}
}
p++;
} else {
GST_ERROR ("Track not found");
}
}
@ -1084,7 +1090,7 @@ G_DEFINE_TYPE (MXFMetadataMaterialPackage, mxf_metadata_material_package,
static gboolean
mxf_metadata_material_package_resolve (MXFMetadataBase * m,
MXFMetadataBase ** metadata)
GHashTable * metadata)
{
gboolean ret =
MXF_METADATA_BASE_CLASS
@ -1194,12 +1200,11 @@ error:
}
static gboolean
mxf_metadata_source_package_resolve (MXFMetadataBase * m,
MXFMetadataBase ** metadata)
mxf_metadata_source_package_resolve (MXFMetadataBase * m, GHashTable * metadata)
{
MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (m);
MXFMetadataGenericPackage *package = MXF_METADATA_GENERIC_PACKAGE (m);
MXFMetadataBase **p = metadata, *current;
MXFMetadataBase *current = NULL;
guint i, j;
gboolean ret;
MXFMetadataGenericDescriptor *d = NULL;
@ -1209,18 +1214,15 @@ mxf_metadata_source_package_resolve (MXFMetadataBase * m,
MXF_METADATA_BASE_CLASS
(mxf_metadata_source_package_parent_class)->resolve (m, metadata);
while (*p) {
current = *p;
if (MXF_IS_METADATA_GENERIC_DESCRIPTOR (current) &&
mxf_ul_is_equal (&current->instance_uid, &self->descriptors_uid)) {
current = g_hash_table_lookup (metadata, &self->descriptors_uid);
if (current && MXF_IS_METADATA_GENERIC_DESCRIPTOR (current)) {
d = MXF_METADATA_GENERIC_DESCRIPTOR (current);
break;
}
p++;
} else {
GST_ERROR ("Descriptor not found");
return FALSE;
}
if (!d || !mxf_metadata_base_resolve (MXF_METADATA_BASE (d), metadata)) {
if (!mxf_metadata_base_resolve (MXF_METADATA_BASE (d), metadata)) {
GST_ERROR ("Couldn't resolve descriptor");
return FALSE;
}
@ -1230,6 +1232,8 @@ mxf_metadata_source_package_resolve (MXFMetadataBase * m,
if (m->sub_descriptors) {
self->n_descriptors = m->n_sub_descriptors + 1;
if (self->descriptors)
g_free (self->descriptors);
self->descriptors =
g_new0 (MXFMetadataGenericDescriptor *, self->n_descriptors);
@ -1241,6 +1245,8 @@ mxf_metadata_source_package_resolve (MXFMetadataBase * m,
}
} else {
self->n_descriptors = 1;
if (self->descriptors)
g_free (self->descriptors);
self->descriptors = g_new0 (MXFMetadataGenericDescriptor *, 1);
self->descriptors[0] = d;
}
@ -1264,6 +1270,8 @@ mxf_metadata_source_package_resolve (MXFMetadataBase * m,
n_descriptor++;
}
if (package->tracks[i]->descriptor)
g_free (package->tracks[i]->descriptor);
package->tracks[i]->descriptor =
g_new0 (MXFMetadataFileDescriptor *, n_descriptor);
package->tracks[i]->n_descriptor = n_descriptor;
@ -1372,28 +1380,24 @@ error:
}
static gboolean
mxf_metadata_track_resolve (MXFMetadataBase * m, MXFMetadataBase ** metadata)
mxf_metadata_track_resolve (MXFMetadataBase * m, GHashTable * metadata)
{
MXFMetadataTrack *self = MXF_METADATA_TRACK (m);
MXFMetadataBase **p = metadata, *current;
MXFMetadataBase *current = NULL;
guint i;
while (*p) {
current = *p;
if (MXF_IS_METADATA_SEQUENCE (current) &&
mxf_ul_is_equal (&current->instance_uid, &self->sequence_uid)) {
current = g_hash_table_lookup (metadata, &self->sequence_uid);
if (current && MXF_IS_METADATA_SEQUENCE (current)) {
if (mxf_metadata_base_resolve (current, metadata)) {
self->sequence = MXF_METADATA_SEQUENCE (current);
break;
}
p++;
}
if (!self->sequence
|| !mxf_metadata_base_resolve (MXF_METADATA_BASE (self->sequence),
metadata)) {
} else {
GST_ERROR ("Couldn't resolve sequence");
return FALSE;
}
} else {
GST_ERROR ("Couldn't find sequence");
return FALSE;
}
self->type =
mxf_metadata_track_identifier_parse (&self->sequence->data_definition);
@ -1674,39 +1678,35 @@ error:
}
static gboolean
mxf_metadata_sequence_resolve (MXFMetadataBase * m, MXFMetadataBase ** metadata)
mxf_metadata_sequence_resolve (MXFMetadataBase * m, GHashTable * metadata)
{
MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (m);
MXFMetadataBase **p, *current;
MXFMetadataBase *current = NULL;
guint i;
guint have_sc = 0;
if (self->structural_components)
memset (self->structural_components, 0,
sizeof (gpointer) * self->n_structural_components);
else
self->structural_components =
g_new0 (MXFMetadataStructuralComponent *, self->n_structural_components);
g_new0 (MXFMetadataStructuralComponent *,
self->n_structural_components);
for (i = 0; i < self->n_structural_components; i++) {
p = metadata;
while (*p) {
current = *p;
if (MXF_IS_METADATA_STRUCTURAL_COMPONENT (current)
&& mxf_ul_is_equal (&current->instance_uid,
&self->structural_components_uids[i])) {
current =
g_hash_table_lookup (metadata, &self->structural_components_uids[i]);
if (current && MXF_IS_METADATA_STRUCTURAL_COMPONENT (current)) {
if (mxf_metadata_base_resolve (current, metadata)) {
self->structural_components[i] =
MXF_METADATA_STRUCTURAL_COMPONENT (current);
have_sc++;
break;
}
}
p++;
}
}
if (have_sc != self->n_structural_components) {
GST_ERROR ("Couldn't resolve all structural components");
} else {
GST_ERROR ("Couldn't resolve structural component");
return FALSE;
}
} else {
GST_ERROR ("Structural component not found");
return FALSE;
}
}
return
MXF_METADATA_BASE_CLASS (mxf_metadata_sequence_parent_class)->resolve (m,
@ -1913,15 +1913,15 @@ error:
}
static gboolean
mxf_metadata_source_clip_resolve (MXFMetadataBase * m,
MXFMetadataBase ** metadata)
mxf_metadata_source_clip_resolve (MXFMetadataBase * m, GHashTable * metadata)
{
MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (m);
MXFMetadataBase **p, *current;
MXFMetadataBase *current = NULL;
GHashTableIter iter;
p = metadata;
while (*p) {
current = *p;
g_hash_table_iter_init (&iter, metadata);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) & current)) {
if (MXF_IS_METADATA_SOURCE_PACKAGE (current)) {
MXFMetadataGenericPackage *p = MXF_METADATA_GENERIC_PACKAGE (current);
@ -1930,7 +1930,6 @@ mxf_metadata_source_clip_resolve (MXFMetadataBase * m,
break;
}
}
p++;
}
return
@ -2143,30 +2142,24 @@ error:
}
static gboolean
mxf_metadata_dm_segment_resolve (MXFMetadataBase * m,
MXFMetadataBase ** metadata)
mxf_metadata_dm_segment_resolve (MXFMetadataBase * m, GHashTable * metadata)
{
MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (m);
MXFMetadataBase **p = metadata, *current;
MXFMetadataBase *current = NULL;
while (*p) {
current = *p;
if (MXF_IS_DESCRIPTIVE_METADATA_FRAMEWORK (current)
&& mxf_ul_is_equal (&current->instance_uid, &self->dm_framework_uid)) {
current = g_hash_table_lookup (metadata, &self->dm_framework_uid);
if (current && MXF_IS_DESCRIPTIVE_METADATA_FRAMEWORK (current)) {
if (mxf_metadata_base_resolve (current, metadata)) {
self->dm_framework = MXF_DESCRIPTIVE_METADATA_FRAMEWORK (current);
}
break;
}
p++;
}
if (!self->dm_framework) {
} else {
GST_ERROR ("Couldn't resolve DM framework");
return FALSE;
}
} else {
GST_ERROR ("Couldn't find DM framework");
return FALSE;
}
return
MXF_METADATA_BASE_CLASS (mxf_metadata_dm_segment_parent_class)->resolve
@ -2257,28 +2250,28 @@ error:
static gboolean
mxf_metadata_generic_descriptor_resolve (MXFMetadataBase * m,
MXFMetadataBase ** metadata)
GHashTable * metadata)
{
MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (m);
MXFMetadataBase **p, *current;
MXFMetadataBase *current = NULL;
guint i;
gboolean have_locator = FALSE;
if (self->locators)
memset (self->locators, 0, sizeof (gpointer) * self->n_locators);
else
self->locators = g_new0 (MXFMetadataLocator *, self->n_locators);
for (i = 0; i < self->n_locators; i++) {
p = metadata;
while (*p) {
current = *p;
if (MXF_IS_METADATA_LOCATOR (current) &&
mxf_ul_is_equal (&current->instance_uid, &self->locators_uids[i])) {
current = g_hash_table_lookup (metadata, &self->locators_uids[i]);
if (current && MXF_IS_METADATA_LOCATOR (current)) {
if (mxf_metadata_base_resolve (current, metadata)) {
self->locators[i] = MXF_METADATA_LOCATOR (current);
have_locator = TRUE;
} else {
GST_ERROR ("Couldn't resolve locator");
}
break;
}
p++;
} else {
GST_ERROR ("Locator not found");
}
}
@ -3149,35 +3142,33 @@ error:
static gboolean
mxf_metadata_multiple_descriptor_resolve (MXFMetadataBase * m,
MXFMetadataBase ** metadata)
GHashTable * metadata)
{
MXFMetadataMultipleDescriptor *self = MXF_METADATA_MULTIPLE_DESCRIPTOR (m);
MXFMetadataBase **p, *current;
MXFMetadataBase *current = NULL;
guint i, have_subdescriptors = 0;
if (self->sub_descriptors)
memset (self->sub_descriptors, 0,
sizeof (gpointer) * self->n_sub_descriptors);
else
self->sub_descriptors =
g_new0 (MXFMetadataGenericDescriptor *, self->n_sub_descriptors);
for (i = 0; i < self->n_sub_descriptors; i++) {
p = metadata;
while (*p) {
current = *p;
if (MXF_IS_METADATA_GENERIC_DESCRIPTOR (current) &&
mxf_ul_is_equal (&current->instance_uid,
&self->sub_descriptors_uids[i])) {
current = g_hash_table_lookup (metadata, &self->sub_descriptors_uids[i]);
if (current && MXF_IS_METADATA_GENERIC_DESCRIPTOR (current)) {
if (mxf_metadata_base_resolve (current, metadata)) {
self->sub_descriptors[i] = MXF_METADATA_GENERIC_DESCRIPTOR (current);
have_subdescriptors++;
}
break;
}
p++;
}
}
if (have_subdescriptors != self->n_sub_descriptors) {
GST_ERROR ("Couldn't resolve all subdescriptors");
} else {
GST_ERROR ("Couldn't resolve descriptor");
return FALSE;
}
} else {
GST_ERROR ("Descriptor not found");
return FALSE;
}
}
return
MXF_METADATA_BASE_CLASS
@ -3358,7 +3349,7 @@ mxf_descriptive_metadata_register (guint8 scheme, GSList * sets)
MXFDescriptiveMetadata *
mxf_descriptive_metadata_new (guint8 scheme, guint32 type,
MXFPrimerPack * primer, const guint8 * data, guint size)
MXFPrimerPack * primer, guint64 offset, const guint8 * data, guint size)
{
GSList *l;
GType t = G_TYPE_INVALID;
@ -3400,6 +3391,9 @@ mxf_descriptive_metadata_new (guint8 scheme, guint32 type,
return NULL;
}
GST_DEBUG ("DM scheme 0x%02x type 0x%06x is handled by type %s", scheme, type,
g_type_name (t));
ret = (MXFDescriptiveMetadata *) g_type_create_instance (t);
if (!mxf_metadata_base_parse (MXF_METADATA_BASE (ret), primer, data, size)) {
GST_ERROR ("Parsing metadata failed");
@ -3408,6 +3402,7 @@ mxf_descriptive_metadata_new (guint8 scheme, guint32 type,
}
ret->type = type;
ret->parent.offset = offset;
return ret;
}
@ -3445,3 +3440,11 @@ mxf_descriptive_metadata_framework_get_type (void)
return (GType) type;
}
GHashTable *
mxf_metadata_hash_table_new (void)
{
return g_hash_table_new_full ((GHashFunc) mxf_ul_hash,
(GEqualFunc) mxf_ul_is_equal, (GDestroyNotify) NULL,
(GDestroyNotify) gst_mini_object_unref);
}

View file

@ -373,6 +373,8 @@ struct _MXFMetadataBase {
MXFUL instance_uid;
MXFUL generation_uid;
guint64 offset;
MXFMetadataBaseResolveState resolved;
GHashTable *other_tags;
@ -382,7 +384,7 @@ struct _MXFMetadataBaseClass {
GstMiniObjectClass parent;
gboolean (*handle_tag) (MXFMetadataBase *self, MXFPrimerPack *primer, guint16 tag, const guint8 *tag_data, guint tag_size);
gboolean (*resolve) (MXFMetadataBase *self, MXFMetadataBase **metadata);
gboolean (*resolve) (MXFMetadataBase *self, GHashTable *metadata);
};
struct _MXFMetadata {
@ -745,9 +747,9 @@ struct _MXFDescriptiveMetadataFrameworkInterface {
};
gboolean mxf_metadata_base_parse (MXFMetadataBase *self, MXFPrimerPack *primer, const guint8 *data, guint size);
gboolean mxf_metadata_base_resolve (MXFMetadataBase *self, MXFMetadataBase **metadata);
gboolean mxf_metadata_base_resolve (MXFMetadataBase *self, GHashTable *metadata);
MXFMetadata *mxf_metadata_new (guint16 type, MXFPrimerPack *primer, const guint8 *data, guint size);
MXFMetadata *mxf_metadata_new (guint16 type, MXFPrimerPack *primer, guint64 offset, const guint8 *data, guint size);
void mxf_metadata_register (guint16 type_id, GType type);
void mxf_metadata_init_types (void);
@ -757,6 +759,8 @@ void mxf_metadata_generic_picture_essence_descriptor_set_caps (MXFMetadataGeneri
void mxf_metadata_generic_sound_essence_descriptor_set_caps (MXFMetadataGenericSoundEssenceDescriptor * self, GstCaps * caps);
void mxf_descriptive_metadata_register (guint8 scheme, GSList *sets);
MXFDescriptiveMetadata * mxf_descriptive_metadata_new (guint8 scheme, guint32 type, MXFPrimerPack * primer, const guint8 * data, guint size);
MXFDescriptiveMetadata * mxf_descriptive_metadata_new (guint8 scheme, guint32 type, MXFPrimerPack * primer, guint64 offset, const guint8 * data, guint size);
GHashTable *mxf_metadata_hash_table_new (void);
#endif /* __MXF_METADATA_H__ */

View file

@ -215,6 +215,20 @@ mxf_ul_is_zero (const MXFUL * key)
return (memcmp (key, &key_zero, 16) == 0);
}
guint
mxf_ul_hash (const MXFUL * key)
{
guint32 ret = 0;
guint i;
for (i = 0; i < 4; i++)
ret ^=
(key->u[i * 4 + 0] << 24) | (key->u[i * 4 + 1] << 16) | (key->u[i * 4 +
2] << 8) | (key->u[i * 4 + 3] << 0);
return ret;
}
gchar *
mxf_ul_to_string (const MXFUL * key, gchar str[48])
{
@ -302,26 +316,6 @@ mxf_umid_from_string (const gchar * str, MXFUMID * umid)
return umid;
}
static guint
gst_mxf_ul_hash (const MXFUL * key)
{
guint32 ret = 0;
guint i;
for (i = 0; i < 4; i++)
ret ^=
(key->u[i * 4 + 0] << 24) | (key->u[i * 4 + 1] << 16) | (key->u[i * 4 +
2] << 8) | (key->u[i * 4 + 3] << 0);
return ret;
}
static gboolean
gst_mxf_ul_equal (const MXFUL * a, const MXFUL * b)
{
return (memcmp (a, b, 16) == 0);
}
gboolean
mxf_timestamp_parse (MXFTimestamp * timestamp, const guint8 * data, guint size)
{
@ -1015,7 +1009,7 @@ mxf_local_tag_parse (const guint8 * data, guint size, guint16 * tag,
}
void
gst_mxf_local_tag_free (MXFLocalTag * tag)
mxf_local_tag_free (MXFLocalTag * tag)
{
g_free (tag->data);
g_slice_free (MXFLocalTag, tag);
@ -1036,9 +1030,9 @@ mxf_local_tag_add_to_hash_table (const MXFPrimerPack * primer,
if (*hash_table == NULL)
*hash_table =
g_hash_table_new_full ((GHashFunc) gst_mxf_ul_hash,
(GEqualFunc) gst_mxf_ul_equal, (GDestroyNotify) NULL,
(GDestroyNotify) gst_mxf_local_tag_free);
g_hash_table_new_full ((GHashFunc) mxf_ul_hash,
(GEqualFunc) mxf_ul_is_equal, (GDestroyNotify) NULL,
(GDestroyNotify) mxf_local_tag_free);
g_return_val_if_fail (*hash_table != NULL, FALSE);

View file

@ -37,6 +37,7 @@ typedef struct {
gchar * mxf_ul_to_string (const MXFUL *ul, gchar str[48]);
gboolean mxf_ul_is_equal (const MXFUL *a, const MXFUL *b);
gboolean mxf_ul_is_zero (const MXFUL *ul);
guint mxf_ul_hash (const MXFUL *ul);
gchar *mxf_umid_to_string (const MXFUMID * umid, gchar str[96]);
MXFUMID *mxf_umid_from_string (const gchar *str, MXFUMID * umid);