avfilter/vf_v360: refactor uf/vf scaling
[ffmpeg.git] / libavformat / mxfdec.c
index f93cc30..af9d33f 100644 (file)
@@ -106,15 +106,19 @@ typedef struct MXFPartition {
     KLVPacket first_essence_klv;
 } MXFPartition;
 
-typedef struct MXFCryptoContext {
+typedef struct MXFMetadataSet {
     UID uid;
+    uint64_t partition_score;
     enum MXFMetadataSetType type;
+} MXFMetadataSet;
+
+typedef struct MXFCryptoContext {
+    MXFMetadataSet meta;
     UID source_container_ul;
 } MXFCryptoContext;
 
 typedef struct MXFStructuralComponent {
-    UID uid;
-    enum MXFMetadataSetType type;
+    MXFMetadataSet meta;
     UID source_package_ul;
     UID source_package_uid;
     UID data_definition_ul;
@@ -124,8 +128,7 @@ typedef struct MXFStructuralComponent {
 } MXFStructuralComponent;
 
 typedef struct MXFSequence {
-    UID uid;
-    enum MXFMetadataSetType type;
+    MXFMetadataSet meta;
     UID data_definition_ul;
     UID *structural_components_refs;
     int structural_components_count;
@@ -134,8 +137,7 @@ typedef struct MXFSequence {
 } MXFSequence;
 
 typedef struct MXFTimecodeComponent {
-    UID uid;
-    enum MXFMetadataSetType type;
+    MXFMetadataSet meta;
     int drop_frame;
     int start_frame;
     struct AVRational rate;
@@ -143,29 +145,25 @@ typedef struct MXFTimecodeComponent {
 } MXFTimecodeComponent;
 
 typedef struct {
-    UID uid;
-    enum MXFMetadataSetType type;
+    MXFMetadataSet meta;
     UID input_segment_ref;
 } MXFPulldownComponent;
 
 typedef struct {
-    UID uid;
-    enum MXFMetadataSetType type;
+    MXFMetadataSet meta;
     UID *structural_components_refs;
     int structural_components_count;
     int64_t duration;
 } MXFEssenceGroup;
 
 typedef struct {
-    UID uid;
-    enum MXFMetadataSetType type;
+    MXFMetadataSet meta;
     char *name;
     char *value;
 } MXFTaggedValue;
 
 typedef struct {
-    UID uid;
-    enum MXFMetadataSetType type;
+    MXFMetadataSet meta;
     MXFSequence *sequence; /* mandatory, and only one */
     UID sequence_ref;
     int track_id;
@@ -182,8 +180,7 @@ typedef struct {
 } MXFTrack;
 
 typedef struct MXFDescriptor {
-    UID uid;
-    enum MXFMetadataSetType type;
+    MXFMetadataSet meta;
     UID essence_container_ul;
     UID essence_codec_ul;
     UID codec_ul;
@@ -206,8 +203,8 @@ typedef struct MXFDescriptor {
     unsigned int color_range;
     unsigned int horiz_subsampling;
     unsigned int vert_subsampling;
-    UID *sub_descriptors_refs;
-    int sub_descriptors_count;
+    UID *file_descriptors_refs;
+    int file_descriptors_count;
     int linked_track_id;
     uint8_t *extradata;
     int extradata_size;
@@ -221,8 +218,7 @@ typedef struct MXFDescriptor {
 } MXFDescriptor;
 
 typedef struct MXFIndexTableSegment {
-    UID uid;
-    enum MXFMetadataSetType type;
+    MXFMetadataSet meta;
     int edit_unit_byte_count;
     int index_sid;
     int body_sid;
@@ -236,8 +232,7 @@ typedef struct MXFIndexTableSegment {
 } MXFIndexTableSegment;
 
 typedef struct MXFPackage {
-    UID uid;
-    enum MXFMetadataSetType type;
+    MXFMetadataSet meta;
     UID package_uid;
     UID package_ul;
     UID *tracks_refs;
@@ -250,19 +245,13 @@ typedef struct MXFPackage {
 } MXFPackage;
 
 typedef struct MXFEssenceContainerData {
-    UID uid;
-    enum MXFMetadataSetType type;
+    MXFMetadataSet meta;
     UID package_uid;
     UID package_ul;
     int index_sid;
     int body_sid;
 } MXFEssenceContainerData;
 
-typedef struct MXFMetadataSet {
-    UID uid;
-    enum MXFMetadataSetType type;
-} MXFMetadataSet;
-
 /* decoded index table */
 typedef struct MXFIndexTable {
     int index_sid;
@@ -353,7 +342,7 @@ static void mxf_free_metadataset(MXFMetadataSet **ctx, int freectx)
         av_freep(&((MXFDescriptor *)*ctx)->extradata);
         av_freep(&((MXFDescriptor *)*ctx)->mastering);
         av_freep(&((MXFDescriptor *)*ctx)->coll);
-        av_freep(&((MXFDescriptor *)*ctx)->sub_descriptors_refs);
+        av_freep(&((MXFDescriptor *)*ctx)->file_descriptors_refs);
         break;
     case Sequence:
         av_freep(&((MXFSequence *)*ctx)->structural_components_refs);
@@ -563,6 +552,10 @@ static int mxf_get_d10_aes3_packet(AVIOContext *pb, AVStream *st, AVPacket *pkt,
     data_ptr = pkt->data;
     end_ptr = pkt->data + length;
     buf_ptr = pkt->data + 4; /* skip SMPTE 331M header */
+
+    if (st->codecpar->channels > 8)
+        return AVERROR_INVALIDDATA;
+
     for (; end_ptr - buf_ptr >= st->codecpar->channels * 4; ) {
         for (i = 0; i < st->codecpar->channels; i++) {
             uint32_t sample = bytestream_get_le32(&buf_ptr);
@@ -842,10 +835,42 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size
     return 0;
 }
 
+static uint64_t partition_score(MXFPartition *p)
+{
+    uint64_t score;
+    if (!p)
+        return 0;
+    if (p->type == Footer)
+        score = 5;
+    else if (p->complete)
+        score = 4;
+    else if (p->closed)
+        score = 3;
+    else
+        score = 1;
+    return (score << 60) | ((uint64_t)p->this_partition >> 4);
+}
+
 static int mxf_add_metadata_set(MXFContext *mxf, MXFMetadataSet **metadata_set)
 {
     MXFMetadataSet **tmp;
-
+    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) {
+                uint64_t old_s = mxf->metadata_sets[i]->partition_score;
+                uint64_t new_s = (*metadata_set)->partition_score;
+                if (old_s > new_s) {
+                     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);
@@ -1176,8 +1201,8 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int
 
     switch(tag) {
     case 0x3F01:
-        return mxf_read_strong_ref_array(pb, &descriptor->sub_descriptors_refs,
-                                             &descriptor->sub_descriptors_count);
+        return mxf_read_strong_ref_array(pb, &descriptor->file_descriptors_refs,
+                                             &descriptor->file_descriptors_count);
     case 0x3002: /* ContainerDuration */
         descriptor->duration = avio_rb64(pb);
         break;
@@ -1400,7 +1425,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];
@@ -1411,7 +1436,7 @@ static void *mxf_resolve_strong_ref(MXFContext *mxf, UID *strong_ref, enum MXFMe
 
 static const MXFCodecUL mxf_picture_essence_container_uls[] = {
     // video essence container uls
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0c,0x01,0x00 }, 14,   AV_CODEC_ID_JPEG2000, NULL, 14 },
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0c,0x01,0x00 }, 14,   AV_CODEC_ID_JPEG2000, NULL, 14, J2KWrap },
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x10,0x60,0x01 }, 14,       AV_CODEC_ID_H264, NULL, 15 }, /* H.264 */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x11,0x01,0x00 }, 14,      AV_CODEC_ID_DNXHD, NULL, 14 }, /* VC-3 */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x12,0x01,0x00 }, 14,        AV_CODEC_ID_VC1, NULL, 14 }, /* VC-1 */
@@ -1495,6 +1520,10 @@ static MXFWrappingScheme mxf_get_wrapping_kind(UID *essence_container_ul)
             if (val == 0x02)
                 val = 0x01;
             break;
+        case J2KWrap:
+            if (val != 0x02)
+                val = 0x01;
+            break;
     }
     if (val == 0x01)
         return FrameWrapped;
@@ -1764,7 +1793,7 @@ static int mxf_compute_ptses_fake_index(MXFContext *mxf, MXFIndexTable *index_ta
      * 6:  5   5
      *
      * We do this by bucket sorting x by x+TemporalOffset[x] into mxf->ptses,
-     * then settings mxf->internal->first_dts = -max(TemporalOffset[x]).
+     * then settings ffstream(mxf)->first_dts = -max(TemporalOffset[x]).
      * The latter makes DTS <= PTS.
      */
     for (i = x = 0; i < index_table->nb_segments; i++) {
@@ -1843,8 +1872,8 @@ static int mxf_compute_index_tables(MXFContext *mxf)
         }
     }
 
-    mxf->index_tables = av_mallocz_array(mxf->nb_index_tables,
-                                         sizeof(*mxf->index_tables));
+    mxf->index_tables = av_calloc(mxf->nb_index_tables,
+                                  sizeof(*mxf->index_tables));
     if (!mxf->index_tables) {
         av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate index tables\n");
         ret = AVERROR(ENOMEM);
@@ -1865,9 +1894,7 @@ static int mxf_compute_index_tables(MXFContext *mxf)
         MXFIndexTable *t = &mxf->index_tables[j];
         MXFTrack *mxf_track = NULL;
 
-        t->segments = av_mallocz_array(t->nb_segments,
-                                       sizeof(*t->segments));
-
+        t->segments = av_calloc(t->nb_segments, sizeof(*t->segments));
         if (!t->segments) {
             av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate IndexTableSegment"
                    " pointer array\n");
@@ -2014,7 +2041,7 @@ static MXFTimecodeComponent* mxf_resolve_timecode_component(MXFContext *mxf, UID
     if (!component)
         return NULL;
 
-    switch (component->type) {
+    switch (component->meta.type) {
     case TimecodeComponent:
         return (MXFTimecodeComponent*)component;
     case PulldownComponent: /* timcode component may be located on a pulldown component */
@@ -2044,25 +2071,25 @@ static MXFPackage* mxf_resolve_source_package(MXFContext *mxf, UID package_ul, U
 
 static MXFDescriptor* mxf_resolve_multidescriptor(MXFContext *mxf, MXFDescriptor *descriptor, int track_id)
 {
-    MXFDescriptor *sub_descriptor = NULL;
+    MXFDescriptor *file_descriptor = NULL;
     int i;
 
     if (!descriptor)
         return NULL;
 
-    if (descriptor->type == MultipleDescriptor) {
-        for (i = 0; i < descriptor->sub_descriptors_count; i++) {
-            sub_descriptor = mxf_resolve_strong_ref(mxf, &descriptor->sub_descriptors_refs[i], Descriptor);
+    if (descriptor->meta.type == MultipleDescriptor) {
+        for (i = 0; i < descriptor->file_descriptors_count; i++) {
+            file_descriptor = mxf_resolve_strong_ref(mxf, &descriptor->file_descriptors_refs[i], Descriptor);
 
-            if (!sub_descriptor) {
-                av_log(mxf->fc, AV_LOG_ERROR, "could not resolve sub descriptor strong ref\n");
+            if (!file_descriptor) {
+                av_log(mxf->fc, AV_LOG_ERROR, "could not resolve file descriptor strong ref\n");
                 continue;
             }
-            if (sub_descriptor->linked_track_id == track_id) {
-                return sub_descriptor;
+            if (file_descriptor->linked_track_id == track_id) {
+                return file_descriptor;
             }
         }
-    } else if (descriptor->type == Descriptor)
+    } else if (descriptor->meta.type == Descriptor)
         return descriptor;
 
     return NULL;
@@ -2102,7 +2129,7 @@ static MXFStructuralComponent* mxf_resolve_sourceclip(MXFContext *mxf, UID *stro
     component = mxf_resolve_strong_ref(mxf, strong_ref, AnyType);
     if (!component)
         return NULL;
-    switch (component->type) {
+    switch (component->meta.type) {
         case SourceClip:
             return component;
         case EssenceGroup:
@@ -2299,6 +2326,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
         const MXFCodecUL *container_ul = NULL;
         const MXFCodecUL *pix_fmt_ul = NULL;
         AVStream *st;
+        FFStream *sti;
         AVTimecode tc;
         int flags;
 
@@ -2406,6 +2434,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
             ret = AVERROR(ENOMEM);
             goto fail_and_free;
         }
+        sti = ffstream(st);
         st->id = material_track->track_id;
         st->priv_data = source_track;
 
@@ -2591,7 +2620,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
                     }
                 }
             }
-            st->internal->need_parsing = AVSTREAM_PARSE_HEADERS;
+            sti->need_parsing = AVSTREAM_PARSE_HEADERS;
             if (material_track->sequence->origin) {
                 av_dict_set_int(&st->metadata, "material_track_origin", material_track->sequence->origin, 0);
             }
@@ -2599,7 +2628,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
                 av_dict_set_int(&st->metadata, "source_track_origin", source_track->sequence->origin, 0);
             }
             if (descriptor->aspect_ratio.num && descriptor->aspect_ratio.den)
-                st->internal->display_aspect_ratio = descriptor->aspect_ratio;
+                sti->display_aspect_ratio = descriptor->aspect_ratio;
             st->codecpar->color_range     = mxf_get_color_range(mxf, descriptor);
             st->codecpar->color_primaries = mxf_get_codec_ul(ff_mxf_color_primaries_uls, &descriptor->color_primaries_ul)->id;
             st->codecpar->color_trc       = mxf_get_codec_ul(ff_mxf_color_trc_uls, &descriptor->color_trc_ul)->id;
@@ -2656,7 +2685,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
                 else if (descriptor->bits_per_sample == 32)
                     st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
             } else if (st->codecpar->codec_id == AV_CODEC_ID_MP2) {
-                st->internal->need_parsing = AVSTREAM_PARSE_FULL;
+                sti->need_parsing = AVSTREAM_PARSE_FULL;
             }
             st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
         } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
@@ -2690,7 +2719,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
         }
         if (st->codecpar->codec_type != AVMEDIA_TYPE_DATA && source_track->wrapping != FrameWrapped) {
             /* TODO: decode timestamps */
-            st->internal->need_parsing = AVSTREAM_PARSE_TIMESTAMPS;
+            sti->need_parsing = AVSTREAM_PARSE_TIMESTAMPS;
         }
     }
 
@@ -2869,9 +2898,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_score = partition_score(partition);
     switch (type){
     case MultipleDescriptor:
     case Descriptor:
@@ -2896,7 +2926,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;
@@ -3265,7 +3295,7 @@ static int mxf_handle_missing_index_segment(MXFContext *mxf, AVStream *st)
     if (!track->index_sid)
         track->index_sid = track->body_sid;
 
-    segment->type = IndexTableSegment;
+    segment->meta.type = IndexTableSegment;
     /* stream will be treated as small EditUnitByteCount */
     segment->edit_unit_byte_count = edit_unit_byte_count;
     segment->index_start_position = 0;
@@ -3650,7 +3680,7 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
                 if (next_ofs <= 0) {
                     // If we have no way to packetize the data, then return it in chunks...
                     if (klv.next_klv - klv.length == pos && max_data_size > MXF_MAX_CHUNK_SIZE) {
-                        st->internal->need_parsing = AVSTREAM_PARSE_FULL;
+                        ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
                         avpriv_request_sample(s, "Huge KLV without proper index in non-frame wrapped essence");
                     }
                     size = FFMIN(max_data_size, MXF_MAX_CHUNK_SIZE);