• 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/adm_to_user_metadata/iamf/user_metadata_generator.h"
14 
15 #include <cstdint>
16 #include <filesystem>
17 #include <fstream>
18 #include <ios>
19 #include <string>
20 #include <vector>
21 
22 #include "absl/log/log.h"
23 #include "absl/status/status.h"
24 #include "absl/status/statusor.h"
25 #include "absl/strings/str_cat.h"
26 #include "absl/strings/string_view.h"
27 #include "iamf/cli/adm_to_user_metadata/adm/adm_elements.h"
28 #include "iamf/cli/adm_to_user_metadata/iamf/ia_sequence_header_obu_metadata_handler.h"
29 #include "iamf/cli/adm_to_user_metadata/iamf/iamf.h"
30 #include "iamf/cli/adm_to_user_metadata/iamf/mix_presentation_handler.h"
31 #include "iamf/cli/adm_to_user_metadata/iamf/test_vector_metadata_handler.h"
32 #include "iamf/cli/proto/user_metadata.pb.h"
33 #include "iamf/cli/user_metadata_builder/audio_frame_metadata_builder.h"
34 #include "iamf/cli/user_metadata_builder/codec_config_obu_metadata_builder.h"
35 #include "iamf/obu/types.h"
36 
37 namespace iamf_tools {
38 namespace adm_to_user_metadata {
39 
40 namespace {
41 constexpr DecodedUleb128 kCodecConfigId = 0;
42 }
43 
WriteUserMetadataToFile(bool write_binary_proto,const std::filesystem::path & file_path,const iamf_tools_cli_proto::UserMetadata & user_metadata)44 absl::Status UserMetadataGenerator::WriteUserMetadataToFile(
45     bool write_binary_proto, const std::filesystem::path& file_path,
46     const iamf_tools_cli_proto::UserMetadata& user_metadata) {
47   const auto file_name =
48       file_path /
49       absl::StrCat(user_metadata.test_vector_metadata().file_name_prefix(),
50                    write_binary_proto ? ".binpb" : ".textproto");
51 
52   std::ofstream output_file(file_name, std::ios::binary | std::ios::out);
53   if (!output_file.is_open()) {
54     return absl::FailedPreconditionError(
55         absl::StrCat("Failed to open file_name= ", file_name.string()));
56   }
57 
58   if (write_binary_proto) {
59     output_file << user_metadata.SerializeAsString();
60   } else {
61     output_file << user_metadata.DebugString();
62   }
63 
64   output_file.close();
65   LOG(INFO) << file_name.string() << " generated successfully.";
66 
67   return absl::OkStatus();
68 }
69 
70 absl::StatusOr<iamf_tools_cli_proto::UserMetadata>
GenerateUserMetadata(iamf_tools_cli_proto::ProfileVersion profile_version,absl::string_view file_prefix) const71 UserMetadataGenerator::GenerateUserMetadata(
72     iamf_tools_cli_proto::ProfileVersion profile_version,
73     absl::string_view file_prefix) const {
74   std::vector<std::string> audio_pack_format_ids;
75   audio_pack_format_ids.reserve(adm_.audio_objects.size());
76   for (auto audio_object : adm_.audio_objects) {
77     audio_pack_format_ids.push_back(audio_object.audio_pack_format_id_refs[0]);
78   }
79 
80   auto iamf =
81       IAMF::Create(adm_, max_frame_duration_, format_info_.samples_per_sec);
82   if (!iamf.ok()) {
83     return iamf.status();
84   }
85   iamf_tools_cli_proto::UserMetadata user_metadata;
86 
87   // Generate test vector metadata.
88   TestVectorMetadataHandler(file_prefix,
89                             *user_metadata.mutable_test_vector_metadata());
90 
91   // Generate ia sequence header metadata.
92   PopulateIaSequenceHeaderObuMetadata(
93       profile_version, *user_metadata.add_ia_sequence_header_metadata());
94 
95   // Generate codec config obu metadata.
96   user_metadata.mutable_codec_config_metadata()->Add(
97       CodecConfigObuMetadataBuilder::GetLpcmCodecConfigObuMetadata(
98           kCodecConfigId, iamf->num_samples_per_frame_,
99           format_info_.bits_per_sample, format_info_.samples_per_sec));
100 
101   // Mapping of audio element
102   constexpr int32_t kFirstAudioElementId = 0;
103   if (adm_.audio_programmes.empty()) {
104     if (const auto status =
105             iamf->audio_element_metadata_builder_.PopulateAudioElementMetadata(
106                 kFirstAudioElementId, kCodecConfigId, iamf->input_layouts_[0],
107                 *user_metadata.add_audio_element_metadata());
108         !status.ok()) {
109       return status;
110     };
111   } else {
112     for (const auto& [unused_audio_object_id, audio_element_id] :
113          iamf->audio_object_to_audio_element_) {
114       if (const auto status =
115               iamf->audio_element_metadata_builder_
116                   .PopulateAudioElementMetadata(
117                       audio_element_id, kCodecConfigId,
118                       iamf->input_layouts_[audio_element_id],
119                       *user_metadata.add_audio_element_metadata());
120           !status.ok()) {
121         return status;
122       }
123     }
124   }
125 
126   // Generate mix presentation obu metadata.
127 
128   if (adm_.audio_programmes.empty()) {
129     constexpr int32_t kFirstMixPresentationId = 0;
130     // Generate a mix presentation with the first audio object and default
131     // loudness metadata.
132     const std::vector<AudioObject>& audio_objects = {adm_.audio_objects[0]};
133 
134     if (const auto& status =
135             iamf->mix_presentation_handler_.PopulateMixPresentation(
136                 kFirstMixPresentationId, audio_objects, LoudnessMetadata(),
137                 *user_metadata.add_mix_presentation_metadata());
138         !status.ok()) {
139       return status;
140     }
141   } else {
142     for (const auto& [mix_presentation_id, audio_objects_and_metadata] :
143          iamf->mix_presentation_id_to_audio_objects_and_metadata_) {
144       if (const auto& status =
145               iamf->mix_presentation_handler_.PopulateMixPresentation(
146                   mix_presentation_id, audio_objects_and_metadata.audio_objects,
147                   adm_.audio_programmes[audio_objects_and_metadata
148                                             .original_audio_programme_index]
149                       .loudness_metadata,
150                   *user_metadata.add_mix_presentation_metadata());
151           !status.ok()) {
152         return status;
153       }
154     }
155   }
156 
157   // Generate audio frame metadata.
158   if (adm_.audio_programmes.empty()) {
159     // The output files have suffixes starting from 1.
160     static const absl::string_view kFirstFileSuffix = "1";
161 
162     if (const auto& status =
163             AudioFrameMetadataBuilder::PopulateAudioFrameMetadata(
164                 absl::StrCat(file_prefix, "_converted", kFirstFileSuffix,
165                              ".wav"),
166                 kFirstAudioElementId, iamf->input_layouts_[0],
167                 *user_metadata.add_audio_frame_metadata());
168         !status.ok()) {
169       return status;
170     }
171   } else {
172     int32_t audio_pack_index = 0;
173     for (const auto& [unused_audio_object_id, audio_element_id] :
174          iamf->audio_object_to_audio_element_) {
175       // The output files have suffixes starting from 1.
176       const std::string wav_file_name =
177           absl::StrCat(file_prefix, "_converted", audio_pack_index + 1, ".wav");
178       if (const auto& status =
179               AudioFrameMetadataBuilder::PopulateAudioFrameMetadata(
180                   wav_file_name, audio_element_id,
181                   iamf->input_layouts_[audio_pack_index++],
182                   *user_metadata.add_audio_frame_metadata());
183           !status.ok()) {
184         return status;
185       }
186     }
187   }
188 
189   return user_metadata;
190 }
191 
192 }  // namespace adm_to_user_metadata
193 }  // namespace iamf_tools
194