avformat/mxfdec: prefer footer and complete partitions for metadata

Also do not store inferior metadata with the same UID.

Signed-off-by: Marton Balint <cus@passwd.hu>
This commit is contained in:
Marton Balint 2021-06-27 22:59:49 +02:00
parent 9b57d2f0a9
commit 7b4bdcd68e
1 changed files with 46 additions and 3 deletions

View 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;