]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/mxfdec.c
avformat/hlsenc: added segment file deletion
[ffmpeg] / libavformat / mxfdec.c
index bc0a10b5423c757f49ac7aacc0c80762ce3da5ae..6c104b97a96677ab9bb8fff08901acbc05184582 100644 (file)
@@ -133,6 +133,14 @@ typedef struct {
     UID input_segment_ref;
 } MXFPulldownComponent;
 
+typedef struct {
+    UID uid;
+    enum MXFMetadataSetType type;
+    UID *structural_components_refs;
+    int structural_components_count;
+    int64_t duration;
+} MXFEssenceGroup;
+
 typedef struct {
     UID uid;
     enum MXFMetadataSetType type;
@@ -161,6 +169,7 @@ typedef struct {
     int field_dominance;
     int channels;
     int bits_per_sample;
+    int64_t duration; /* ContainerDuration optional property */
     unsigned int component_depth;
     unsigned int horiz_subsampling;
     unsigned int vert_subsampling;
@@ -733,8 +742,10 @@ static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID
     case 0x1001:
         sequence->structural_components_count = avio_rb32(pb);
         sequence->structural_components_refs = av_calloc(sequence->structural_components_count, sizeof(UID));
-        if (!sequence->structural_components_refs)
+        if (!sequence->structural_components_refs) {
+            sequence->structural_components_count = 0;
             return AVERROR(ENOMEM);
+        }
         avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */
         avio_read(pb, (uint8_t *)sequence->structural_components_refs, sequence->structural_components_count * sizeof(UID));
         break;
@@ -742,6 +753,27 @@ static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID
     return 0;
 }
 
+static int mxf_read_essence_group(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
+{
+    MXFEssenceGroup *essence_group = arg;
+    switch (tag) {
+    case 0x0202:
+        essence_group->duration = avio_rb64(pb);
+        break;
+    case 0x0501:
+        essence_group->structural_components_count = avio_rb32(pb);
+        essence_group->structural_components_refs = av_calloc(essence_group->structural_components_count, sizeof(UID));
+        if (!essence_group->structural_components_refs) {
+            essence_group->structural_components_count = 0;
+            return AVERROR(ENOMEM);
+        }
+        avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */
+        avio_read(pb, (uint8_t *)essence_group->structural_components_refs, essence_group->structural_components_count * sizeof(UID));
+        break;
+    }
+    return 0;
+}
+
 static int mxf_read_utf16_string(AVIOContext *pb, int size, char** str)
 {
     int ret;
@@ -872,7 +904,6 @@ static void mxf_read_pixel_layout(AVIOContext *pb, MXFDescriptor *descriptor)
 static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
 {
     MXFDescriptor *descriptor = arg;
-    descriptor->pix_fmt = AV_PIX_FMT_NONE;
     switch(tag) {
     case 0x3F01:
         descriptor->sub_descriptors_count = avio_rb32(pb);
@@ -882,6 +913,9 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int
         avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */
         avio_read(pb, (uint8_t *)descriptor->sub_descriptors_refs, descriptor->sub_descriptors_count * sizeof(UID));
         break;
+    case 0x3002: /* ContainerDuration */
+        descriptor->duration = avio_rb64(pb);
+        break;
     case 0x3004:
         avio_read(pb, descriptor->essence_container_ul, 16);
         break;
@@ -994,6 +1028,7 @@ static const MXFCodecUL mxf_picture_essence_container_uls[] = {
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MPEG-ES Frame wrapped */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, 14,    AV_CODEC_ID_DVVIDEO }, /* DV 625 25mbps */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14,   AV_CODEC_ID_RAWVIDEO }, /* Uncompressed Picture */
+    { { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xff,0x4b,0x46,0x41,0x41,0x00,0x0d,0x4d,0x4f }, 14,   AV_CODEC_ID_RAWVIDEO }, /* Legacy ?? Uncompressed Picture */
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0,      AV_CODEC_ID_NONE },
 };
 
@@ -1457,12 +1492,97 @@ static MXFTimecodeComponent* mxf_resolve_timecode_component(MXFContext *mxf, UID
     return NULL;
 }
 
+static MXFPackage* mxf_resolve_source_package(MXFContext *mxf, UID package_uid)
+{
+    MXFPackage *package = NULL;
+    int i;
+
+    for (i = 0; i < mxf->packages_count; i++) {
+        package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[i], SourcePackage);
+        if (!package)
+            continue;
+
+        if (!memcmp(package->package_uid, package_uid, 16))
+            return package;
+    }
+    return NULL;
+}
+
+static MXFDescriptor* mxf_resolve_multidescriptor(MXFContext *mxf, MXFDescriptor *descriptor, int track_id)
+{
+    MXFDescriptor *sub_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 (!sub_descriptor) {
+                av_log(mxf->fc, AV_LOG_ERROR, "could not resolve sub descriptor strong ref\n");
+                continue;
+            }
+            if (sub_descriptor->linked_track_id == track_id) {
+                return sub_descriptor;
+            }
+        }
+    } else if (descriptor->type == Descriptor)
+        return descriptor;
+
+    return NULL;
+}
+
+static MXFStructuralComponent* mxf_resolve_essence_group_choice(MXFContext *mxf, MXFEssenceGroup *essence_group)
+{
+    MXFStructuralComponent *component = NULL;
+    MXFPackage *package = NULL;
+    MXFDescriptor *descriptor = NULL;
+    int i;
+
+    if (!essence_group || !essence_group->structural_components_count)
+        return NULL;
+
+    /* essence groups contains multiple representations of the same media,
+       this return the first components with a valid Descriptor typically index 0 */
+    for (i =0; i < essence_group->structural_components_count; i++){
+        component = mxf_resolve_strong_ref(mxf, &essence_group->structural_components_refs[i], SourceClip);
+        if (!component)
+            continue;
+
+        if (!(package = mxf_resolve_source_package(mxf, component->source_package_uid)))
+            continue;
+
+        descriptor = mxf_resolve_strong_ref(mxf, &package->descriptor_ref, Descriptor);
+        if (descriptor)
+            return component;
+    }
+    return NULL;
+}
+
+static MXFStructuralComponent* mxf_resolve_sourceclip(MXFContext *mxf, UID *strong_ref)
+{
+    MXFStructuralComponent *component = NULL;
+
+    component = mxf_resolve_strong_ref(mxf, strong_ref, AnyType);
+    if (!component)
+        return NULL;
+    switch (component->type) {
+        case SourceClip:
+            return component;
+        case EssenceGroup:
+            return mxf_resolve_essence_group_choice(mxf, (MXFEssenceGroup*) component);
+        default:
+            break;
+    }
+    return NULL;
+}
+
 static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_track, AVStream *st)
 {
-    MXFPackage *temp_package = NULL;
     MXFPackage *physical_package = NULL;
     MXFTrack *physical_track = NULL;
-    MXFStructuralComponent *component = NULL;
     MXFStructuralComponent *sourceclip = NULL;
     MXFTimecodeComponent *mxf_tc = NULL;
     int i, j, k;
@@ -1471,21 +1591,11 @@ static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_t
     int64_t start_position;
 
     for (i = 0; i < source_track->sequence->structural_components_count; i++) {
-        component = mxf_resolve_strong_ref(mxf, &source_track->sequence->structural_components_refs[i], SourceClip);
-        if (!component)
+        sourceclip = mxf_resolve_strong_ref(mxf, &source_track->sequence->structural_components_refs[i], SourceClip);
+        if (!sourceclip)
             continue;
 
-        for (j = 0; j < mxf->packages_count; j++) {
-            temp_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[j], SourcePackage);
-            if (!temp_package)
-                continue;
-            if (!memcmp(temp_package->package_uid, component->source_package_uid, 16)){
-                physical_package = temp_package;
-                sourceclip = component;
-                break;
-            }
-        }
-        if (!physical_package)
+        if (!(physical_package = mxf_resolve_source_package(mxf, sourceclip->source_package_uid)))
             break;
 
         mxf_add_uid_metadata(&st->metadata, "reel_uid", physical_package->package_uid);
@@ -1532,7 +1642,6 @@ static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_t
 static int mxf_parse_structural_metadata(MXFContext *mxf)
 {
     MXFPackage *material_package = NULL;
-    MXFPackage *temp_package = NULL;
     int i, j, k, ret;
 
     av_dlog(mxf->fc, "metadata sets count %d\n", mxf->metadata_sets_count);
@@ -1599,19 +1708,11 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
 
         /* TODO: handle multiple source clips */
         for (j = 0; j < material_track->sequence->structural_components_count; j++) {
-            component = mxf_resolve_strong_ref(mxf, &material_track->sequence->structural_components_refs[j], SourceClip);
+            component = mxf_resolve_sourceclip(mxf, &material_track->sequence->structural_components_refs[j]);
             if (!component)
                 continue;
 
-            for (k = 0; k < mxf->packages_count; k++) {
-                temp_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[k], SourcePackage);
-                if (!temp_package)
-                    continue;
-                if (!memcmp(temp_package->package_uid, component->source_package_uid, 16)) {
-                    source_package = temp_package;
-                    break;
-                }
-            }
+            source_package = mxf_resolve_source_package(mxf, component->source_package_uid);
             if (!source_package) {
                 av_dlog(mxf->fc, "material track %d: no corresponding source package found\n", material_track->track_id);
                 break;
@@ -1656,7 +1757,17 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
         }
         st->id = source_track->track_id;
         st->priv_data = source_track;
-        source_track->original_duration = st->duration = component->duration;
+
+        source_package->descriptor = mxf_resolve_strong_ref(mxf, &source_package->descriptor_ref, AnyType);
+        descriptor = mxf_resolve_multidescriptor(mxf, source_package->descriptor, source_track->track_id);
+
+        /* A SourceClip from a EssenceGroup may only be a single frame of essence data. The clips duration is then how many
+         * frames its suppose to repeat for. Descriptor->duration, if present, contains the real duration of the essence data */
+        if (descriptor && descriptor->duration != AV_NOPTS_VALUE)
+            source_track->original_duration = st->duration = FFMIN(descriptor->duration, component->duration);
+        else
+            source_track->original_duration = st->duration = component->duration;
+
         if (st->duration == -1)
             st->duration = AV_NOPTS_VALUE;
         st->start_time = component->start_position;
@@ -1679,24 +1790,6 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
         codec_ul = mxf_get_codec_ul(ff_mxf_data_definition_uls, &source_track->sequence->data_definition_ul);
         st->codec->codec_type = codec_ul->id;
 
-        source_package->descriptor = mxf_resolve_strong_ref(mxf, &source_package->descriptor_ref, AnyType);
-        if (source_package->descriptor) {
-            if (source_package->descriptor->type == MultipleDescriptor) {
-                for (j = 0; j < source_package->descriptor->sub_descriptors_count; j++) {
-                    MXFDescriptor *sub_descriptor = mxf_resolve_strong_ref(mxf, &source_package->descriptor->sub_descriptors_refs[j], Descriptor);
-
-                    if (!sub_descriptor) {
-                        av_log(mxf->fc, AV_LOG_ERROR, "could not resolve sub descriptor strong ref\n");
-                        continue;
-                    }
-                    if (sub_descriptor->linked_track_id == source_track->track_id) {
-                        descriptor = sub_descriptor;
-                        break;
-                    }
-                }
-            } else if (source_package->descriptor->type == Descriptor)
-                descriptor = source_package->descriptor;
-        }
         if (!descriptor) {
             av_log(mxf->fc, AV_LOG_INFO, "source track %d: stream %d, no descriptor found\n", source_track->track_id, st->index);
             continue;
@@ -1976,6 +2069,7 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = {
     { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_package, sizeof(MXFPackage), SourcePackage },
     { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_package, sizeof(MXFPackage), MaterialPackage },
     { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0f,0x00 }, mxf_read_sequence, sizeof(MXFSequence), Sequence },
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x05,0x00 }, mxf_read_essence_group, sizeof(MXFEssenceGroup), EssenceGroup},
     { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_source_clip, sizeof(MXFStructuralComponent), SourceClip },
     { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x44,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), MultipleDescriptor },
     { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Generic Sound */
@@ -1996,6 +2090,20 @@ 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)
+{
+    switch (type){
+    case MultipleDescriptor:
+    case Descriptor:
+        ((MXFDescriptor*)ctx)->pix_fmt = AV_PIX_FMT_NONE;
+        ((MXFDescriptor*)ctx)->duration = AV_NOPTS_VALUE;
+        break;
+    default:
+        break;
+    }
+    return 0;
+}
+
 static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadFunc *read_child, int ctx_size, enum MXFMetadataSetType type)
 {
     AVIOContext *pb = mxf->fc->pb;
@@ -2004,6 +2112,7 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF
 
     if (!ctx)
         return AVERROR(ENOMEM);
+    mxf_metadataset_init(ctx, type);
     while (avio_tell(pb) + 4 < klv_end && !avio_feof(pb)) {
         int ret;
         int tag = avio_rb16(pb);
@@ -2741,6 +2850,9 @@ static int mxf_read_close(AVFormatContext *s)
         case Sequence:
             av_freep(&((MXFSequence *)mxf->metadata_sets[i])->structural_components_refs);
             break;
+        case EssenceGroup:
+            av_freep(&((MXFEssenceGroup *)mxf->metadata_sets[i])->structural_components_refs);
+            break;
         case SourcePackage:
         case MaterialPackage:
             av_freep(&((MXFPackage *)mxf->metadata_sets[i])->tracks_refs);