1 /*
2 * Copyright (c) 2024, Alliance for Open Media. All rights reserved
3 *
4 * This source code is subject to the terms of the BSD 3-Clause Clear License
5 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6 * License was not distributed with this source code in the LICENSE file, you
7 * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
8 * Alliance for Open Media Patent License 1.0 was not distributed with this
9 * source code in the PATENTS file, you can obtain it at
10 * www.aomedia.org/license/patent.
11 */
12
13 #include "iamf/cli/user_metadata_builder/audio_frame_metadata_builder.h"
14
15 #include <cstdint>
16 #include <vector>
17
18 #include "absl/base/no_destructor.h"
19 #include "absl/container/flat_hash_map.h"
20 #include "absl/status/status.h"
21 #include "absl/status/statusor.h"
22 #include "absl/strings/string_view.h"
23 #include "iamf/cli/proto/audio_frame.pb.h"
24 #include "iamf/cli/proto/user_metadata.pb.h"
25 #include "iamf/cli/user_metadata_builder/iamf_input_layout.h"
26 #include "iamf/common/utils/map_utils.h"
27
28 namespace iamf_tools {
29
30 namespace {
31
32 absl::StatusOr<std::vector<iamf_tools_cli_proto::ChannelLabel>>
LookupLabelsFromInputLayout(IamfInputLayout input_layout)33 LookupLabelsFromInputLayout(IamfInputLayout input_layout) {
34 // Map which holds the channel labels corresponding to the loudspeaker
35 // layout/ambisonics.
36 using enum IamfInputLayout;
37 using enum iamf_tools_cli_proto::ChannelLabel;
38 static const absl::NoDestructor<absl::flat_hash_map<
39 IamfInputLayout, std::vector<iamf_tools_cli_proto::ChannelLabel>>>
40 kIamfInputLayoutToProtoLabels({
41 {kMono, {CHANNEL_LABEL_MONO}},
42 {kStereo, {CHANNEL_LABEL_L_2, CHANNEL_LABEL_R_2}},
43 {k5_1,
44 {CHANNEL_LABEL_L_5, CHANNEL_LABEL_R_5, CHANNEL_LABEL_CENTRE,
45 CHANNEL_LABEL_LFE, CHANNEL_LABEL_LS_5, CHANNEL_LABEL_RS_5}},
46 {k5_1_2,
47 {CHANNEL_LABEL_L_5, CHANNEL_LABEL_R_5, CHANNEL_LABEL_CENTRE,
48 CHANNEL_LABEL_LFE, CHANNEL_LABEL_LS_5, CHANNEL_LABEL_RS_5,
49 CHANNEL_LABEL_LTF_2, CHANNEL_LABEL_RTF_2}},
50 {k5_1_4,
51 {CHANNEL_LABEL_L_5, CHANNEL_LABEL_R_5, CHANNEL_LABEL_CENTRE,
52 CHANNEL_LABEL_LFE, CHANNEL_LABEL_LS_5, CHANNEL_LABEL_RS_5,
53 CHANNEL_LABEL_LTF_4, CHANNEL_LABEL_RTF_4, CHANNEL_LABEL_LTB_4,
54 CHANNEL_LABEL_RTB_4}},
55 {k7_1,
56 {CHANNEL_LABEL_L_7, CHANNEL_LABEL_R_7, CHANNEL_LABEL_CENTRE,
57 CHANNEL_LABEL_LFE, CHANNEL_LABEL_LSS_7, CHANNEL_LABEL_RSS_7,
58 CHANNEL_LABEL_LRS_7, CHANNEL_LABEL_RRS_7}},
59 {k7_1_4,
60 {CHANNEL_LABEL_L_7, CHANNEL_LABEL_R_7, CHANNEL_LABEL_CENTRE,
61 CHANNEL_LABEL_LFE, CHANNEL_LABEL_LSS_7, CHANNEL_LABEL_RSS_7,
62 CHANNEL_LABEL_LRS_7, CHANNEL_LABEL_RRS_7, CHANNEL_LABEL_LTF_4,
63 CHANNEL_LABEL_RTF_4, CHANNEL_LABEL_LTB_4, CHANNEL_LABEL_RTB_4}},
64 {kBinaural, {CHANNEL_LABEL_L_2, CHANNEL_LABEL_R_2}},
65 {kLFE, {CHANNEL_LABEL_LFE}},
66 {kAmbisonicsOrder1,
67 {CHANNEL_LABEL_A_0, CHANNEL_LABEL_A_1, CHANNEL_LABEL_A_2,
68 CHANNEL_LABEL_A_3}},
69 {kAmbisonicsOrder2,
70 {CHANNEL_LABEL_A_0, CHANNEL_LABEL_A_1, CHANNEL_LABEL_A_2,
71 CHANNEL_LABEL_A_3, CHANNEL_LABEL_A_4, CHANNEL_LABEL_A_5,
72 CHANNEL_LABEL_A_6, CHANNEL_LABEL_A_7, CHANNEL_LABEL_A_8}},
73 {kAmbisonicsOrder3,
74 {CHANNEL_LABEL_A_0, CHANNEL_LABEL_A_1, CHANNEL_LABEL_A_2,
75 CHANNEL_LABEL_A_3, CHANNEL_LABEL_A_4, CHANNEL_LABEL_A_5,
76 CHANNEL_LABEL_A_6, CHANNEL_LABEL_A_7, CHANNEL_LABEL_A_8,
77 CHANNEL_LABEL_A_9, CHANNEL_LABEL_A_10, CHANNEL_LABEL_A_11,
78 CHANNEL_LABEL_A_12, CHANNEL_LABEL_A_13, CHANNEL_LABEL_A_14,
79 CHANNEL_LABEL_A_15}},
80 });
81
82 return LookupInMap(*kIamfInputLayoutToProtoLabels, input_layout,
83 "Proto-based channels labels for `IamfInputLayout`");
84 }
85
86 } // namespace
87
88 // Sets the required textproto fields for audio_frame_metadata.
PopulateAudioFrameMetadata(absl::string_view wav_filename,uint32_t audio_element_id,IamfInputLayout input_layout,iamf_tools_cli_proto::AudioFrameObuMetadata & audio_frame_obu_metadata)89 absl::Status AudioFrameMetadataBuilder::PopulateAudioFrameMetadata(
90 absl::string_view wav_filename, uint32_t audio_element_id,
91 IamfInputLayout input_layout,
92 iamf_tools_cli_proto::AudioFrameObuMetadata& audio_frame_obu_metadata) {
93 audio_frame_obu_metadata.set_wav_filename(wav_filename);
94 // Let the encoder determine how much codec delay and padding is required. We
95 // just want to preserve the original audio.
96 audio_frame_obu_metadata.set_samples_to_trim_at_start_includes_codec_delay(
97 false);
98 audio_frame_obu_metadata.set_samples_to_trim_at_end_includes_padding(false);
99 audio_frame_obu_metadata.set_samples_to_trim_at_start(0);
100 audio_frame_obu_metadata.set_samples_to_trim_at_end(0);
101 audio_frame_obu_metadata.set_audio_element_id(audio_element_id);
102
103 const auto& labels = LookupLabelsFromInputLayout(input_layout);
104 if (!labels.ok()) {
105 return labels.status();
106 }
107 int32_t channel_id = 0;
108 for (const auto& label : *labels) {
109 auto* channel_metadata = audio_frame_obu_metadata.add_channel_metadatas();
110 channel_metadata->set_channel_label(label);
111 channel_metadata->set_channel_id(channel_id++);
112 }
113
114 return absl::OkStatus();
115 }
116
117 } // namespace iamf_tools
118