[FFmpeg-devel] [PATCH] avformat/mxf: support MCA audio information

Tomas Härdin tjoppen at acc.umu.se
Wed Aug 18 16:16:57 EEST 2021


tor 2021-08-12 klockan 14:38 +0200 skrev Marc-Antoine Arnaud:

@@ -177,6 +179,7 @@ typedef struct {
     int body_sid;
     MXFWrappingScheme wrapping;
     int edit_units_per_packet; /* how many edit units to read at a
time (PCM, ClipWrapped) */
+    int* channel_ordering;

Is there a maximum number of channels? If so then this should be made
constant size.

 } MXFTrack;
 
 typedef struct MXFDescriptor {
@@ -217,6 +220,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_dictionnary_id;
+    char *language;

Language doesn't seem to be used

+} MXFMCASubDescriptor;

+static inline int mxf_read_us_ascii_string(AVIOContext *pb, int size,
char** str)
+{
+    int ret;
+    size_t buf_size;
+
+    if (size < 0)
+        return AVERROR(EINVAL);
+
+    buf_size = size + 1;
+    av_free(*str);
+    *str = av_malloc(buf_size);

av_realloc()

 static int mxf_parse_structural_metadata(MXFContext *mxf)
 {
     MXFPackage *material_package = NULL;
@@ -2322,7 +2461,10 @@ static int
mxf_parse_structural_metadata(MXFContext *mxf)
         const MXFCodecUL *pix_fmt_ul = NULL;
         AVStream *st;
         AVTimecode tc;
+        enum AVAudioServiceType *ast;
+        int* channel_ordering;
         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");
@@ -2681,6 +2823,185 @@ static int
mxf_parse_structural_metadata(MXFContext *mxf)
                 st->internal->need_parsing = AVSTREAM_PARSE_FULL;
             }
             st->codecpar->bits_per_coded_sample =
av_get_bits_per_sample(st->codecpar->codec_id);
+
+            current_channel = 0;
+
+            channel_ordering = av_mallocz_array(descriptor->channels,
sizeof(int));
+
+            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_dictionnary_id, mxf_soundfield_group)) {
+                    if (IS_KLV_KEY(mca_sub_descriptor-
>mca_label_dictionnary_id, mxf_soundfield_group_51)) {
+                        st->codecpar->channel_layout =
AV_CH_LAYOUT_5POINT1;
+                        continue;
+                    }

Consider using a table lookup for this instead.

+
+                // Audio channel
+                if (IS_KLV_KEY(mca_sub_descriptor-
>mca_label_dictionnary_id, mxf_audio_channel)) {
+                    if (IS_KLV_KEY(mca_sub_descriptor-
>mca_label_dictionnary_id, mxf_left_audio_channel)) {
+                        channel_ordering[current_channel] = 0;
+                        current_channel += 1;
+                    }

Same here, except for the special case for the impaired stuff.

+
+                    // TODO support other channels
+                    // mxf_smpte_st2067_8_mono_one_audio_channel
+                    // mxf_smpte_st2067_8_mono_two_audio_channel
+                    // mxf_smpte_st2067_8_left_total_audio_channel
+                    // mxf_smpte_st2067_8_right_total_audio_channel
+                    //
mxf_smpte_st2067_8_left_surround_total_audio_channel
+                    //
mxf_smpte_st2067_8_right_surround_total_audio_channel
+                    // mxf_smpte_st2067_8_surround_audio_channel

These should be a ticket, not just a comment in the code. Or just
implement them :)

+                }
+
+                // set language from MCA spoken language information
+                // av_dict_set(&st->metadata, "language",
mca_sub_descriptor->language, 0);

Stray dead code. Is language not accurate perhaps?

+            }
+
+            // check if the mapping is not required
+            bool require_reordering = false;
+            for (j = 0; j < descriptor->channels; ++j) {
+                if (channel_ordering[j] != j) {
+                    require_reordering = true;
+                    break;
+                }
+            }
+
+            if (require_reordering && is_pcm(st->codecpar->codec_id))
{
+                current_channel = 0;
+                av_log(mxf->fc, AV_LOG_INFO, "MCA Audio mapping (");
+                for(j = 0; j < descriptor->channels; ++j) {
+                    for(int k = 0; k < descriptor->channels; ++k) {
+                        if(channel_ordering[k] == current_channel) {
+                            av_log(mxf->fc, AV_LOG_INFO, "%d -> %d",
channel_ordering[k], k);
+                            if (current_channel != descriptor-
>channels - 1)
+                                av_log(mxf->fc, AV_LOG_INFO, ", ");
+                            current_channel += 1;
+                        }
+                    }
+                }
+                av_log(mxf->fc, AV_LOG_INFO, ")\n");

AV_LOG_DEBUG

 
+static void 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 = av_malloc(sample_offset);

Could avoid malloc here as well if we capped the number of channels.

+    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) {
+            for (int sample_index = 0; sample_index < sample_size;
++sample_index) {
+                data_ptr[sample_size * channel_ordering[channel] +
sample_index] = tmp[sample_size * channel + sample_index];
+            }
+        }

This looks like it would be very slow. Lots of copying.

/Tomas



More information about the ffmpeg-devel mailing list