From patchwork Mon Nov 29 00:59:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 31790 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:d206:0:0:0:0:0 with SMTP id q6csp5463328iob; Sun, 28 Nov 2021 16:59:52 -0800 (PST) X-Google-Smtp-Source: ABdhPJw50ekzfplcJiR/SqIMvRpqNW0H3P6tyvBwPvJHdYoiVbyAyXabKuwWFmlYf85jWCAlgFJu X-Received: by 2002:a05:6402:170a:: with SMTP id y10mr69851502edu.324.1638147592276; Sun, 28 Nov 2021 16:59:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1638147592; cv=none; d=google.com; s=arc-20160816; b=XVg2qT/RAhQh3K2bUmLlYE3TeZFcUL9TqCEpLowurXG/6o5b5cATTJqwXDVkEeJ2Dm Jq1TZdZNQz9IMS//Za9Bppd1yaLrHgTSzC4ib6a4/6h2n6mT9P7Fd7fc8tLCeGDEQRTv tcgSO8210T8rNhNtJdswlhMWN4KC+2doSgbZg/Qu5XxCralvQheSeH/La2hWXEv6/+pe CvlA4A3dRce6EWsPndPw87sWVP7SuZajIuu6IN3LVhaRqrDziw2TQa2J5ZURGOhSx5q1 ALXFSRjuPKMnTLfOhkVu9qWjOsflj/YQMh7qqjAgRVSTsA9XGHO6ghvIwro6NHrcmWQG h+ZQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=ZI/jzh4mnJMgNa5VllEVrMmVNm7J9CLzIeLqPUJNKIc=; b=zXa5nTKIhJMQQ25UFHRpjyqxCbr1i1weYF/YPgHO1Sh4feOOv87NKsbIef2eAdWtEx /Fp4S4f4Q9n5J2LGb8vlQb1Zb0T613errQj14xcpa/6cyc+4HeU5+J4AnD9lDkDgV6GY /cP7LSP4x+oqqjYtCLPTFs447PASMoOTSKayY+lVyk+ZJ5cGxk/Yqg4o1SiaYtMKsg9J J1ZGfJq/Yjn0r/jdOacuWzjL00EtiIJ8KCbbYobEL1ZMSsuFgBmZAxWKa3puqADm+dNN uRWX+BaPPKdsgIa2KUzGzsmBLpECBINo3MFuoRXtK9wd+AveyGxmybNbKzebHauK39Ny EnUg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id k19si17788727ejg.192.2021.11.28.16.59.51; Sun, 28 Nov 2021 16:59:52 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id B77A968ADC6; Mon, 29 Nov 2021 02:59:42 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DD9CF680C04 for ; Mon, 29 Nov 2021 02:59:33 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 3E279E6420 for ; Mon, 29 Nov 2021 01:59:33 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 8Klfg8aBTb-r for ; Mon, 29 Nov 2021 01:59:30 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id B3F20E44A4 for ; Mon, 29 Nov 2021 01:59:30 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Mon, 29 Nov 2021 01:59:26 +0100 Message-Id: <20211129005930.7188-1-cus@passwd.hu> X-Mailer: git-send-email 2.31.1 In-Reply-To: <1b5e45c8-574a-c0d3-cf2-11963ad25cc1@passwd.hu> References: <1b5e45c8-574a-c0d3-cf2-11963ad25cc1@passwd.hu> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/5] avformat/mxf: support MCA audio information X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: KjudmzSbMTix From: Marc-Antoine Arnaud Signed-off-by: Marton Balint --- doc/demuxers.texi | 10 ++ libavformat/mxf.h | 1 + libavformat/mxfdec.c | 293 +++++++++++++++++++++++++++++++++++++++++- libavformat/version.h | 2 +- 4 files changed, 299 insertions(+), 7 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index cab8a7072c..23b6753602 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -770,6 +770,16 @@ MJPEG stream. Turning this option on by setting it to 1 will result in a stricte of the boundary value. @end table +@section mxf + +MXF demuxer. + +@table @option + +@item -skip_audio_reordering @var{bool} +This option will disable the audio reordering based on Multi-Channel Audio (MCA) labelling (SMPTE ST-377-4). +@end table + @section rawvideo Raw video demuxer. diff --git a/libavformat/mxf.h b/libavformat/mxf.h index fe9c52732c..cddbcb13c9 100644 --- a/libavformat/mxf.h +++ b/libavformat/mxf.h @@ -50,6 +50,7 @@ enum MXFMetadataSetType { TaggedValue, TapeDescriptor, AVCSubDescriptor, + MCASubDescriptor, }; enum MXFFrameLayout { diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index af9d33f796..58ba330475 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -51,11 +51,14 @@ #include "libavutil/mastering_display_metadata.h" #include "libavutil/mathematics.h" #include "libavcodec/bytestream.h" +#include "libavcodec/internal.h" +#include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "libavutil/parseutils.h" #include "libavutil/timecode.h" #include "libavutil/opt.h" #include "avformat.h" +#include "avlanguage.h" #include "internal.h" #include "mxf.h" @@ -177,6 +180,8 @@ typedef struct { int body_sid; MXFWrappingScheme wrapping; int edit_units_per_packet; /* how many edit units to read at a time (PCM, ClipWrapped) */ + int require_reordering; + int channel_ordering[FF_SANE_NB_CHANNELS]; } MXFTrack; typedef struct MXFDescriptor { @@ -205,6 +210,8 @@ typedef struct MXFDescriptor { unsigned int vert_subsampling; UID *file_descriptors_refs; int file_descriptors_count; + UID *sub_descriptors_refs; + int sub_descriptors_count; int linked_track_id; uint8_t *extradata; int extradata_size; @@ -217,6 +224,15 @@ typedef struct MXFDescriptor { size_t coll_size; } MXFDescriptor; +typedef struct MXFMCASubDescriptor { + MXFMetadataSet meta; + UID uid; + UID mca_link_id; + UID mca_group_link_id; + UID mca_label_dictionary_id; + char *language; +} MXFMCASubDescriptor; + typedef struct MXFIndexTableSegment { MXFMetadataSet meta; int edit_unit_byte_count; @@ -290,6 +306,7 @@ typedef struct MXFContext { int nb_index_tables; MXFIndexTable *index_tables; int eia608_extract; + int skip_audio_reordering; } MXFContext; /* NOTE: klv_offset is not set (-1) for local keys */ @@ -311,6 +328,9 @@ static const uint8_t mxf_system_item_key_cp[] = { 0x06,0x0e,0x2b,0x static const uint8_t mxf_system_item_key_gc[] = { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x03,0x01,0x14 }; static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x34 }; static const uint8_t mxf_apple_coll_prefix[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x0e,0x20,0x04,0x01,0x05,0x03,0x01 }; +static const uint8_t mxf_audio_channel[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01 }; +static const uint8_t mxf_soundfield_group[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02 }; + /* complete keys to match */ static const uint8_t mxf_crypto_source_container_ul[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x02,0x02,0x00,0x00,0x00 }; static const uint8_t mxf_encrypted_triplet_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x04,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x7e,0x01,0x00 }; @@ -323,6 +343,15 @@ static const uint8_t mxf_indirect_value_utf16be[] = { 0x42,0x01,0x10,0x static const uint8_t mxf_apple_coll_max_cll[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x0e,0x20,0x04,0x01,0x05,0x03,0x01,0x01 }; static const uint8_t mxf_apple_coll_max_fall[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x0e,0x20,0x04,0x01,0x05,0x03,0x01,0x02 }; +static const uint8_t mxf_mca_label_dictionary_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x01,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_tag_symbol[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x02,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_tag_name[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x03,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x05,0x00,0x00,0x00 }; +static const uint8_t mxf_soundfield_group_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x06,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_rfc5646_spoken_language[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0d,0x03,0x01,0x01,0x02,0x03,0x15,0x00,0x00 }; + +static const uint8_t mxf_sub_descriptor[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x04,0x06,0x10,0x00,0x00 }; + static const uint8_t mxf_mastering_display_prefix[13] = { FF_MXF_MasteringDisplay_PREFIX }; static const uint8_t mxf_mastering_display_uls[4][16] = { FF_MXF_MasteringDisplayPrimaries, @@ -343,6 +372,11 @@ static void mxf_free_metadataset(MXFMetadataSet **ctx, int freectx) av_freep(&((MXFDescriptor *)*ctx)->mastering); av_freep(&((MXFDescriptor *)*ctx)->coll); av_freep(&((MXFDescriptor *)*ctx)->file_descriptors_refs); + av_freep(&((MXFDescriptor *)*ctx)->sub_descriptors_refs); + break; + case MCASubDescriptor: + if (((MXFMCASubDescriptor *)*ctx)->language) + av_freep(&((MXFMCASubDescriptor *)*ctx)->language); break; case Sequence: av_freep(&((MXFSequence *)*ctx)->structural_components_refs); @@ -906,6 +940,30 @@ static int mxf_read_strong_ref_array(AVIOContext *pb, UID **refs, int *count) return 0; } +static inline int mxf_read_us_ascii_string(AVIOContext *pb, int size, char** str) +{ + int ret; + size_t buf_size; + + if (size < 0 || size > INT_MAX - 1) + return AVERROR(EINVAL); + + buf_size = size + 1; + av_free(*str); + *str = av_malloc(buf_size); + if (!*str) + return AVERROR(ENOMEM); + + ret = avio_get_str(pb, size, *str, buf_size); + + if (ret < 0) { + av_freep(str); + return ret; + } + + return ret; +} + static inline int mxf_read_utf16_string(AVIOContext *pb, int size, char** str, int be) { int ret; @@ -1360,11 +1418,34 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int descriptor->coll->MaxFALL = avio_rb16(pb); } } + + if (IS_KLV_KEY(uid, mxf_sub_descriptor)) + mxf_read_strong_ref_array(pb, &descriptor->sub_descriptors_refs, &descriptor->sub_descriptors_count); + break; } return 0; } +static int mxf_read_mca_sub_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) +{ + MXFMCASubDescriptor *mca_sub_descriptor = arg; + + if (IS_KLV_KEY(uid, mxf_mca_label_dictionary_id)) + avio_read(pb, mca_sub_descriptor->mca_label_dictionary_id, 16); + + if (IS_KLV_KEY(uid, mxf_mca_link_id)) + avio_read(pb, mca_sub_descriptor->mca_link_id, 16); + + if (IS_KLV_KEY(uid, mxf_soundfield_group_link_id)) + avio_read(pb, mca_sub_descriptor->mca_group_link_id, 16); + + if (IS_KLV_KEY(uid, mxf_mca_rfc5646_spoken_language)) + return mxf_read_us_ascii_string(pb, size, &mca_sub_descriptor->language); + + return 0; +} + static int mxf_read_indirect_value(void *arg, AVIOContext *pb, int size) { MXFTaggedValue *tagged_value = arg; @@ -1494,6 +1575,56 @@ static const MXFCodecUL mxf_data_essence_container_uls[] = { { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, }; +typedef struct MXFSoundfieldGroupUL { + UID uid; + int64_t id; +} MXFSoundfieldGroupUL; + +static const MXFSoundfieldGroupUL mxf_soundfield_groups[] = { + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, AV_CH_LAYOUT_5POINT1 }, // 5.1 + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x02,0x00,0x00,0x00,0x00 }, AV_CH_LAYOUT_7POINT1 }, // 7.1 DS + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x03,0x00,0x00,0x00,0x00 }, AV_CH_LAYOUT_7POINT1_WIDE }, // 7.1 SDS + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x04,0x00,0x00,0x00,0x00 }, AV_CH_LAYOUT_6POINT1 }, // 6.1 + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x05,0x00,0x00,0x00,0x00 }, AV_CH_LAYOUT_MONO }, // 1.0 Monoral + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x01,0x00,0x00,0x00 }, AV_CH_LAYOUT_STEREO }, // Standard stereo + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x02,0x00,0x00,0x00 }, AV_CH_LAYOUT_STEREO }, // Dual mono + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x04,0x00,0x00,0x00 }, AV_CH_LAYOUT_SURROUND }, // 3.0 + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x05,0x00,0x00,0x00 }, AV_CH_LAYOUT_4POINT0 }, // 4.0 + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x06,0x00,0x00,0x00 }, AV_CH_LAYOUT_5POINT0 }, // 5.0 + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x07,0x00,0x00,0x00 }, AV_CH_LAYOUT_6POINT0 }, // 6.0 + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x08,0x00,0x00,0x00 }, AV_CH_LAYOUT_7POINT0 }, // 7.0 + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x09,0x00,0x00,0x00 }, AV_CH_LAYOUT_STEREO }, // LrRt + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x0a,0x00,0x00,0x00 }, AV_CH_LAYOUT_5POINT1 }, // 5.1 EX + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x0b,0x00,0x00,0x00 }, AV_CH_LAYOUT_MONO }, // Hearing accessibility + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x0c,0x00,0x00,0x00 }, AV_CH_LAYOUT_MONO }, // Visual accessibility + { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0 }, +}; + +typedef struct MXFChannelOrderingUL { + UID uid; + int index; + enum AVAudioServiceType service_type; +} MXFChannelOrderingUL; + +static const MXFChannelOrderingUL mxf_channel_ordering[] = { + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00 }, 0, AV_AUDIO_SERVICE_TYPE_NB }, // Left audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x02,0x00,0x00,0x00,0x00 }, 1, AV_AUDIO_SERVICE_TYPE_NB }, // Right audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x03,0x00,0x00,0x00,0x00 }, 2, AV_AUDIO_SERVICE_TYPE_NB }, // Center audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x04,0x00,0x00,0x00,0x00 }, 5, AV_AUDIO_SERVICE_TYPE_NB }, // LFE audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x05,0x00,0x00,0x00,0x00 }, 3, AV_AUDIO_SERVICE_TYPE_NB }, // Left surround audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x06,0x00,0x00,0x00,0x00 }, 4, AV_AUDIO_SERVICE_TYPE_NB }, // Right surround audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x07,0x00,0x00,0x00,0x00 }, 3, AV_AUDIO_SERVICE_TYPE_NB }, // Left side surround audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x08,0x00,0x00,0x00,0x00 }, 4, AV_AUDIO_SERVICE_TYPE_NB }, // Right side surround audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x09,0x00,0x00,0x00,0x00 }, 6, AV_AUDIO_SERVICE_TYPE_NB }, // Left rear surround audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0a,0x00,0x00,0x00,0x00 }, 7, AV_AUDIO_SERVICE_TYPE_NB }, // Right rear surround audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0b,0x00,0x00,0x00,0x00 }, 6, AV_AUDIO_SERVICE_TYPE_NB }, // Left center audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0c,0x00,0x00,0x00,0x00 }, 7, AV_AUDIO_SERVICE_TYPE_NB }, // Right center audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0d,0x00,0x00,0x00,0x00 }, 6, AV_AUDIO_SERVICE_TYPE_NB }, // Center surround audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0e,0x00,0x00,0x00,0x00 }, 0, AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED }, // Hearing impaired audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0f,0x00,0x00,0x00,0x00 }, 0, AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED }, // Visually impaired narrative audio channel + { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_AUDIO_SERVICE_TYPE_NB }, +}; + static MXFWrappingScheme mxf_get_wrapping_kind(UID *essence_container_ul) { int val; @@ -2292,6 +2423,27 @@ static enum AVColorRange mxf_get_color_range(MXFContext *mxf, MXFDescriptor *des return AVCOL_RANGE_UNSPECIFIED; } +static int is_pcm(enum AVCodecID codec_id) +{ + /* we only care about "normal" PCM codecs until we get samples */ + return codec_id >= AV_CODEC_ID_PCM_S16LE && codec_id < AV_CODEC_ID_PCM_S24DAUD; +} + +static int set_language(AVFormatContext *s, const char *rfc5646, AVDictionary **met) +{ + // language abbr should contain at least 2 chars + if (rfc5646 && strlen(rfc5646) > 1) { + char primary_tag[4] = + {rfc5646[0], rfc5646[1], rfc5646[2] != '-' ? rfc5646[2] : '\0', '\0'}; + + const char *iso6392 = ff_convert_lang_to(primary_tag, + AV_LANG_ISO639_2_BIBL); + if (iso6392) + return(av_dict_set(met, "language", iso6392, 0)); + } + return 0; +} + static int mxf_parse_structural_metadata(MXFContext *mxf) { MXFPackage *material_package = NULL; @@ -2329,6 +2481,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) FFStream *sti; AVTimecode tc; int flags; + int current_channel; if (!(material_track = mxf_resolve_strong_ref(mxf, &material_package->tracks_refs[i], Track))) { av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track strong ref\n"); @@ -2688,6 +2841,107 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) sti->need_parsing = AVSTREAM_PARSE_FULL; } st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id); + + current_channel = 0; + + if (descriptor->channels >= FF_SANE_NB_CHANNELS) { + av_log(mxf->fc, AV_LOG_ERROR, "max number of channels %d reached\n", FF_SANE_NB_CHANNELS); + return AVERROR_INVALIDDATA; + } + + for (j = 0; j < descriptor->channels; ++j) { + source_track->channel_ordering[j] = j; + } + + for (j = 0; j < descriptor->sub_descriptors_count; j++) { + MXFMCASubDescriptor *mca_sub_descriptor = mxf_resolve_strong_ref(mxf, &descriptor->sub_descriptors_refs[j], MCASubDescriptor); + if (mca_sub_descriptor == NULL) { + continue; + } + + // Soundfield group + if (IS_KLV_KEY(mca_sub_descriptor->mca_label_dictionary_id, mxf_soundfield_group)) { + const MXFSoundfieldGroupUL* group_ptr = mxf_soundfield_groups; + + while (group_ptr->uid[0]) { + if (IS_KLV_KEY(group_ptr->uid, mca_sub_descriptor->mca_label_dictionary_id)) { + st->codecpar->channel_layout = group_ptr->id; + break; + } + group_ptr++; + } + } + + // Audio channel + if (IS_KLV_KEY(mca_sub_descriptor->mca_label_dictionary_id, mxf_audio_channel)) { + const MXFChannelOrderingUL* channel_ordering_ptr = mxf_channel_ordering; + + while (channel_ordering_ptr->uid[0]) { + if (IS_KLV_KEY(channel_ordering_ptr->uid, mca_sub_descriptor->mca_label_dictionary_id)) { + if (current_channel >= FF_SANE_NB_CHANNELS) { + av_log(mxf->fc, AV_LOG_ERROR, "max number of channels %d reached\n", FF_SANE_NB_CHANNELS); + return AVERROR_INVALIDDATA; + } + if (channel_ordering_ptr->index >= FF_SANE_NB_CHANNELS) { + av_log(mxf->fc, AV_LOG_ERROR, "mapping to channel index %d out of range, maximum is %d\n", channel_ordering_ptr->index, FF_SANE_NB_CHANNELS); + return AVERROR_INVALIDDATA; + } + source_track->channel_ordering[current_channel] = channel_ordering_ptr->index; + + if(channel_ordering_ptr->service_type != AV_AUDIO_SERVICE_TYPE_NB) { + enum AVAudioServiceType *ast; + uint8_t* side_data = av_stream_new_side_data(st, AV_PKT_DATA_AUDIO_SERVICE_TYPE, sizeof(*ast)); + if (!side_data) + goto fail_and_free; + ast = (enum AVAudioServiceType*)side_data; + *ast = channel_ordering_ptr->service_type; + } + + current_channel += 1; + break; + } + channel_ordering_ptr++; + } + } + + // set language from MCA spoken language information + if (mca_sub_descriptor->language) { + ret = set_language(mxf->fc, mca_sub_descriptor->language, &st->metadata); + if (ret < 0) { + return ret; + } + } + } + + // check if the mapping is not required + source_track->require_reordering = 0; + for (j = 0; j < descriptor->channels; ++j) { + if (source_track->channel_ordering[j] != j) { + if (!is_pcm(st->codecpar->codec_id) || mxf->skip_audio_reordering) { + av_log(mxf->fc, AV_LOG_WARNING, "Skipping channel reordering!\n"); + st->codecpar->channel_layout = 0; + } else { + source_track->require_reordering = 1; + } + break; + } + } + + if (source_track->require_reordering) { + current_channel = 0; + av_log(mxf->fc, AV_LOG_DEBUG, "MCA Audio mapping ("); + for(j = 0; j < descriptor->channels; ++j) { + for(int k = 0; k < descriptor->channels; ++k) { + if(source_track->channel_ordering[k] == current_channel) { + av_log(mxf->fc, AV_LOG_DEBUG, "%d -> %d", source_track->channel_ordering[k], k); + if (current_channel != descriptor->channels - 1) + av_log(mxf->fc, AV_LOG_DEBUG, ", "); + current_channel += 1; + } + } + } + av_log(mxf->fc, AV_LOG_DEBUG, ")\n"); + } } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) { enum AVMediaType type; container_ul = mxf_get_codec_ul(mxf_data_essence_container_uls, essence_container_ul); @@ -2888,6 +3142,8 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = { { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5c,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* VANC/VBI - SMPTE 436M */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5e,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* MPEG2AudioDescriptor */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x64,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* DC Timed Text Descriptor */ + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6c,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), MCASubDescriptor }, /* Soundfield Group Label Subdescriptor */ + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6b,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), MCASubDescriptor }, /* Audio Channel Label Subdescriptor */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Static Track */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Generic Track */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x14,0x00 }, mxf_read_timecode_component, sizeof(MXFTimecodeComponent), TimecodeComponent }, @@ -3187,12 +3443,6 @@ static void mxf_compute_essence_containers(AVFormatContext *s) } } -static int is_pcm(enum AVCodecID codec_id) -{ - /* we only care about "normal" PCM codecs until we get samples */ - return codec_id >= AV_CODEC_ID_PCM_S16LE && codec_id < AV_CODEC_ID_PCM_S24DAUD; -} - static MXFIndexTable *mxf_find_index_table(MXFContext *mxf, int index_sid) { int i; @@ -3619,6 +3869,25 @@ static int mxf_set_pts(MXFContext *mxf, AVStream *st, AVPacket *pkt) return 0; } +static int mxf_audio_remapping(int* channel_ordering, uint8_t* data, int size, int sample_size, int channels) +{ + int sample_offset = channels * sample_size; + int number_of_samples = size / sample_offset; + uint8_t tmp[FF_SANE_NB_CHANNELS * 4]; + uint8_t* data_ptr = data; + + for (int sample = 0; sample < number_of_samples; ++sample) { + memcpy(tmp, data_ptr, sample_offset); + + for (int channel = 0; channel < channels; ++channel) { + memcpy(&data_ptr[sample_size * channel_ordering[channel]], &tmp[sample_size * channel], sample_size); + } + + data_ptr += sample_offset; + } + return 0; +} + static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) { KLVPacket klv; @@ -3733,6 +4002,15 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) return ret; } + // for audio, process audio remapping if MCA label requires it + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && track->require_reordering) { + int byte_per_sample = st->codecpar->bits_per_coded_sample / 8; + ret = mxf_audio_remapping(track->channel_ordering, pkt->data, pkt->size, byte_per_sample, st->codecpar->channels); + if (ret < 0) { + return ret; + } + } + /* seek for truncated packets */ avio_seek(s->pb, klv.next_klv, SEEK_SET); @@ -3920,6 +4198,9 @@ static const AVOption options[] = { { "eia608_extract", "extract eia 608 captions from s436m track", offsetof(MXFContext, eia608_extract), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, + { "skip_audio_reordering", "skip audio reordering based on Multi-Channel Audio labelling", + offsetof(MXFContext, skip_audio_reordering), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, + AV_OPT_FLAG_DECODING_PARAM }, { NULL }, }; diff --git a/libavformat/version.h b/libavformat/version.h index 0705ee4112..21ca6ed096 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -33,7 +33,7 @@ // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 #define LIBAVFORMAT_VERSION_MINOR 9 -#define LIBAVFORMAT_VERSION_MICRO 102 +#define LIBAVFORMAT_VERSION_MICRO 103 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From patchwork Mon Nov 29 00:59:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 31788 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:d206:0:0:0:0:0 with SMTP id q6csp5463154iob; Sun, 28 Nov 2021 16:59:42 -0800 (PST) X-Google-Smtp-Source: ABdhPJxC7sHXUTmzDWvOIlYICk0wckR38rQGm4U70z2FiNY2XwenyRFonUahSbRsUq3dFBQjK3GT X-Received: by 2002:a05:6402:40d2:: with SMTP id z18mr69651105edb.395.1638147582656; Sun, 28 Nov 2021 16:59:42 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1638147582; cv=none; d=google.com; s=arc-20160816; b=MbiLovoO+8QW8NqUDYrWm53pmeYGWNbHK3yR31/ZXpCxdqwz+ZHhI1uBZk8qBhNnM6 OPM4RjcIXd1fD5u+x8YnAvUPt4cOTZjWBjpdg1VIFT1DIQ6g6z3+WGrmYp0yCICmYNQ5 VwrdHLph1S8CE3zWS9c6rMeQZaQzZEb3RxaZ4JEnJV2RUQGqn3FKxFW+34UT+ixoc19G RbOD8I/0g+zI7w7VQ2I/fyU94gnju9tCe1OplkBC+2HlrbupHkMKHXgvsoSvIge8IxT5 91+yepzKDf8hONZksguwcxY/vP9kUskwuE58mpINQzRxeIfGnCgZO7RZMr2UFgbq5eXW 12mg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=W2FQhdUhvjzSnPC7SzTdxuleAUj8fW1tK5711Bv7myk=; b=0jpYBq41a0qGIYoV1dHPZB4v56KfwKeds26uavRkjqp7guXyvGx3HlyoXs+Zg04pzA 8x8FqEwPUdRgj5kPJE7RYRZddWXmqmIG8A4amKSi2bN8xmHBRhezbfuvzprQk1JV8/7w pI3navIRSxIneqc/xFBQVybl72A/voBhAA6D+OSZSevoCkmLuvGkLP1ClPrnHyteyukc evGRmL64EE9xxjBHuytsl3Rio+Q1Gmh4OzmsiURdNPUl+t3vyZa81qJinUKBa2R42Qnh sAcb3LBv++hgxEC5Eylj6pb5pEP2hps3PXbnmrMxRoFv9Kjycs/OutTOEwubqm5Rr1ne Y4ZA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id ho42si29660765ejc.50.2021.11.28.16.59.42; Sun, 28 Nov 2021 16:59:42 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id B872768AD50; Mon, 29 Nov 2021 02:59:39 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id C2D23680C04 for ; Mon, 29 Nov 2021 02:59:32 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 421A7E6427 for ; Mon, 29 Nov 2021 01:59:32 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id iuOkYj8wsais for ; Mon, 29 Nov 2021 01:59:31 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id DECDCE6420 for ; Mon, 29 Nov 2021 01:59:30 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Mon, 29 Nov 2021 01:59:27 +0100 Message-Id: <20211129005930.7188-2-cus@passwd.hu> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211129005930.7188-1-cus@passwd.hu> References: <1b5e45c8-574a-c0d3-cf2-11963ad25cc1@passwd.hu> <20211129005930.7188-1-cus@passwd.hu> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/5] avformat/mxfdec: remove uneeded check before av_freep X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: Ru7z4a3j6olg Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 58ba330475..8cb66b73c4 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -375,8 +375,7 @@ static void mxf_free_metadataset(MXFMetadataSet **ctx, int freectx) av_freep(&((MXFDescriptor *)*ctx)->sub_descriptors_refs); break; case MCASubDescriptor: - if (((MXFMCASubDescriptor *)*ctx)->language) - av_freep(&((MXFMCASubDescriptor *)*ctx)->language); + av_freep(&((MXFMCASubDescriptor *)*ctx)->language); break; case Sequence: av_freep(&((MXFSequence *)*ctx)->structural_components_refs); From patchwork Mon Nov 29 00:59:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 31789 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:d206:0:0:0:0:0 with SMTP id q6csp5463471iob; Sun, 28 Nov 2021 17:00:02 -0800 (PST) X-Google-Smtp-Source: ABdhPJzIN/nd8jWQzWnto9pi28tgTYsvHDgjOdXsAfwgKFAfC8bjkTaPwhx/YqjKe7V5EvU0WPhi X-Received: by 2002:a05:6402:34d6:: with SMTP id w22mr71373661edc.35.1638147602322; Sun, 28 Nov 2021 17:00:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1638147602; cv=none; d=google.com; s=arc-20160816; b=MEmCJR4GIf2pOvfkShQrDcm3pH0+h3e3Qp+//H94kK4bVNDZ9yYN2oacXlcr9lrQXk XJaXOPVZA0RwXUiri7NU5AZ6KZe3dLtPjc5M18ab8ojoREdszG1ZLBcmxT8CkvycdqAJ s7l2jG526ehP8LvzLBt9H4rPjPYwySxnBSh7Njy+EwJOckoFUPIYlfF5NnnwAuz8bGFo jo+nHfKgYLvPi+uLN0in7ZQsWY9aOVQwfs7GDtJjmDmQgQWtotFaeh7G2s0ohQutDcoF MkNkewPnuzpnpgcrecYqVz6NCn1YfWk4t7j67Tyyp6oLhvaJsqH4UMHKLbjgje+Nc2l1 C2ZA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=kukJpARd12Vu4QLmjxjH/7MkT8IYIY0HDLxJCjM0Tbc=; b=MRITNoNb5FyIniWXrKxZgcw5A2AQ++UNyJRkJxz+OCEXXXp9go42q3VYToncDdbccS aQZHGjP6ExvU9JViiKU/df4GwIfk1/fVh46YqX0BKXiQQ7v2Zh15dkmJkIuPq1U15beb VDSdafYIRzFw9r8bbckiu8SdKvhRR+A3mDWACQjT4RE5lN54OoFGgXdW91X4Cm2Bc+NK AViXPmm5asG7G/SSsdlLYJ3uuGtt5bQhFo3BmNp5Cj1iBvV8dmJfd8T4WpD4zy9mofNu POPvgw+/R/CK1jRjWcQWetNM2cu20N1bmylydvoz4xsY3PS60S7zwPc4KTPJpcC98pia +Qfw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id l10si16992199ejz.697.2021.11.28.17.00.02; Sun, 28 Nov 2021 17:00:02 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DCBEB68ADE7; Mon, 29 Nov 2021 02:59:43 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 18FF868AD8B for ; Mon, 29 Nov 2021 02:59:35 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 7DD6AE6428 for ; Mon, 29 Nov 2021 01:59:34 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Pg-Yb0uMB9zN for ; Mon, 29 Nov 2021 01:59:32 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 14819E6421 for ; Mon, 29 Nov 2021 01:59:31 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Mon, 29 Nov 2021 01:59:28 +0100 Message-Id: <20211129005930.7188-3-cus@passwd.hu> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211129005930.7188-1-cus@passwd.hu> References: <1b5e45c8-574a-c0d3-cf2-11963ad25cc1@passwd.hu> <20211129005930.7188-1-cus@passwd.hu> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/5] avformat/mxfdec: also check for non-positive number of channels X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: DiPeYJEcrK8u Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 8cb66b73c4..e0a52e3883 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -2843,8 +2843,8 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) current_channel = 0; - if (descriptor->channels >= FF_SANE_NB_CHANNELS) { - av_log(mxf->fc, AV_LOG_ERROR, "max number of channels %d reached\n", FF_SANE_NB_CHANNELS); + if (descriptor->channels <= 0 || descriptor->channels >= FF_SANE_NB_CHANNELS) { + av_log(mxf->fc, AV_LOG_ERROR, "Invalid number of channels %d, must be less than %d\n", descriptor->channels, FF_SANE_NB_CHANNELS); return AVERROR_INVALIDDATA; } From patchwork Mon Nov 29 00:59:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 31792 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:d206:0:0:0:0:0 with SMTP id q6csp5463699iob; Sun, 28 Nov 2021 17:00:14 -0800 (PST) X-Google-Smtp-Source: ABdhPJwnh++3cpRfQoqizJfm3iQhrPZnY/tMAXNVNM4JyXI5e1XYDF2mYkLhdWCVqTIc/9+Gq+ZF X-Received: by 2002:a05:6402:1d50:: with SMTP id dz16mr69051866edb.385.1638147614354; Sun, 28 Nov 2021 17:00:14 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1638147614; cv=none; d=google.com; s=arc-20160816; b=JRorpUgni+uSjAsvUMrbOwUpMnz1+wt9VB/zUc3oj31/8RJZ46NcAkoftopO/0nEG9 TvT4vsCXbFRxVgUriG+yzj1X3ArLQWlo6KyGHGUavTluA1PZGpXX5zb38V2WyzfRKdIV uzw/i/DwL5kSdNo2lypa2KOzvKWJIWCofezI/aBKaZX9if81lVkJHKLrOizzmx8ls9oT Q0SZa349LrgaNbfyvpl/bzV0tRsbIbdRjOi1wVGRyharMtWCR8XhhWqYrhlD8+Ma58hV GO1Z2VWSRgRMiMBLrT9ctJDoS7IcWTBxf+NR/+rJrQqojmDP7iwgHR6+hQhhZP5Y3rP6 yw2g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=O35EHcMycBgTxWAwjzdyfs0MAetxynlRUrtoY4Dv/XI=; b=j7Qk02Gc9+t50uWrg0J31HOwaaUTwmty/jBtCpeGjSIU9tfKKPkcUHyLZokRRjlvgp eqp7c6EwTP1T287WpqSt/oM3wthqQn3sdWslenBDRv1aRmovj33CIl+M60sAfTE2jyDA OPEsGnTmYkSiIztwDFFU45Cpe5UkkCTsvsq5D/u0ng+5/cYCxXtIqlBYwyoAakCuQDB3 BsIWaFZ9jl8nnIuFFdWMg7lg5UiY6JxbQ4Ccdkw5afTaMSwvLoTTH0I01242nZdNnmlr PEGUCyYdyzZ6KnyVeMpUWlYd0PdoiLh/Ij5aTZ88b/Zn8cAbYFqfv0j7Egy44FaPsU9l qg4A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id k23si20325456edk.555.2021.11.28.17.00.13; Sun, 28 Nov 2021 17:00:14 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id C214868AE33; Mon, 29 Nov 2021 02:59:44 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9E12168ACC3 for ; Mon, 29 Nov 2021 02:59:35 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 1AD05E44A4 for ; Mon, 29 Nov 2021 01:59:35 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id MBPkrxg1Z5PI for ; Mon, 29 Nov 2021 01:59:33 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 27EA9E6425 for ; Mon, 29 Nov 2021 01:59:31 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Mon, 29 Nov 2021 01:59:29 +0100 Message-Id: <20211129005930.7188-4-cus@passwd.hu> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211129005930.7188-1-cus@passwd.hu> References: <1b5e45c8-574a-c0d3-cf2-11963ad25cc1@passwd.hu> <20211129005930.7188-1-cus@passwd.hu> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 4/5] avformat/mxfdec: do not ignore mxf_read_strong_ref_array return value when reading sub descriptors X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 9blsSU8v1KDh Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index e0a52e3883..229c02a85e 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1419,7 +1419,7 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int } if (IS_KLV_KEY(uid, mxf_sub_descriptor)) - mxf_read_strong_ref_array(pb, &descriptor->sub_descriptors_refs, &descriptor->sub_descriptors_count); + return mxf_read_strong_ref_array(pb, &descriptor->sub_descriptors_refs, &descriptor->sub_descriptors_count); break; } From patchwork Mon Nov 29 00:59:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 31791 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:d206:0:0:0:0:0 with SMTP id q6csp5463971iob; Sun, 28 Nov 2021 17:00:27 -0800 (PST) X-Google-Smtp-Source: ABdhPJzPWrAvzNL0t1Wf9icBkvaRI4H63+kCIEBIwlr3kX9xP9E8SMAoWzaAAP89z/OAm5cd/gHh X-Received: by 2002:a17:907:9256:: with SMTP id kb22mr58846465ejb.423.1638147627070; Sun, 28 Nov 2021 17:00:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1638147627; cv=none; d=google.com; s=arc-20160816; b=F/59yvc/dL38sxMjiF1rmsDbK12g3JJPxVQyRwLy1x0p1pXvjgmd0Pnm0Bfz76H+Md yHG1c/OAPYUmUJa+6hdoLTMo4jyl6Ln8FAlNt2Ub3TfqWohKMNYGQAJOg0PAF3s6ISyv zO+SHNL9tYSkXwe+ymrb0LvnLPuTPB39SZJrr170Dh6Ni6nV11Oymfg/8iKXa/zhiGqL /MrVX8045oquY9SX+m1ojHsgEQD+In+edpoPOZM3ka9UEUgG0Nm2teO4rz5gV7xho6wP YcdEdtyBqpLCe+kJWE+O66u3ToN5m3gvE0IdJwaTriJka9VGvH8lcRiWNxKPPxCEKsPc 36Kw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=2xNx/D/X0+Dx63HFLJdsmfWa3t6ph6F+GoEIMXo2RO0=; b=CyvHIu9vhCfzHmN9N31+3C9EO/vYoKO2X5bsybBJR29/NDRcUnJBcXe+S/OmBw76NI rJNKdqpwe7anmZiTQCcEoRIGIqGxU1FB5mN8pt1lCxnIQ4Clfq8sXyGZlipqzeBoChvJ GQ3p7DWiww0ssON0d+4/QxKBfFzfmgqxfUujahZnLlLGf9TBGW3XJY0szjiZqpaHzmBh e43yEAYwVx3d5YeJVEIEYZ4B+OxeLzH8zBRn7gefxSoGeLUQxCwB2WZEK14QRqKNhViu k7dG9OGQFqLkCtPyAFRC+FYd7lcQ/bZ/+SUq1sXuStjE2mrn+1I3Tw2MBXDsQPeJv8uD PAGA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id gb42si22631204ejc.415.2021.11.28.17.00.26; Sun, 28 Nov 2021 17:00:27 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id B45A968ADD1; Mon, 29 Nov 2021 02:59:49 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9B09068ADC0 for ; Mon, 29 Nov 2021 02:59:37 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 0EB6FE6421 for ; Mon, 29 Nov 2021 01:59:37 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id o9x6dQAeba36 for ; Mon, 29 Nov 2021 01:59:34 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 63D97E6426 for ; Mon, 29 Nov 2021 01:59:31 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Mon, 29 Nov 2021 01:59:30 +0100 Message-Id: <20211129005930.7188-5-cus@passwd.hu> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211129005930.7188-1-cus@passwd.hu> References: <1b5e45c8-574a-c0d3-cf2-11963ad25cc1@passwd.hu> <20211129005930.7188-1-cus@passwd.hu> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 5/5] avformat/mxfdec: rework MCA channel layout parsing X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 3JI+y2na4ifP Setting the channel layout was based on SoundfieldGroupLabelSubDescriptor, but this was wrong, because soundfield groups are not necessarily used and a file can also contain e.g. a single channel of a multichannel audio. The new approach is to parse every AudioChannelLabelSubDescriptor and create a channel layout based on those. We should also make sure that we only provide a channel layout if every channel designation is recognized and is supported. If a designation is not supported, or if a channel designation is used more than once (e.g. multiple languages) we fall back to the unknown channel layout. MCA channel ID was also ignored previously, that should have been used to determine which AudioChannelLabelSubDescriptor references which audio channel. This is also fixed now. The new parsing code also detects ambigous language or service types, and only set these metadata if all channels have the same value. Soundfield groups are now only used for determinig the language of the tracks, if it is not provided in the AudioChannelLabelSubDescriptor. Track sub descriptors not necessarily contain the references to their soundfield groups, so pairing of the soundfield group with a channel is now based on MCA group link ID. The language of the first GroupOfSoundfieldGroups which a SoundfieldGroup is part of is also considered if the SoundfieldGroup has no language metadata. Signed-off-by: Marton Balint --- libavformat/mxf.h | 4 +- libavformat/mxfdec.c | 333 ++++++++++++++++++++++++------------------- 2 files changed, 191 insertions(+), 146 deletions(-) diff --git a/libavformat/mxf.h b/libavformat/mxf.h index cddbcb13c9..d53a16df51 100644 --- a/libavformat/mxf.h +++ b/libavformat/mxf.h @@ -50,7 +50,9 @@ enum MXFMetadataSetType { TaggedValue, TapeDescriptor, AVCSubDescriptor, - MCASubDescriptor, + AudioChannelLabelSubDescriptor, + SoundfieldGroupLabelSubDescriptor, + GroupOfSoundfieldGroupsLabelSubDescriptor, }; enum MXFFrameLayout { diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 229c02a85e..6e1da75542 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -228,8 +228,11 @@ typedef struct MXFMCASubDescriptor { MXFMetadataSet meta; UID uid; UID mca_link_id; - UID mca_group_link_id; + UID soundfield_group_link_id; + UID *group_of_soundfield_groups_link_id_refs; + int group_of_soundfield_groups_link_id_count; UID mca_label_dictionary_id; + int mca_channel_id; char *language; } MXFMCASubDescriptor; @@ -328,8 +331,6 @@ static const uint8_t mxf_system_item_key_cp[] = { 0x06,0x0e,0x2b,0x static const uint8_t mxf_system_item_key_gc[] = { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x03,0x01,0x14 }; static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x34 }; static const uint8_t mxf_apple_coll_prefix[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x0e,0x20,0x04,0x01,0x05,0x03,0x01 }; -static const uint8_t mxf_audio_channel[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01 }; -static const uint8_t mxf_soundfield_group[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02 }; /* complete keys to match */ static const uint8_t mxf_crypto_source_container_ul[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x02,0x02,0x00,0x00,0x00 }; @@ -346,7 +347,9 @@ static const uint8_t mxf_apple_coll_max_fall[] = { 0x06,0x0e,0x2b,0x static const uint8_t mxf_mca_label_dictionary_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x01,0x00,0x00,0x00 }; static const uint8_t mxf_mca_tag_symbol[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x02,0x00,0x00,0x00 }; static const uint8_t mxf_mca_tag_name[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x03,0x00,0x00,0x00 }; +static const uint8_t mxf_group_of_soundfield_groups_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x04,0x00,0x00,0x00 }; static const uint8_t mxf_mca_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x05,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_channel_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x04,0x0a,0x00,0x00,0x00,0x00 }; static const uint8_t mxf_soundfield_group_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x06,0x00,0x00,0x00 }; static const uint8_t mxf_mca_rfc5646_spoken_language[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0d,0x03,0x01,0x01,0x02,0x03,0x15,0x00,0x00 }; @@ -374,8 +377,11 @@ static void mxf_free_metadataset(MXFMetadataSet **ctx, int freectx) av_freep(&((MXFDescriptor *)*ctx)->file_descriptors_refs); av_freep(&((MXFDescriptor *)*ctx)->sub_descriptors_refs); break; - case MCASubDescriptor: + case AudioChannelLabelSubDescriptor: + case SoundfieldGroupLabelSubDescriptor: + case GroupOfSoundfieldGroupsLabelSubDescriptor: av_freep(&((MXFMCASubDescriptor *)*ctx)->language); + av_freep(&((MXFMCASubDescriptor *)*ctx)->group_of_soundfield_groups_link_id_refs); break; case Sequence: av_freep(&((MXFSequence *)*ctx)->structural_components_refs); @@ -1437,7 +1443,13 @@ static int mxf_read_mca_sub_descriptor(void *arg, AVIOContext *pb, int tag, int avio_read(pb, mca_sub_descriptor->mca_link_id, 16); if (IS_KLV_KEY(uid, mxf_soundfield_group_link_id)) - avio_read(pb, mca_sub_descriptor->mca_group_link_id, 16); + avio_read(pb, mca_sub_descriptor->soundfield_group_link_id, 16); + + if (IS_KLV_KEY(uid, mxf_group_of_soundfield_groups_link_id)) + return mxf_read_strong_ref_array(pb, &mca_sub_descriptor->group_of_soundfield_groups_link_id_refs, &mca_sub_descriptor->group_of_soundfield_groups_link_id_count); + + if (IS_KLV_KEY(uid, mxf_mca_channel_id)) + mca_sub_descriptor->mca_channel_id = avio_rb32(pb); if (IS_KLV_KEY(uid, mxf_mca_rfc5646_spoken_language)) return mxf_read_us_ascii_string(pb, size, &mca_sub_descriptor->language); @@ -1574,54 +1586,48 @@ static const MXFCodecUL mxf_data_essence_container_uls[] = { { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, }; -typedef struct MXFSoundfieldGroupUL { - UID uid; - int64_t id; -} MXFSoundfieldGroupUL; - -static const MXFSoundfieldGroupUL mxf_soundfield_groups[] = { - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, AV_CH_LAYOUT_5POINT1 }, // 5.1 - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x02,0x00,0x00,0x00,0x00 }, AV_CH_LAYOUT_7POINT1 }, // 7.1 DS - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x03,0x00,0x00,0x00,0x00 }, AV_CH_LAYOUT_7POINT1_WIDE }, // 7.1 SDS - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x04,0x00,0x00,0x00,0x00 }, AV_CH_LAYOUT_6POINT1 }, // 6.1 - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x05,0x00,0x00,0x00,0x00 }, AV_CH_LAYOUT_MONO }, // 1.0 Monoral - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x01,0x00,0x00,0x00 }, AV_CH_LAYOUT_STEREO }, // Standard stereo - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x02,0x00,0x00,0x00 }, AV_CH_LAYOUT_STEREO }, // Dual mono - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x04,0x00,0x00,0x00 }, AV_CH_LAYOUT_SURROUND }, // 3.0 - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x05,0x00,0x00,0x00 }, AV_CH_LAYOUT_4POINT0 }, // 4.0 - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x06,0x00,0x00,0x00 }, AV_CH_LAYOUT_5POINT0 }, // 5.0 - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x07,0x00,0x00,0x00 }, AV_CH_LAYOUT_6POINT0 }, // 6.0 - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x08,0x00,0x00,0x00 }, AV_CH_LAYOUT_7POINT0 }, // 7.0 - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x09,0x00,0x00,0x00 }, AV_CH_LAYOUT_STEREO }, // LrRt - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x0a,0x00,0x00,0x00 }, AV_CH_LAYOUT_5POINT1 }, // 5.1 EX - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x0b,0x00,0x00,0x00 }, AV_CH_LAYOUT_MONO }, // Hearing accessibility - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x02,0x20,0x0c,0x00,0x00,0x00 }, AV_CH_LAYOUT_MONO }, // Visual accessibility - { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0 }, -}; - typedef struct MXFChannelOrderingUL { UID uid; - int index; + uint64_t layout_mask; enum AVAudioServiceType service_type; } MXFChannelOrderingUL; static const MXFChannelOrderingUL mxf_channel_ordering[] = { - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00 }, 0, AV_AUDIO_SERVICE_TYPE_NB }, // Left audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x02,0x00,0x00,0x00,0x00 }, 1, AV_AUDIO_SERVICE_TYPE_NB }, // Right audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x03,0x00,0x00,0x00,0x00 }, 2, AV_AUDIO_SERVICE_TYPE_NB }, // Center audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x04,0x00,0x00,0x00,0x00 }, 5, AV_AUDIO_SERVICE_TYPE_NB }, // LFE audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x05,0x00,0x00,0x00,0x00 }, 3, AV_AUDIO_SERVICE_TYPE_NB }, // Left surround audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x06,0x00,0x00,0x00,0x00 }, 4, AV_AUDIO_SERVICE_TYPE_NB }, // Right surround audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x07,0x00,0x00,0x00,0x00 }, 3, AV_AUDIO_SERVICE_TYPE_NB }, // Left side surround audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x08,0x00,0x00,0x00,0x00 }, 4, AV_AUDIO_SERVICE_TYPE_NB }, // Right side surround audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x09,0x00,0x00,0x00,0x00 }, 6, AV_AUDIO_SERVICE_TYPE_NB }, // Left rear surround audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0a,0x00,0x00,0x00,0x00 }, 7, AV_AUDIO_SERVICE_TYPE_NB }, // Right rear surround audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0b,0x00,0x00,0x00,0x00 }, 6, AV_AUDIO_SERVICE_TYPE_NB }, // Left center audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0c,0x00,0x00,0x00,0x00 }, 7, AV_AUDIO_SERVICE_TYPE_NB }, // Right center audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0d,0x00,0x00,0x00,0x00 }, 6, AV_AUDIO_SERVICE_TYPE_NB }, // Center surround audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0e,0x00,0x00,0x00,0x00 }, 0, AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED }, // Hearing impaired audio channel - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0f,0x00,0x00,0x00,0x00 }, 0, AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED }, // Visually impaired narrative audio channel - { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_AUDIO_SERVICE_TYPE_NB }, + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x02,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x03,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x04,0x00,0x00,0x00,0x00 }, AV_CH_LOW_FREQUENCY, AV_AUDIO_SERVICE_TYPE_MAIN }, // Low Frequency Effects + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x05,0x00,0x00,0x00,0x00 }, AV_CH_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x06,0x00,0x00,0x00,0x00 }, AV_CH_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x07,0x00,0x00,0x00,0x00 }, AV_CH_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Side Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x08,0x00,0x00,0x00,0x00 }, AV_CH_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Side Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x09,0x00,0x00,0x00,0x00 }, AV_CH_BACK_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Rear Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0a,0x00,0x00,0x00,0x00 }, AV_CH_BACK_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Rear Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0b,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_LEFT_OF_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Center + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0c,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_RIGHT_OF_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Center + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0d,0x00,0x00,0x00,0x00 }, AV_CH_BACK_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0e,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED }, // Hearing impaired audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0f,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED }, // Visually impaired narrative audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x01,0x00,0x00 }, AV_CH_TOP_FRONT_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x02,0x00,0x00 }, AV_CH_TOP_FRONT_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x03,0x00,0x00 }, AV_CH_TOP_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x04,0x00,0x00 }, AV_CH_TOP_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x05,0x00,0x00 }, AV_CH_TOP_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x06,0x00,0x00 }, AV_CH_TOP_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Side Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x07,0x00,0x00 }, AV_CH_TOP_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Side Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x08,0x00,0x00 }, AV_CH_TOP_BACK_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Rear Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x09,0x00,0x00 }, AV_CH_TOP_BACK_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Rear Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0a,0x00,0x00 }, AV_CH_TOP_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Top Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0b,0x00,0x00 }, AV_CH_TOP_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Top Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0c,0x00,0x00 }, AV_CH_TOP_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Top Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0d,0x00,0x00 }, AV_CH_LOW_FREQUENCY, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Front Subwoofer + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0e,0x00,0x00 }, AV_CH_LOW_FREQUENCY_2, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Front Subwoofer + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0f,0x00,0x00 }, AV_CH_TOP_BACK_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Rear Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x10,0x00,0x00 }, AV_CH_BACK_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Rear + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x11,0x00,0x00 }, AV_CH_BOTTOM_FRONT_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Below + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x12,0x00,0x00 }, AV_CH_BOTTOM_FRONT_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Below + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x13,0x00,0x00 }, AV_CH_BOTTOM_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Below + { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_AUDIO_SERVICE_TYPE_NB }, }; static MXFWrappingScheme mxf_get_wrapping_kind(UID *essence_container_ul) @@ -2443,6 +2449,135 @@ static int set_language(AVFormatContext *s, const char *rfc5646, AVDictionary ** return 0; } +static MXFMCASubDescriptor *find_mca_link_id(MXFContext *mxf, enum MXFMetadataSetType type, UID *mca_link_id) +{ + for (int k = 0; k < mxf->metadata_sets_count; k++) { + MXFMCASubDescriptor *group = (MXFMCASubDescriptor*)mxf->metadata_sets[k]; + if (group->meta.type == type && !memcmp(&group->mca_link_id, mca_link_id, 16)) + return group; + } + return NULL; +} + +static int parse_mca_labels(MXFContext *mxf, MXFTrack *source_track, MXFDescriptor *descriptor, AVStream *st) +{ + uint64_t routing[FF_SANE_NB_CHANNELS] = {0}; + char *language = NULL; + int ambigous_language = 0; + enum AVAudioServiceType service_type = AV_AUDIO_SERVICE_TYPE_NB; + int ambigous_service_type = 0; + int has_channel_label = 0; + + for (int i = 0; i < descriptor->sub_descriptors_count; i++) { + char *channel_language; + + MXFMCASubDescriptor *label = mxf_resolve_strong_ref(mxf, &descriptor->sub_descriptors_refs[i], AudioChannelLabelSubDescriptor); + if (label == NULL) + continue; + + has_channel_label = 1; + for (const MXFChannelOrderingUL* channel_ordering = mxf_channel_ordering; channel_ordering->uid[0]; channel_ordering++) { + if (IS_KLV_KEY(channel_ordering->uid, label->mca_label_dictionary_id)) { + int target_channel = label->mca_channel_id; + if (target_channel == 0 && descriptor->channels == 1) + target_channel = 1; + if (target_channel <= 0 || target_channel > descriptor->channels) { + av_log(mxf->fc, AV_LOG_ERROR, "AudioChannelLabelSubDescriptor has invalid MCA channel ID %d\n", target_channel); + return AVERROR_INVALIDDATA; + } + routing[target_channel - 1] = channel_ordering->layout_mask; + if (service_type == AV_AUDIO_SERVICE_TYPE_NB) + service_type = channel_ordering->service_type; + else if (service_type != channel_ordering->service_type) + ambigous_service_type = 1; + break; + } + } + + channel_language = label->language; + if (!channel_language) { + MXFMCASubDescriptor *group = find_mca_link_id(mxf, SoundfieldGroupLabelSubDescriptor, &label->soundfield_group_link_id); + if (group) { + channel_language = group->language; + if (!channel_language && group->group_of_soundfield_groups_link_id_count) { + MXFMCASubDescriptor *supergroup = find_mca_link_id(mxf, GroupOfSoundfieldGroupsLabelSubDescriptor, + group->group_of_soundfield_groups_link_id_refs); + if (supergroup) + channel_language = supergroup->language; + } + } + } + if (channel_language) { + if (language && strcmp(language, channel_language)) + ambigous_language = 1; + else + language = channel_language; + } + } + + if (language && !ambigous_language) { + int ret = set_language(mxf->fc, language, &st->metadata); + if (ret < 0) + return ret; + } + + if (service_type != AV_AUDIO_SERVICE_TYPE_NB && service_type != AV_AUDIO_SERVICE_TYPE_MAIN && !ambigous_service_type) { + enum AVAudioServiceType *ast; + uint8_t* side_data = av_stream_new_side_data(st, AV_PKT_DATA_AUDIO_SERVICE_TYPE, sizeof(*ast)); + if (!side_data) + return AVERROR(ENOMEM); + ast = (enum AVAudioServiceType*)side_data; + *ast = service_type; + } + + if (has_channel_label) { + uint64_t channel_layout = 0; + int require_reorder = 0; + + for (int i = 0; i < descriptor->channels; i++) { + if (!routing[i]) { + av_log(mxf->fc, AV_LOG_WARNING, "Designation of audio channel %d in stream #%d is unknown or unsupported, " + "falling back to unknown channel layout\n", st->index, i); + return 0; + } + if (channel_layout & routing[i]) { + av_log(mxf->fc, AV_LOG_WARNING, "%s audio channel is used multiple times in stream #%d, " + "falling back to unknown channel layout\n", + av_get_channel_name(routing[i]), st->index); + return 0; + } + if (routing[i] < channel_layout) + require_reorder = 1; + channel_layout |= routing[i]; + } + + av_assert0(descriptor->channels == av_get_channel_layout_nb_channels(channel_layout)); + + if (require_reorder) { + if (mxf->skip_audio_reordering) + return 0; + if (!is_pcm(st->codecpar->codec_id)) { + av_log(mxf->fc, AV_LOG_WARNING, "Audio channel reordering for stream #%d is not supported because it is using a non-PCM codec, " + "falling back to unknown channel layout\n", st->index); + return 0; + } + av_log(mxf->fc, AV_LOG_VERBOSE, "MCA mapping for stream #%d: ", st->index); + for (int j = 0; j < descriptor->channels; j++) { + int reordered_channel = av_get_channel_layout_channel_index(channel_layout, routing[j]); + av_assert0(reordered_channel >= 0 && reordered_channel < descriptor->channels); + source_track->channel_ordering[j] = reordered_channel; + av_log(mxf->fc, AV_LOG_VERBOSE, "%s%s: %d->%d", j ? ", " : "", av_get_channel_name(routing[j]), j, reordered_channel); + } + av_log(mxf->fc, AV_LOG_VERBOSE, "\n"); + source_track->require_reordering = 1; + } + + st->codecpar->channel_layout = channel_layout; + } + + return 0; +} + static int mxf_parse_structural_metadata(MXFContext *mxf) { MXFPackage *material_package = NULL; @@ -2480,7 +2615,6 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) FFStream *sti; AVTimecode tc; int flags; - int current_channel; if (!(material_track = mxf_resolve_strong_ref(mxf, &material_package->tracks_refs[i], Track))) { av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track strong ref\n"); @@ -2841,106 +2975,14 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) } st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id); - current_channel = 0; - if (descriptor->channels <= 0 || descriptor->channels >= FF_SANE_NB_CHANNELS) { av_log(mxf->fc, AV_LOG_ERROR, "Invalid number of channels %d, must be less than %d\n", descriptor->channels, FF_SANE_NB_CHANNELS); return AVERROR_INVALIDDATA; } - for (j = 0; j < descriptor->channels; ++j) { - source_track->channel_ordering[j] = j; - } - - for (j = 0; j < descriptor->sub_descriptors_count; j++) { - MXFMCASubDescriptor *mca_sub_descriptor = mxf_resolve_strong_ref(mxf, &descriptor->sub_descriptors_refs[j], MCASubDescriptor); - if (mca_sub_descriptor == NULL) { - continue; - } - - // Soundfield group - if (IS_KLV_KEY(mca_sub_descriptor->mca_label_dictionary_id, mxf_soundfield_group)) { - const MXFSoundfieldGroupUL* group_ptr = mxf_soundfield_groups; - - while (group_ptr->uid[0]) { - if (IS_KLV_KEY(group_ptr->uid, mca_sub_descriptor->mca_label_dictionary_id)) { - st->codecpar->channel_layout = group_ptr->id; - break; - } - group_ptr++; - } - } - - // Audio channel - if (IS_KLV_KEY(mca_sub_descriptor->mca_label_dictionary_id, mxf_audio_channel)) { - const MXFChannelOrderingUL* channel_ordering_ptr = mxf_channel_ordering; - - while (channel_ordering_ptr->uid[0]) { - if (IS_KLV_KEY(channel_ordering_ptr->uid, mca_sub_descriptor->mca_label_dictionary_id)) { - if (current_channel >= FF_SANE_NB_CHANNELS) { - av_log(mxf->fc, AV_LOG_ERROR, "max number of channels %d reached\n", FF_SANE_NB_CHANNELS); - return AVERROR_INVALIDDATA; - } - if (channel_ordering_ptr->index >= FF_SANE_NB_CHANNELS) { - av_log(mxf->fc, AV_LOG_ERROR, "mapping to channel index %d out of range, maximum is %d\n", channel_ordering_ptr->index, FF_SANE_NB_CHANNELS); - return AVERROR_INVALIDDATA; - } - source_track->channel_ordering[current_channel] = channel_ordering_ptr->index; - - if(channel_ordering_ptr->service_type != AV_AUDIO_SERVICE_TYPE_NB) { - enum AVAudioServiceType *ast; - uint8_t* side_data = av_stream_new_side_data(st, AV_PKT_DATA_AUDIO_SERVICE_TYPE, sizeof(*ast)); - if (!side_data) - goto fail_and_free; - ast = (enum AVAudioServiceType*)side_data; - *ast = channel_ordering_ptr->service_type; - } - - current_channel += 1; - break; - } - channel_ordering_ptr++; - } - } - - // set language from MCA spoken language information - if (mca_sub_descriptor->language) { - ret = set_language(mxf->fc, mca_sub_descriptor->language, &st->metadata); - if (ret < 0) { - return ret; - } - } - } - - // check if the mapping is not required - source_track->require_reordering = 0; - for (j = 0; j < descriptor->channels; ++j) { - if (source_track->channel_ordering[j] != j) { - if (!is_pcm(st->codecpar->codec_id) || mxf->skip_audio_reordering) { - av_log(mxf->fc, AV_LOG_WARNING, "Skipping channel reordering!\n"); - st->codecpar->channel_layout = 0; - } else { - source_track->require_reordering = 1; - } - break; - } - } - - if (source_track->require_reordering) { - current_channel = 0; - av_log(mxf->fc, AV_LOG_DEBUG, "MCA Audio mapping ("); - for(j = 0; j < descriptor->channels; ++j) { - for(int k = 0; k < descriptor->channels; ++k) { - if(source_track->channel_ordering[k] == current_channel) { - av_log(mxf->fc, AV_LOG_DEBUG, "%d -> %d", source_track->channel_ordering[k], k); - if (current_channel != descriptor->channels - 1) - av_log(mxf->fc, AV_LOG_DEBUG, ", "); - current_channel += 1; - } - } - } - av_log(mxf->fc, AV_LOG_DEBUG, ")\n"); - } + ret = parse_mca_labels(mxf, source_track, descriptor, st); + if (ret < 0) + return ret; } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) { enum AVMediaType type; container_ul = mxf_get_codec_ul(mxf_data_essence_container_uls, essence_container_ul); @@ -3141,8 +3183,9 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = { { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5c,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* VANC/VBI - SMPTE 436M */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5e,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* MPEG2AudioDescriptor */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x64,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* DC Timed Text Descriptor */ - { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6c,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), MCASubDescriptor }, /* Soundfield Group Label Subdescriptor */ - { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6b,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), MCASubDescriptor }, /* Audio Channel Label Subdescriptor */ + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6b,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), AudioChannelLabelSubDescriptor }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6c,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), SoundfieldGroupLabelSubDescriptor }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6d,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), GroupOfSoundfieldGroupsLabelSubDescriptor }, { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Static Track */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Generic Track */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x14,0x00 }, mxf_read_timecode_component, sizeof(MXFTimecodeComponent), TimecodeComponent },