• 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 #ifndef CLI_PROTO_CONVERSION_CHANNEL_LABEL_UTILS_H_
14 #define CLI_PROTO_CONVERSION_CHANNEL_LABEL_UTILS_H_
15 
16 #include <algorithm>
17 
18 #include "absl/status/status.h"
19 #include "absl/status/statusor.h"
20 #include "absl/strings/str_cat.h"
21 #include "absl/strings/string_view.h"
22 #include "iamf/cli/channel_label.h"
23 #include "iamf/cli/proto/audio_frame.pb.h"
24 
25 namespace iamf_tools {
26 
27 class ChannelLabelUtils {
28  public:
29   /*!\brief Converts the input proto enum to a `Label`.
30    *
31    * \param proto_label Label to convert.
32    * \return Converted label on success. A specific status on failure.
33    */
34   static absl::StatusOr<ChannelLabel::Label> ProtoToLabel(
35       iamf_tools_cli_proto::ChannelLabel proto_label);
36 
37   /*!\brief Converts the input `ChanelLabel` to a proto enum
38    *
39    * \param label Label to convert.
40    * \return Converted label on success. A specific status on failure.
41    */
42   static absl::StatusOr<iamf_tools_cli_proto::ChannelLabel> LabelToProto(
43       ChannelLabel::Label label);
44 
45   /*!\brief Converts labels and fill the output container.
46    *
47    * Useful to convert containers of `std::string`, `absl::string_view`, or
48    * `iamf_tools_cli_proto::ChannelLabel` proto enums to the
49    * canonical internal representation.
50    *
51    * \param input_labels Container to convert.
52    * \param output_labels Container to fill with the converted labels. The
53    *        labels are inserted using the end iterator as a "hint"; when both
54    *        containers are ordered the input and output order will agree.
55    * \return `absl::OkStatus()` on success. An error if any labels fail to be
56    *         converted. An error if any output labels are duplicate.
57    */
58   template <class InputContainer, class OutputContainer>
ConvertAndFillLabels(const InputContainer & input_labels,OutputContainer & output_labels)59   static absl::Status ConvertAndFillLabels(const InputContainer& input_labels,
60                                            OutputContainer& output_labels) {
61     for (const auto& input_label : input_labels) {
62       const absl::StatusOr<ChannelLabel::Label> label = [&]() -> auto {
63         using iamf_tools_cli_proto::ChannelMetadata;
64         if constexpr (std::is_convertible_v<decltype(input_label),
65                                             absl::string_view>) {
66           return ChannelLabel::DeprecatedStringBasedLabelToLabel(input_label);
67         } else if constexpr (std::is_convertible_v<decltype(input_label),
68                                                    ChannelMetadata>) {
69           return ProtoToLabel(input_label.channel_label());
70         } else {
71           return ProtoToLabel(input_label);
72         }
73       }();
74       if (!label.ok()) {
75         return label.status();
76       }
77 
78       if (std::find(output_labels.begin(), output_labels.end(), *label) !=
79           output_labels.end()) {
80         return absl::InvalidArgumentError(
81             absl::StrCat("Duplicate output_label: ", *label,
82                          " when inserting from input_label= ", input_label));
83       }
84       output_labels.insert(output_labels.end(), *label);
85     }
86 
87     return absl::OkStatus();
88   }
89 
90   /*!\brief Select the labels and forward to `ConvertAndFillLabels`.
91    *
92    * Acts as a shim to allow common handling of `channel_metadatas` and
93    * the deprecated `channel_labels` fields. This function will change behavior
94    * as the deprecation process moves forward.
95    *
96    * Prefers selecting labels based on the `channel_metadatas` field if it is
97    * present. Warns, but permits the deprecated `channel_labels`. Forbids
98    * partial upgrades, which would result in a confusing state with multiple
99    * sources of labels.
100    *
101    * \param audio_frame_metadata Metadata to select labels from and convert.
102    * \param output_labels Container to fill with the converted labels. The
103    *        labels are inserted using the end iterator as a "hint"; when both
104    *        containers are ordered the input and output order will agree.
105    * \return `absl::OkStatus()` on success. An error if the `channel_metadatas`
106    *         is present, but `channel_labels` or `channel_ids` is not empty. An
107    *         error if any labels fail to be converted. An error if any output
108    *         labels are duplicate.
109    */
110   template <class OutputContainer>
SelectConvertAndFillLabels(const iamf_tools_cli_proto::AudioFrameObuMetadata & audio_frame_metadata,OutputContainer & output_labels)111   static absl::Status SelectConvertAndFillLabels(
112       const iamf_tools_cli_proto::AudioFrameObuMetadata& audio_frame_metadata,
113       OutputContainer& output_labels) {
114     if (!audio_frame_metadata.channel_metadatas().empty()) {
115       if (!audio_frame_metadata.channel_labels().empty()) {
116         return absl::InvalidArgumentError(
117             "Please fully upgrade to `channel_metadatas`. Leave "
118             "`channel_labels` empty");
119       }
120       return ConvertAndFillLabels(audio_frame_metadata.channel_metadatas(),
121                                   output_labels);
122     } else {
123       return ConvertAndFillLabels(audio_frame_metadata.channel_labels(),
124                                   output_labels);
125     }
126   }
127 };
128 }  // namespace iamf_tools
129 
130 #endif  // CLI_PROTO_CONVERSION_CHANNEL_LABEL_UTILS_H_
131