1 /*
2  * Copyright (c) 2023, 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 #include "iamf/cli/proto_conversion/proto_utils.h"
13 
14 #include <algorithm>
15 #include <cstdint>
16 #include <memory>
17 #include <string>
18 #include <vector>
19 
20 #include "absl/log/log.h"
21 #include "absl/status/status.h"
22 #include "absl/strings/str_cat.h"
23 #include "absl/strings/string_view.h"
24 #include "iamf/cli/proto/obu_header.pb.h"
25 #include "iamf/cli/proto/param_definitions.pb.h"
26 #include "iamf/cli/proto/parameter_data.pb.h"
27 #include "iamf/cli/proto_conversion/lookup_tables.h"
28 #include "iamf/common/leb_generator.h"
29 #include "iamf/common/utils/macros.h"
30 #include "iamf/common/utils/map_utils.h"
31 #include "iamf/common/utils/numeric_utils.h"
32 #include "iamf/obu/demixing_info_parameter_data.h"
33 #include "iamf/obu/obu_header.h"
34 #include "iamf/obu/param_definitions.h"
35 #include "iamf/obu/types.h"
36 
37 namespace iamf_tools {
38 
CopyParamDefinition(const iamf_tools_cli_proto::ParamDefinition & input_param_definition,ParamDefinition & param_definition)39 absl::Status CopyParamDefinition(
40     const iamf_tools_cli_proto::ParamDefinition& input_param_definition,
41     ParamDefinition& param_definition) {
42   param_definition.parameter_id_ = input_param_definition.parameter_id();
43   param_definition.parameter_rate_ = input_param_definition.parameter_rate();
44 
45   param_definition.param_definition_mode_ =
46       input_param_definition.param_definition_mode();
47   RETURN_IF_NOT_OK(StaticCastIfInRange<uint32_t, uint8_t>(
48       "ParamDefinition.reserved", input_param_definition.reserved(),
49       param_definition.reserved_));
50   param_definition.duration_ = input_param_definition.duration();
51   param_definition.constant_subblock_duration_ =
52       input_param_definition.constant_subblock_duration();
53 
54   if (input_param_definition.constant_subblock_duration() != 0) {
55     // Nothing else to be done. Return.
56     return absl::OkStatus();
57   }
58 
59   if (input_param_definition.num_subblocks() <
60       input_param_definition.subblock_durations_size()) {
61     return absl::InvalidArgumentError(absl::StrCat(
62         "Expected at least ", input_param_definition.num_subblocks(),
63         "subblock durations for parameter id = ",
64         input_param_definition.parameter_id()));
65   }
66 
67   param_definition.InitializeSubblockDurations(
68       static_cast<DecodedUleb128>(input_param_definition.num_subblocks()));
69   for (int i = 0; i < input_param_definition.num_subblocks(); ++i) {
70     RETURN_IF_NOT_OK(param_definition.SetSubblockDuration(
71         i, input_param_definition.subblock_durations(i)));
72   }
73 
74   return absl::OkStatus();
75 }
76 
GetHeaderFromMetadata(const iamf_tools_cli_proto::ObuHeaderMetadata & input_obu_header)77 ObuHeader GetHeaderFromMetadata(
78     const iamf_tools_cli_proto::ObuHeaderMetadata& input_obu_header) {
79   std::vector<uint8_t> extension_header_bytes(
80       input_obu_header.extension_header_bytes().size());
81   std::transform(input_obu_header.extension_header_bytes().begin(),
82                  input_obu_header.extension_header_bytes().end(),
83                  extension_header_bytes.begin(),
84                  [](char c) { return static_cast<uint8_t>(c); });
85 
86   return ObuHeader{
87       .obu_redundant_copy = input_obu_header.obu_redundant_copy(),
88       .obu_trimming_status_flag = input_obu_header.obu_trimming_status_flag(),
89       .obu_extension_flag = input_obu_header.obu_extension_flag(),
90       .num_samples_to_trim_at_end =
91           input_obu_header.num_samples_to_trim_at_end(),
92       .num_samples_to_trim_at_start =
93           input_obu_header.num_samples_to_trim_at_start(),
94       .extension_header_size = input_obu_header.extension_header_size(),
95       .extension_header_bytes = extension_header_bytes};
96 }
97 
CopyDemixingInfoParameterData(const iamf_tools_cli_proto::DemixingInfoParameterData & input_demixing_info_parameter_data,DemixingInfoParameterData & obu_demixing_param_data)98 absl::Status CopyDemixingInfoParameterData(
99     const iamf_tools_cli_proto::DemixingInfoParameterData&
100         input_demixing_info_parameter_data,
101     DemixingInfoParameterData& obu_demixing_param_data) {
102   static const auto kProtoToInternalDMixPMode =
103       BuildStaticMapFromPairs(LookupTables::kProtoAndInternalDMixPModes);
104 
105   RETURN_IF_NOT_OK(CopyFromMap(*kProtoToInternalDMixPMode,
106                                input_demixing_info_parameter_data.dmixp_mode(),
107                                "Internal version of proto `dmixp_mode`",
108                                obu_demixing_param_data.dmixp_mode));
109 
110   RETURN_IF_NOT_OK(StaticCastIfInRange<uint32_t, uint8_t>(
111       "DemixingInfoParameterData.reserved",
112       input_demixing_info_parameter_data.reserved(),
113       obu_demixing_param_data.reserved));
114 
115   return absl::OkStatus();
116 }
117 
CopyDMixPMode(DemixingInfoParameterData::DMixPMode obu_dmixp_mode,iamf_tools_cli_proto::DMixPMode & dmixp_mode)118 absl::Status CopyDMixPMode(DemixingInfoParameterData::DMixPMode obu_dmixp_mode,
119                            iamf_tools_cli_proto::DMixPMode& dmixp_mode) {
120   static const auto kInternalToProtoDMixPMode = BuildStaticMapFromInvertedPairs(
121       LookupTables::kProtoAndInternalDMixPModes);
122 
123   return CopyFromMap(*kInternalToProtoDMixPMode, obu_dmixp_mode,
124                      "Proto version of internal `DMixPMode`", dmixp_mode);
125 }
126 
CreateLebGenerator(const iamf_tools_cli_proto::Leb128Generator & user_config)127 std::unique_ptr<LebGenerator> CreateLebGenerator(
128     const iamf_tools_cli_proto::Leb128Generator& user_config) {
129   // Transform the enum and possibly `fixed_size` to call LebGenerator::Create.
130   using enum iamf_tools_cli_proto::Leb128GeneratorMode;
131   switch (user_config.mode()) {
132     case GENERATE_LEB_MINIMUM:
133       return LebGenerator::Create(LebGenerator::GenerationMode::kMinimum);
134     case GENERATE_LEB_FIXED_SIZE: {
135       int8_t fixed_size_int8;
136       auto status =
137           StaticCastIfInRange("user_metadata.leb_generator.fixed_size",
138                               user_config.fixed_size(), fixed_size_int8);
139       if (!status.ok()) {
140         LOG(ERROR) << status;
141         return nullptr;
142       }
143       return LebGenerator::Create(LebGenerator::GenerationMode::kFixedSize,
144                                   fixed_size_int8);
145     }
146     default:
147       LOG(ERROR) << "Invalid generation mode: " << user_config.mode();
148       return nullptr;
149   }
150 }
151 
152 }  // namespace iamf_tools
153