• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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