Skip to content

Commit 93acd2b

Browse files
committed
Implement ElementGainOffsetConfig.
- Add read and write functions. The variants are simple enough to hide in the class. PiperOrigin-RevId: 856223061
1 parent a6e5c44 commit 93acd2b

File tree

5 files changed

+534
-0
lines changed

5 files changed

+534
-0
lines changed

iamf/obu/BUILD

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,24 @@ cc_library(
159159
],
160160
)
161161

162+
cc_library(
163+
name = "element_gain_offset_config",
164+
srcs = ["element_gain_offset_config.cc"],
165+
hdrs = ["element_gain_offset_config.h"],
166+
deps = [
167+
"//iamf/common:q_format_or_floating_point",
168+
"//iamf/common:read_bit_buffer",
169+
"//iamf/common:write_bit_buffer",
170+
"//iamf/common/utils:macros",
171+
"//iamf/common/utils:validation_utils",
172+
"@abseil-cpp//absl/log:absl_log",
173+
"@abseil-cpp//absl/status",
174+
"@abseil-cpp//absl/status:statusor",
175+
"@abseil-cpp//absl/strings",
176+
"@abseil-cpp//absl/types:span",
177+
],
178+
)
179+
162180
cc_library(
163181
name = "ia_sequence_header",
164182
srcs = ["ia_sequence_header.cc"],
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
* Copyright (c) 2026, 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/obu/element_gain_offset_config.h"
13+
14+
#include <cstdint>
15+
#include <utility>
16+
#include <variant>
17+
#include <vector>
18+
19+
#include "absl/log/absl_log.h"
20+
#include "absl/status/status.h"
21+
#include "absl/status/statusor.h"
22+
#include "absl/strings/string_view.h"
23+
#include "absl/types/span.h"
24+
#include "iamf/common/q_format_or_floating_point.h"
25+
#include "iamf/common/read_bit_buffer.h"
26+
#include "iamf/common/utils/macros.h"
27+
#include "iamf/common/utils/validation_utils.h"
28+
#include "iamf/common/write_bit_buffer.h"
29+
30+
namespace iamf_tools {
31+
32+
using ::absl::MakeConstSpan;
33+
using ::absl::MakeSpan;
34+
35+
namespace {
36+
37+
enum class ElementGainOffsetConfigType : uint8_t {
38+
kValueType = 0,
39+
kRangeType = 1
40+
};
41+
42+
} // namespace
43+
44+
absl::Status ElementGainOffsetConfig::ValueType::Write(
45+
WriteBitBuffer& wb) const {
46+
RETURN_IF_NOT_OK(wb.WriteUnsignedLiteral(
47+
static_cast<uint32_t>(ElementGainOffsetConfigType::kValueType), 8));
48+
return wb.WriteSigned16(element_gain_offset.GetQ7_8());
49+
}
50+
51+
absl::Status ElementGainOffsetConfig::RangeType::Write(
52+
WriteBitBuffer& wb) const {
53+
RETURN_IF_NOT_OK(wb.WriteUnsignedLiteral(
54+
static_cast<uint32_t>(ElementGainOffsetConfigType::kRangeType), 8));
55+
RETURN_IF_NOT_OK(wb.WriteSigned16(default_element_gain_offset.GetQ7_8()));
56+
RETURN_IF_NOT_OK(wb.WriteSigned16(min_element_gain_offset.GetQ7_8()));
57+
return wb.WriteSigned16(max_element_gain_offset.GetQ7_8());
58+
}
59+
60+
absl::Status ElementGainOffsetConfig::ExtensionType::Write(
61+
WriteBitBuffer& wb) const {
62+
RETURN_IF_NOT_OK(wb.WriteUnsignedLiteral(element_gain_offset_config_type, 8));
63+
RETURN_IF_NOT_OK(wb.WriteUleb128(element_gain_offset_bytes.size()));
64+
return wb.WriteUint8Span(MakeConstSpan(element_gain_offset_bytes));
65+
}
66+
67+
void ElementGainOffsetConfig::ValueType::Print() const {
68+
ABSL_LOG(INFO) << "value_type: " << element_gain_offset;
69+
}
70+
71+
void ElementGainOffsetConfig::RangeType::Print() const {
72+
ABSL_LOG(INFO) << "range_type: ";
73+
ABSL_LOG(INFO) << " default_element_gain_offset= "
74+
<< default_element_gain_offset;
75+
ABSL_LOG(INFO) << " min_element_gain_offset= " << min_element_gain_offset;
76+
ABSL_LOG(INFO) << " max_element_gain_offset= " << max_element_gain_offset;
77+
}
78+
79+
void ElementGainOffsetConfig::ExtensionType::Print() const {
80+
ABSL_LOG(INFO) << "element_gain_offset_config_type: "
81+
<< element_gain_offset_config_type;
82+
ABSL_LOG(INFO) << " element_gain_offset_bytes size: "
83+
<< element_gain_offset_bytes.size();
84+
ABSL_LOG(INFO) << " (element_gain_offset_bytes omitted)";
85+
}
86+
87+
ElementGainOffsetConfig ElementGainOffsetConfig::MakeValueType(
88+
QFormatOrFloatingPoint element_gain_offset) {
89+
// Nothing can fail here.
90+
return ElementGainOffsetConfig(
91+
ValueType{.element_gain_offset = element_gain_offset});
92+
}
93+
94+
absl::StatusOr<ElementGainOffsetConfig>
95+
ElementGainOffsetConfig::CreateRangeType(
96+
QFormatOrFloatingPoint default_element_gain_offset,
97+
QFormatOrFloatingPoint min_element_gain_offset,
98+
QFormatOrFloatingPoint max_element_gain_offset) {
99+
// Check that the range is valid, and the default is within the range.
100+
RETURN_IF_NOT_OK(ValidateInRange(
101+
default_element_gain_offset.GetQ7_8(),
102+
{min_element_gain_offset.GetQ7_8(), max_element_gain_offset.GetQ7_8()},
103+
"default_element_gain_offset"));
104+
105+
return ElementGainOffsetConfig(RangeType{
106+
.default_element_gain_offset = default_element_gain_offset,
107+
.min_element_gain_offset = min_element_gain_offset,
108+
.max_element_gain_offset = max_element_gain_offset,
109+
});
110+
}
111+
112+
absl::StatusOr<ElementGainOffsetConfig>
113+
ElementGainOffsetConfig::CreateExtensionType(
114+
uint8_t element_gain_offset_config_type,
115+
absl::Span<const uint8_t> element_gain_offset_bytes) {
116+
if (element_gain_offset_config_type ==
117+
static_cast<uint8_t>(ElementGainOffsetConfigType::kValueType) ||
118+
element_gain_offset_config_type ==
119+
static_cast<uint8_t>(ElementGainOffsetConfigType::kRangeType)) {
120+
return absl::InvalidArgumentError(
121+
"Call the specific factory function for value and range types.");
122+
}
123+
124+
return ElementGainOffsetConfig(ExtensionType{
125+
.element_gain_offset_config_type = element_gain_offset_config_type,
126+
.element_gain_offset_bytes = std::vector<uint8_t>(
127+
element_gain_offset_bytes.begin(), element_gain_offset_bytes.end()),
128+
});
129+
}
130+
131+
absl::StatusOr<ElementGainOffsetConfig>
132+
ElementGainOffsetConfig::CreateFromBuffer(ReadBitBuffer& rb) {
133+
uint8_t element_gain_offset_config_type;
134+
RETURN_IF_NOT_OK(rb.ReadUnsignedLiteral(8, element_gain_offset_config_type));
135+
if (element_gain_offset_config_type ==
136+
static_cast<uint8_t>(ElementGainOffsetConfigType::kValueType)) {
137+
int16_t element_gain_offset_q78;
138+
RETURN_IF_NOT_OK(rb.ReadSigned16(element_gain_offset_q78));
139+
return MakeValueType(
140+
QFormatOrFloatingPoint::MakeFromQ7_8(element_gain_offset_q78));
141+
} else if (element_gain_offset_config_type ==
142+
static_cast<uint8_t>(ElementGainOffsetConfigType::kRangeType)) {
143+
int16_t default_element_gain_offset_q78;
144+
int16_t min_element_gain_offset_q78;
145+
int16_t max_element_gain_offset_q78;
146+
RETURN_IF_NOT_OK(rb.ReadSigned16(default_element_gain_offset_q78));
147+
RETURN_IF_NOT_OK(rb.ReadSigned16(min_element_gain_offset_q78));
148+
RETURN_IF_NOT_OK(rb.ReadSigned16(max_element_gain_offset_q78));
149+
return CreateRangeType(
150+
QFormatOrFloatingPoint::MakeFromQ7_8(default_element_gain_offset_q78),
151+
QFormatOrFloatingPoint::MakeFromQ7_8(min_element_gain_offset_q78),
152+
QFormatOrFloatingPoint::MakeFromQ7_8(max_element_gain_offset_q78));
153+
}
154+
155+
// Else it is an extension type.
156+
uint32_t element_gain_offset_size;
157+
RETURN_IF_NOT_OK(rb.ReadULeb128(element_gain_offset_size));
158+
std::vector<uint8_t> element_gain_offset_bytes(element_gain_offset_size);
159+
RETURN_IF_NOT_OK(rb.ReadUint8Span(MakeSpan(element_gain_offset_bytes)));
160+
return CreateExtensionType(element_gain_offset_config_type,
161+
element_gain_offset_bytes);
162+
}
163+
164+
absl::Status ElementGainOffsetConfig::Write(WriteBitBuffer& wb) const {
165+
return std::visit(
166+
[&wb](const auto& data) -> absl::Status { return data.Write(wb); },
167+
element_gain_offset_config_data_);
168+
}
169+
170+
void ElementGainOffsetConfig::Print() const {
171+
std::visit([](const auto& data) { data.Print(); },
172+
element_gain_offset_config_data_);
173+
}
174+
175+
} // namespace iamf_tools
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* Copyright (c) 2026, 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+
#ifndef OBU_ELEMENT_GAIN_OFFSET_CONFIG_H_
13+
#define OBU_ELEMENT_GAIN_OFFSET_CONFIG_H_
14+
15+
#include <cstdint>
16+
#include <utility>
17+
#include <variant>
18+
#include <vector>
19+
20+
#include "absl/status/status.h"
21+
#include "absl/status/statusor.h"
22+
#include "absl/types/span.h"
23+
#include "iamf/common/q_format_or_floating_point.h"
24+
#include "iamf/common/read_bit_buffer.h"
25+
#include "iamf/common/write_bit_buffer.h"
26+
27+
namespace iamf_tools {
28+
29+
/*!\brief Implements Element Gain Offset Config from the IAMF spec. */
30+
class ElementGainOffsetConfig {
31+
public:
32+
friend bool operator==(const ElementGainOffsetConfig& lhs,
33+
const ElementGainOffsetConfig& rhs) = default;
34+
35+
/*!\brief Creates a value-type `ElementGainOffsetConfig`.
36+
*
37+
* \param element_gain_offset Element gain offset.
38+
* \return Value-type `ElementGainOffsetConfig`.
39+
*/
40+
static ElementGainOffsetConfig MakeValueType(
41+
QFormatOrFloatingPoint element_gain_offset);
42+
43+
/*!\brief Creates a range-type `ElementGainOffsetConfig`.
44+
*
45+
* \param default_element_gain_offset Default element gain offset.
46+
* \param min_element_gain_offset Minimum element gain offset.
47+
* \param max_element_gain_offset Maximum element gain offset.
48+
* \return `ElementGainOffsetConfig` on success; a specific status on failure.
49+
*/
50+
static absl::StatusOr<ElementGainOffsetConfig> CreateRangeType(
51+
QFormatOrFloatingPoint default_element_gain_offset,
52+
QFormatOrFloatingPoint min_element_gain_offset,
53+
QFormatOrFloatingPoint max_element_gain_offset);
54+
55+
/*!\brief Creates an extension-type `ElementGainOffsetConfig`.
56+
*
57+
* \param element_gain_offset_config_type Type of the extension.
58+
* \param element_gain_offset_bytes Bytes of the extension.
59+
* \return `ElementGainOffsetConfig` on success; a specific status on failure.
60+
*/
61+
static absl::StatusOr<ElementGainOffsetConfig> CreateExtensionType(
62+
uint8_t element_gain_offset_config_type,
63+
absl::Span<const uint8_t> element_gain_offset_bytes);
64+
65+
/*!\brief Creates an `ElementGainOffsetConfig` from a `ReadBitBuffer`.
66+
*
67+
* \param rb `ReadBitBuffer` where the `ElementGainOffsetConfig` data is
68+
* stored. Data read from the buffer is consumed.
69+
* \return `ElementGainOffsetConfig` on success; a specific status on failure.
70+
*/
71+
static absl::StatusOr<ElementGainOffsetConfig> CreateFromBuffer(
72+
ReadBitBuffer& rb);
73+
74+
/*!\brief Writes the `ElementGainOffsetConfig` to a `WriteBitBuffer`.
75+
*
76+
* \param wb `WriteBitBuffer` to write to.
77+
* \return `absl::OkStatus()` on success; a specific status on failure.
78+
*/
79+
absl::Status Write(WriteBitBuffer& wb) const;
80+
81+
/*!\brief Prints logging information about the config.*/
82+
void Print() const;
83+
84+
private:
85+
struct ValueType {
86+
QFormatOrFloatingPoint element_gain_offset;
87+
bool operator==(const ValueType&) const = default;
88+
89+
absl::Status Write(WriteBitBuffer& wb) const;
90+
91+
void Print() const;
92+
};
93+
struct RangeType {
94+
QFormatOrFloatingPoint default_element_gain_offset;
95+
QFormatOrFloatingPoint min_element_gain_offset;
96+
QFormatOrFloatingPoint max_element_gain_offset;
97+
bool operator==(const RangeType&) const = default;
98+
99+
absl::Status Write(WriteBitBuffer& wb) const;
100+
101+
void Print() const;
102+
};
103+
struct ExtensionType {
104+
uint8_t element_gain_offset_config_type;
105+
std::vector<uint8_t> element_gain_offset_bytes;
106+
bool operator==(const ExtensionType&) const = default;
107+
108+
absl::Status Write(WriteBitBuffer& wb) const;
109+
110+
void Print() const;
111+
};
112+
113+
using ElementGainOffsetConfigVariant =
114+
std::variant<ValueType, RangeType, ExtensionType>;
115+
116+
/*!\brief Private constructor.
117+
*
118+
* For use by static factory functions only.
119+
*
120+
* \param element_gain_offset_config_data `ElementGainOffsetConfigVariant` to
121+
* construct from.
122+
*/
123+
explicit ElementGainOffsetConfig(
124+
ElementGainOffsetConfigVariant&& element_gain_offset_config_data)
125+
: element_gain_offset_config_data_(
126+
std::move(element_gain_offset_config_data)) {}
127+
128+
ElementGainOffsetConfigVariant element_gain_offset_config_data_;
129+
};
130+
131+
} // namespace iamf_tools
132+
133+
#endif // OBU_ELEMENT_GAIN_OFFSET_CONFIG_H_

iamf/obu/tests/BUILD

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,19 @@ cc_test(
115115
],
116116
)
117117

118+
cc_test(
119+
name = "element_gain_offset_config_test",
120+
srcs = ["element_gain_offset_config_test.cc"],
121+
deps = [
122+
"//iamf/common:q_format_or_floating_point",
123+
"//iamf/common:read_bit_buffer",
124+
"//iamf/common:write_bit_buffer",
125+
"//iamf/obu:element_gain_offset_config",
126+
"@abseil-cpp//absl/types:span",
127+
"@com_google_googletest//:gtest_main",
128+
],
129+
)
130+
118131
cc_test(
119132
name = "ia_sequence_header_test",
120133
size = "small",

0 commit comments

Comments
 (0)