avformat/mxfdec: prefer footer and complete partitions for metadata
authorMarton Balint <cus@passwd.hu>
Sun, 27 Jun 2021 20:59:49 +0000 (22:59 +0200)
committerMarton Balint <cus@passwd.hu>
Sun, 1 Aug 2021 00:57:53 +0000 (02:57 +0200)
Also do not store inferior metadata with the same UID.

Signed-off-by: Marton Balint <cus@passwd.hu>
libavformat/mxfdec.c

index f491914..fd22680 100644 (file)
@@ -108,12 +108,14 @@ typedef struct MXFPartition {
 
 typedef struct MXFCryptoContext {
     UID uid;
+    MXFPartition *partition;
     enum MXFMetadataSetType type;
     UID source_container_ul;
 } MXFCryptoContext;
 
 typedef struct MXFStructuralComponent {
     UID uid;
+    MXFPartition *partition;
     enum MXFMetadataSetType type;
     UID source_package_ul;
     UID source_package_uid;
@@ -125,6 +127,7 @@ typedef struct MXFStructuralComponent {
 
 typedef struct MXFSequence {
     UID uid;
+    MXFPartition *partition;
     enum MXFMetadataSetType type;
     UID data_definition_ul;
     UID *structural_components_refs;
@@ -135,6 +138,7 @@ typedef struct MXFSequence {
 
 typedef struct MXFTimecodeComponent {
     UID uid;
+    MXFPartition *partition;
     enum MXFMetadataSetType type;
     int drop_frame;
     int start_frame;
@@ -144,12 +148,14 @@ typedef struct MXFTimecodeComponent {
 
 typedef struct {
     UID uid;
+    MXFPartition *partition;
     enum MXFMetadataSetType type;
     UID input_segment_ref;
 } MXFPulldownComponent;
 
 typedef struct {
     UID uid;
+    MXFPartition *partition;
     enum MXFMetadataSetType type;
     UID *structural_components_refs;
     int structural_components_count;
@@ -158,6 +164,7 @@ typedef struct {
 
 typedef struct {
     UID uid;
+    MXFPartition *partition;
     enum MXFMetadataSetType type;
     char *name;
     char *value;
@@ -165,6 +172,7 @@ typedef struct {
 
 typedef struct {
     UID uid;
+    MXFPartition *partition;
     enum MXFMetadataSetType type;
     MXFSequence *sequence; /* mandatory, and only one */
     UID sequence_ref;
@@ -183,6 +191,7 @@ typedef struct {
 
 typedef struct MXFDescriptor {
     UID uid;
+    MXFPartition *partition;
     enum MXFMetadataSetType type;
     UID essence_container_ul;
     UID essence_codec_ul;
@@ -222,6 +231,7 @@ typedef struct MXFDescriptor {
 
 typedef struct MXFIndexTableSegment {
     UID uid;
+    MXFPartition *partition;
     enum MXFMetadataSetType type;
     int edit_unit_byte_count;
     int index_sid;
@@ -237,6 +247,7 @@ typedef struct MXFIndexTableSegment {
 
 typedef struct MXFPackage {
     UID uid;
+    MXFPartition *partition;
     enum MXFMetadataSetType type;
     UID package_uid;
     UID package_ul;
@@ -251,6 +262,7 @@ typedef struct MXFPackage {
 
 typedef struct MXFEssenceContainerData {
     UID uid;
+    MXFPartition *partition;
     enum MXFMetadataSetType type;
     UID package_uid;
     UID package_ul;
@@ -260,6 +272,7 @@ typedef struct MXFEssenceContainerData {
 
 typedef struct MXFMetadataSet {
     UID uid;
+    MXFPartition *partition;
     enum MXFMetadataSetType type;
 } MXFMetadataSet;
 
@@ -842,10 +855,39 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size
     return 0;
 }
 
+static int partition_score(MXFPartition *p)
+{
+    if (p->type == Footer)
+        return 5;
+    if (p->complete)
+        return 4;
+    if (p->closed)
+        return 3;
+    return 1;
+}
+
 static int mxf_add_metadata_set(MXFContext *mxf, MXFMetadataSet **metadata_set)
 {
     MXFMetadataSet **tmp;
-
+    MXFPartition *new_p = (*metadata_set)->partition;
+    enum MXFMetadataSetType type = (*metadata_set)->type;
+
+    // Index Table is special because it might be added manually without
+    // partition and we iterate thorugh all instances of them. Also some files
+    // use the same Instance UID for different index tables...
+    if (type != IndexTableSegment) {
+        for (int i = 0; i < mxf->metadata_sets_count; i++) {
+            if (!memcmp((*metadata_set)->uid, mxf->metadata_sets[i]->uid, 16) && type == mxf->metadata_sets[i]->type) {
+                MXFPartition *old_p = mxf->metadata_sets[i]->partition;
+                int old_s = partition_score(old_p);
+                int new_s = partition_score(new_p);
+                if (old_s > new_s || old_s == new_s && old_p->this_partition > new_p->this_partition) {
+                     mxf_free_metadataset(metadata_set, 1);
+                     return 0;
+                }
+            }
+        }
+    }
     tmp = av_realloc_array(mxf->metadata_sets, mxf->metadata_sets_count + 1, sizeof(*mxf->metadata_sets));
     if (!tmp) {
         mxf_free_metadataset(metadata_set, 1);
@@ -1400,7 +1442,7 @@ static void *mxf_resolve_strong_ref(MXFContext *mxf, UID *strong_ref, enum MXFMe
 
     if (!strong_ref)
         return NULL;
-    for (i = 0; i < mxf->metadata_sets_count; i++) {
+    for (i = mxf->metadata_sets_count - 1; i >= 0; i--) {
         if (!memcmp(*strong_ref, mxf->metadata_sets[i]->uid, 16) &&
             (type == AnyType || mxf->metadata_sets[i]->type == type)) {
             return mxf->metadata_sets[i];
@@ -2873,9 +2915,10 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = {
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL, 0, AnyType },
 };
 
-static int mxf_metadataset_init(MXFMetadataSet *ctx, enum MXFMetadataSetType type)
+static int mxf_metadataset_init(MXFMetadataSet *ctx, enum MXFMetadataSetType type, MXFPartition *partition)
 {
     ctx->type = type;
+    ctx->partition = partition;
     switch (type){
     case MultipleDescriptor:
     case Descriptor:
@@ -2900,7 +2943,7 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF
         if (!meta)
             return AVERROR(ENOMEM);
         ctx  = meta;
-        mxf_metadataset_init(meta, type);
+        mxf_metadataset_init(meta, type, mxf->current_partition);
     } else {
         meta = NULL;
         ctx  = mxf;