From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id 62E1F40F44 for ; Sat, 1 Jan 2022 23:13:26 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A70BA6801C5; Sun, 2 Jan 2022 01:13:23 +0200 (EET) Received: from mail-io1-f45.google.com (mail-io1-f45.google.com [209.85.166.45]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 36A386801C5 for ; Sun, 2 Jan 2022 01:13:17 +0200 (EET) Received: by mail-io1-f45.google.com with SMTP id y18so28078789iob.8 for ; Sat, 01 Jan 2022 15:13:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sandflow-com.20210112.gappssmtp.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=a3MRKuoW3uouZ9lUTDOVb3oF9OwlAx++lW94rV8BhRM=; b=FvePNLwoxDbwIFbRwSZJ8aDtJyzCJOEv+BLq/6qF1F3sIjFitp9R9dCJAZRkCIzN+R JyVSz+CXScMezAKxrpA5lxy4yrLCnOvlHcGUIKgq56pVwge8o40zf0q+gfFvvihsWEhJ RnFASfebss+8GcIilt0H7uZUiXENcZMKwTwuZvigawh1+6U0OOU4KrlP+Tifttymlq6i qVpBw/qU+uMO2ViEYNBSpbAcwtR8bK6sn9oKjs/XzU3Se8HwBM1PEHo+m4ykfAKMTG/p 0D0qnlDxPglnPR6ItB/A4zw7TgGqe2Ab5fqFIMa7rsuUXUvkx3HSEQ75VDRQtRN8MHYi eWkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=a3MRKuoW3uouZ9lUTDOVb3oF9OwlAx++lW94rV8BhRM=; b=lWUbuIjVWBgf0XkoivQcT7Qj0b1J9BlWk0dZw4Op/JEVqxXPAEwXRLPAO4xzOpdNzl XmZw1Q+WWmwhnpqYTILY3s42EYPkcbI2RoGC8MGCaW6Jjaio03Sh1o8HEbP1es9jw5eU yF2A6ZrbT1UBgNOpvxN0nw9LudHiwaX26H2n+6li5Rg5rpeiDoGxY8muDttSdo05vorw 1bYr8TOweVoosPlW1s4z9FYOB2MIfIRk3QBt7zBg23dkCG5ueiyTFThZxPkOOww2CysD Ft4pX+OMbJx5JJYgsCRjrCyFCxpDpQGPPNl5OUfk9qiAxt4ptB9LXn23Och/39+vE/wM C/VQ== X-Gm-Message-State: AOAM532dpPUQNFecpECdsR83JuR3OeurAXNqHggsVd9/FtDySog3zRaE hNIM9ByyUTYEtMEpuUhMNmlXbQNSYY0Qvg== X-Google-Smtp-Source: ABdhPJwMKK69sQD80BZKgSfVsAg4FQpU/nq6ihwn1Ue5UdrtxWUEJY9XnddaLBWxrnwGu7UEknZshQ== X-Received: by 2002:a05:6638:22c7:: with SMTP id j7mr14139330jat.264.1641078794042; Sat, 01 Jan 2022 15:13:14 -0800 (PST) Received: from mail-io1-f43.google.com (mail-io1-f43.google.com. [209.85.166.43]) by smtp.gmail.com with ESMTPSA id g8sm18393116ilf.17.2022.01.01.15.13.13 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 01 Jan 2022 15:13:13 -0800 (PST) Received: by mail-io1-f43.google.com with SMTP id q5so36369485ioj.7 for ; Sat, 01 Jan 2022 15:13:13 -0800 (PST) X-Received: by 2002:a5d:87d8:: with SMTP id q24mr17853393ios.154.1641078792800; Sat, 01 Jan 2022 15:13:12 -0800 (PST) MIME-Version: 1.0 References: <20220101192645.19849-1-cus@passwd.hu> In-Reply-To: <20220101192645.19849-1-cus@passwd.hu> From: Pierre-Anthony Lemieux Date: Sat, 1 Jan 2022 15:13:01 -0800 X-Gmail-Original-Message-ID: Message-ID: To: FFmpeg development discussions and patches Subject: Re: [FFmpeg-devel] [PATCH] avformat/mxfdec: 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 Cc: Marc-Antoine Arnaud , Marton Balint Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: Minor suggestion below. In addition, will sample file(s) be added to FATE? Below are two examples: http://ffmpeg-imf-samples-public.s3.us-west-1.amazonaws.com/callout_51_l_r_c_lfe_ls_rs.mxf http://ffmpeg-imf-samples-public.s3.us-west-1.amazonaws.com/callout_51_l_c_r_ls_rs_lfe.mxf On Sat, Jan 1, 2022 at 11:27 AM Marton Balint wrote: > > From: Marc-Antoine Arnaud > > Channel reordering is removed from this patch because the new channel layout > API will support it properly. > > Signed-off-by: Marton Balint > --- > libavformat/mxf.h | 3 + > libavformat/mxfdec.c | 286 ++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 283 insertions(+), 6 deletions(-) > > diff --git a/libavformat/mxf.h b/libavformat/mxf.h > index fe9c52732c..d53a16df51 100644 > --- a/libavformat/mxf.h > +++ b/libavformat/mxf.h > @@ -50,6 +50,9 @@ enum MXFMetadataSetType { > TaggedValue, > TapeDescriptor, > AVCSubDescriptor, > + AudioChannelLabelSubDescriptor, > + SoundfieldGroupLabelSubDescriptor, > + GroupOfSoundfieldGroupsLabelSubDescriptor, > }; > > enum MXFFrameLayout { > diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c > index 1d50198279..26b5531720 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,18 @@ typedef struct MXFDescriptor { > size_t coll_size; > } MXFDescriptor; > > +typedef struct MXFMCASubDescriptor { > + MXFMetadataSet meta; > + UID uid; > + UID mca_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; > + > typedef struct MXFIndexTableSegment { > MXFMetadataSet meta; > int edit_unit_byte_count; > @@ -311,6 +330,7 @@ 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 }; > + > /* 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,17 @@ 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_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 }; > + > +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 +374,13 @@ 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 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); > @@ -906,6 +944,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; > @@ -1363,11 +1425,40 @@ 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)) > + return 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->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); > + > + return 0; > +} > + > static int mxf_read_indirect_value(void *arg, AVIOContext *pb, int size) > { > MXFTaggedValue *tagged_value = arg; > @@ -1497,6 +1588,50 @@ 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 MXFChannelOrderingUL { > + UID uid; > + 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 }, 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 }, > +}; I suggest adding the following audio channels, which are specified in SMPTE ST 2067-8 [1] and have a direct mapping to ffmpeg audio channels: urn:smpte:ul:060e2b34.0401010d.03020120.03000000 (Left Total) -> AV_CH_STEREO_LEFT urn:smpte:ul:060e2b34.0401010d.03020120.04000000 (RightTotal) -> AV_CH_STEREO_RIGHT [1] https://registry.smpte-ra.org/view/published/labels_view.html > + > static MXFWrappingScheme mxf_get_wrapping_kind(UID *essence_container_ul) > { > int val; > @@ -2295,6 +2430,139 @@ 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 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; > + > + 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) { > + av_log(mxf->fc, AV_LOG_WARNING, "stream #%d is not in in native channel order, " > + "falling back to unknown channel layout\n", st->index); > + return 0; > + } > + channel_layout |= routing[i]; > + } > + > + av_assert0(descriptor->channels == av_get_channel_layout_nb_channels(channel_layout)); > + > + st->codecpar->channel_layout = channel_layout; > + } > + > + return 0; > +} > + > static int mxf_parse_structural_metadata(MXFContext *mxf) > { > MXFPackage *material_package = NULL; > @@ -2691,6 +2959,15 @@ 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); > + > + 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; > + } > + > + 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); > @@ -2891,6 +3168,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,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 }, > @@ -3190,12 +3470,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; > -- > 2.31.1 > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".