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/common/utils/sample_processing_utils.h"
13
14 #include <array>
15 #include <cstddef>
16 #include <cstdint>
17 #include <vector>
18
19 #include "absl/functional/any_invocable.h"
20 #include "absl/status/status.h"
21 #include "absl/status/status_matchers.h"
22 #include "absl/strings/string_view.h"
23 #include "absl/types/span.h"
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26
27 namespace iamf_tools {
28 namespace {
29
30 using ::absl_testing::IsOk;
31 using ::absl_testing::StatusIs;
32 using ::testing::ElementsAreArray;
33
TEST(WritePcmSample,LittleEndian32Bits)34 TEST(WritePcmSample, LittleEndian32Bits) {
35 std::vector<uint8_t> buffer(4, 0);
36 size_t write_position = 0;
37 EXPECT_THAT(WritePcmSample(0x12345678, 32, /*big_endian=*/false,
38 buffer.data(), write_position),
39 IsOk());
40 EXPECT_EQ(write_position, 4);
41 std::vector<uint8_t> expected_result = {0x78, 0x56, 0x34, 0x12};
42 EXPECT_EQ(buffer, expected_result);
43 }
44
TEST(WritePcmSample,BigEndian32bits)45 TEST(WritePcmSample, BigEndian32bits) {
46 std::vector<uint8_t> buffer(4, 0);
47 size_t write_position = 0;
48 EXPECT_THAT(WritePcmSample(0x12345678, 32, /*big_endian=*/true, buffer.data(),
49 write_position),
50 IsOk());
51 EXPECT_EQ(write_position, 4);
52 std::vector<uint8_t> expected_result = {0x12, 0x34, 0x56, 0x78};
53 EXPECT_EQ(buffer, expected_result);
54 }
55
TEST(WritePcmSample,LittleEndian24Bits)56 TEST(WritePcmSample, LittleEndian24Bits) {
57 std::vector<uint8_t> buffer(3, 0);
58 size_t write_position = 0;
59 EXPECT_THAT(WritePcmSample(0x12345600, 24, /*big_endian=*/false,
60 buffer.data(), write_position),
61 IsOk());
62 EXPECT_EQ(write_position, 3);
63 std::vector<uint8_t> expected_result = {0x56, 0x34, 0x12};
64 EXPECT_EQ(buffer, expected_result);
65 }
66
TEST(WritePcmSample,BigEndian24Bits)67 TEST(WritePcmSample, BigEndian24Bits) {
68 std::vector<uint8_t> buffer(3, 0);
69 size_t write_position = 0;
70 EXPECT_THAT(WritePcmSample(0x12345600, 24, /*big_endian=*/true, buffer.data(),
71 write_position),
72 IsOk());
73 EXPECT_EQ(write_position, 3);
74 std::vector<uint8_t> expected_result = {0x12, 0x34, 0x56};
75 EXPECT_EQ(buffer, expected_result);
76 }
77
TEST(WritePcmSample,LittleEndian16Bits)78 TEST(WritePcmSample, LittleEndian16Bits) {
79 std::vector<uint8_t> buffer(2, 0);
80 size_t write_position = 0;
81 EXPECT_THAT(WritePcmSample(0x12340000, 16, /*big_endian=*/false,
82 buffer.data(), write_position),
83 IsOk());
84 EXPECT_EQ(write_position, 2);
85 std::vector<uint8_t> expected_result = {0x34, 0x12};
86 EXPECT_EQ(buffer, expected_result);
87 }
88
TEST(WritePcmSample,BigEndian16Bits)89 TEST(WritePcmSample, BigEndian16Bits) {
90 std::vector<uint8_t> buffer(2, 0);
91 size_t write_position = 0;
92 EXPECT_THAT(WritePcmSample(0x12340000, 16, /*big_endian=*/true, buffer.data(),
93 write_position),
94 IsOk());
95 EXPECT_EQ(write_position, 2);
96 std::vector<uint8_t> expected_result = {0x12, 0x34};
97 EXPECT_EQ(buffer, expected_result);
98 }
99
TEST(WritePcmSample,InvalidOver32Bits)100 TEST(WritePcmSample, InvalidOver32Bits) {
101 std::vector<uint8_t> buffer(5, 0);
102 size_t write_position = 0;
103 EXPECT_EQ(WritePcmSample(0x00000000, 40, /*big_endian=*/false, buffer.data(),
104 write_position)
105 .code(),
106 absl::StatusCode::kInvalidArgument);
107 }
108
109 const absl::AnyInvocable<absl::Status(int32_t, int32_t&) const>
__anonfec31a6a0202(int32_t input, int32_t& output) 110 kIdentityTransform = [](int32_t input, int32_t& output) {
111 output = input;
112 return absl::OkStatus();
113 };
114
TEST(ConvertInterleavedToTimeChannel,FailsIfSamplesIsNotAMultipleOfChannels)115 TEST(ConvertInterleavedToTimeChannel, FailsIfSamplesIsNotAMultipleOfChannels) {
116 constexpr std::array<int32_t, 4> kFourTestValues = {1, 2, 3, 4};
117 constexpr size_t kNumChannels = 3;
118 std::vector<std::vector<int32_t>> undefined_result(
119 1, std::vector<int32_t>(kNumChannels));
120 size_t undefined_num_ticks;
121 EXPECT_THAT(ConvertInterleavedToTimeChannel(
122 absl::MakeConstSpan(kFourTestValues), kNumChannels,
123 kIdentityTransform, undefined_result, undefined_num_ticks),
124 StatusIs(absl::StatusCode::kInvalidArgument));
125 }
126
TEST(ConvertInterleavedToTimeChannel,FailsIfTooFewTicksInResult)127 TEST(ConvertInterleavedToTimeChannel, FailsIfTooFewTicksInResult) {
128 constexpr std::array<int32_t, 4> kFourTestValues = {1, 2, 3, 4};
129 constexpr size_t kNumChannels = 2;
130 const size_t input_num_ticks = kFourTestValues.size() / kNumChannels;
131
132 // The result has one fewer ticks than the input, which will be rejected.
133 std::vector<std::vector<int32_t>> undefined_result(
134 input_num_ticks - 1, std::vector<int32_t>(kNumChannels));
135 size_t undefined_num_ticks;
136 EXPECT_THAT(ConvertInterleavedToTimeChannel(
137 absl::MakeConstSpan(kFourTestValues), kNumChannels,
138 kIdentityTransform, undefined_result, undefined_num_ticks),
139 StatusIs(absl::StatusCode::kInvalidArgument));
140 }
141
TEST(ConvertInterleavedToTimeChannel,FailsIfDifferentChannelNumbersInResult)142 TEST(ConvertInterleavedToTimeChannel, FailsIfDifferentChannelNumbersInResult) {
143 constexpr std::array<int32_t, 4> kFourTestValues = {1, 2, 3, 4};
144 constexpr size_t kNumChannels = 2;
145 const size_t input_num_ticks = kFourTestValues.size() / kNumChannels;
146
147 // The result has a different number of channels than the input, which will be
148 // rejected.
149 std::vector<std::vector<int32_t>> undefined_result(
150 input_num_ticks, std::vector<int32_t>(kNumChannels + 1));
151 size_t undefined_num_ticks;
152 EXPECT_THAT(ConvertInterleavedToTimeChannel(
153 absl::MakeConstSpan(kFourTestValues), kNumChannels,
154 kIdentityTransform, undefined_result, undefined_num_ticks),
155 StatusIs(absl::StatusCode::kInvalidArgument));
156 }
157
TEST(ConvertInterleavedToTimeChannel,PropagatesError)158 TEST(ConvertInterleavedToTimeChannel, PropagatesError) {
159 const absl::Status kError = absl::InternalError("Test error");
160 const size_t kNumChannels = 2;
161 constexpr std::array<int32_t, 4> kSamples{1, 2, 3, 4};
162 const size_t kNumTicks = kSamples.size() / kNumChannels;
163 const absl::AnyInvocable<absl::Status(int32_t, int32_t&) const>
164 kAlwaysErrorTransform =
165 [kError](int32_t input, int32_t& output) { return kError; };
166 std::vector<std::vector<int32_t>> undefined_result(
167 kNumTicks, std::vector<int32_t>(kNumChannels));
168 size_t undefined_num_ticks;
169 EXPECT_EQ(ConvertInterleavedToTimeChannel(
170 absl::MakeConstSpan(kSamples), kNumChannels,
171 kAlwaysErrorTransform, undefined_result, undefined_num_ticks),
172 kError);
173 }
174
TEST(ConvertInterleavedToTimeChannel,SucceedsOnEmptySamples)175 TEST(ConvertInterleavedToTimeChannel, SucceedsOnEmptySamples) {
176 constexpr std::array<int32_t, 0> kEmptySamples{};
177 constexpr size_t kNumChannels = 2;
178 std::vector<std::vector<int32_t>> result;
179 size_t num_ticks = 0;
180 EXPECT_THAT(ConvertInterleavedToTimeChannel(
181 absl::MakeConstSpan(kEmptySamples), kNumChannels,
182 kIdentityTransform, result, num_ticks),
183 IsOk());
184 EXPECT_EQ(num_ticks, 0);
185 }
186
TEST(ConvertInterleavedToTimeChannel,DoesNotAlterOutputVector)187 TEST(ConvertInterleavedToTimeChannel, DoesNotAlterOutputVector) {
188 constexpr size_t kNumChannels = 2;
189 constexpr std::array<int32_t, 0> kEmptySamples{};
190 std::vector<std::vector<int32_t>> result = {{1, 2}, {3, 4}};
191 const auto copy_of_result = result;
192 size_t num_ticks = 0;
193 EXPECT_THAT(ConvertInterleavedToTimeChannel(
194 absl::MakeConstSpan(kEmptySamples), kNumChannels,
195 kIdentityTransform, result, num_ticks),
196 IsOk());
197
198 // Result is not changed but the valid range (`num_ticks`) is zero, meaning
199 // none of the result should be used.
200 EXPECT_EQ(copy_of_result, result);
201 EXPECT_EQ(num_ticks, 0);
202 }
203
TEST(ConvertInterleavedToTimeChannel,InterleavesResults)204 TEST(ConvertInterleavedToTimeChannel, InterleavesResults) {
205 constexpr size_t kNumChannels = 3;
206 constexpr std::array<int32_t, 6> kTwoTicksOfThreeChannels{1, 2, 3, 4, 5, 6};
207 const std::vector<std::vector<int32_t>> kExpectedTwoTicksForThreeChannels = {
208 {1, 2, 3}, {4, 5, 6}};
209 std::vector<std::vector<int32_t>> result(2,
210 std::vector<int32_t>(kNumChannels));
211 size_t num_ticks = 0;
212 EXPECT_THAT(ConvertInterleavedToTimeChannel(
213 absl::MakeConstSpan(kTwoTicksOfThreeChannels), kNumChannels,
214 kIdentityTransform, result, num_ticks),
215 IsOk());
216 EXPECT_EQ(result, kExpectedTwoTicksForThreeChannels);
217 EXPECT_EQ(num_ticks, 2);
218 }
219
TEST(ConvertInterleavedToTimeChannel,AppliesTransform)220 TEST(ConvertInterleavedToTimeChannel, AppliesTransform) {
221 const size_t kNumChannels = 2;
222 constexpr std::array<int32_t, 4> kSamples = {1, 2, 3, 4};
223 const std::vector<std::vector<int32_t>> kExpectedResult = {{2, 4}, {6, 8}};
224 const absl::AnyInvocable<absl::Status(int32_t, int32_t&) const>
225 kDoublingTransform = [](int32_t input, int32_t& output) {
226 output = input * 2;
227 return absl::OkStatus();
228 };
229 std::vector<std::vector<int32_t>> result(2,
230 std::vector<int32_t>(kNumChannels));
231 size_t num_ticks = 0;
232 EXPECT_THAT(ConvertInterleavedToTimeChannel(absl::MakeConstSpan(kSamples),
233 kNumChannels, kDoublingTransform,
234 result, num_ticks),
235 IsOk());
236 EXPECT_EQ(result, kExpectedResult);
237 EXPECT_EQ(num_ticks, 2);
238 }
239
TEST(ConvertTimeChannelToInterleaved,FailsIfSamplesHaveAnUnevenNumberOfChannels)240 TEST(ConvertTimeChannelToInterleaved,
241 FailsIfSamplesHaveAnUnevenNumberOfChannels) {
242 std::vector<std::vector<int32_t>> input = {{1, 2}, {3, 4, 5}};
243 std::vector<int32_t> undefined_result;
244
245 EXPECT_THAT(
246 ConvertTimeChannelToInterleaved(absl::MakeConstSpan(input),
247 kIdentityTransform, undefined_result),
248 StatusIs(absl::StatusCode::kInvalidArgument));
249 }
250
TEST(ConvertTimeChannelToInterleaved,PropagatesError)251 TEST(ConvertTimeChannelToInterleaved, PropagatesError) {
252 const absl::Status kError = absl::InternalError("Test error");
253 const std::vector<std::vector<int32_t>> kInput = {{1, 2, 3}, {4, 5, 6}};
254 const absl::AnyInvocable<absl::Status(int32_t, int32_t&) const>
255 kAlwaysErrorTransform =
256 [kError](int32_t /*input*/, int32_t& /*output*/) { return kError; };
257 std::vector<int32_t> undefined_result;
258
259 EXPECT_EQ(
260 ConvertTimeChannelToInterleaved(absl::MakeConstSpan(kInput),
261 kAlwaysErrorTransform, undefined_result),
262 kError);
263 }
264
TEST(ConvertTimeChannelToInterleaved,SucceedsOnEmptyInput)265 TEST(ConvertTimeChannelToInterleaved, SucceedsOnEmptyInput) {
266 const std::vector<std::vector<int32_t>> kEmptyInput;
267 std::vector<int32_t> result;
268
269 EXPECT_THAT(ConvertTimeChannelToInterleaved(absl::MakeConstSpan(kEmptyInput),
270 kIdentityTransform, result),
271 IsOk());
272 EXPECT_TRUE(result.empty());
273 }
274
TEST(ConvertTimeChannelToInterleaved,ClearsOutputVector)275 TEST(ConvertTimeChannelToInterleaved, ClearsOutputVector) {
276 const std::vector<std::vector<int32_t>> kInput = {{1}};
277 std::vector<int32_t> result = {1, 2, 3};
278 constexpr std::array<int32_t, 1> kExpectedResult{1};
279
280 EXPECT_THAT(ConvertTimeChannelToInterleaved(absl::MakeConstSpan(kInput),
281 kIdentityTransform, result),
282 IsOk());
283 EXPECT_THAT(result, ElementsAreArray(kExpectedResult));
284 }
285
TEST(ConvertTimeChannelToInterleaved,InterleavesResult)286 TEST(ConvertTimeChannelToInterleaved, InterleavesResult) {
287 const std::vector<std::vector<int32_t>> kInput = {{1, 2, 3}, {4, 5, 6}};
288 std::vector<int32_t> result;
289 constexpr std::array<int32_t, 6> kExpectedResult{1, 2, 3, 4, 5, 6};
290
291 EXPECT_THAT(ConvertTimeChannelToInterleaved(absl::MakeConstSpan(kInput),
292 kIdentityTransform, result),
293 IsOk());
294 EXPECT_THAT(result, ElementsAreArray(kExpectedResult));
295 }
296
TEST(ConvertTimeChannelToInterleaved,AppliesTransform)297 TEST(ConvertTimeChannelToInterleaved, AppliesTransform) {
298 const std::vector<std::vector<int32_t>> kInput = {{1, 2, 3}, {4, 5, 6}};
299 std::vector<int32_t> result;
300 const absl::AnyInvocable<absl::Status(int32_t, int32_t&) const>
301 kDoublingTransform = [](int32_t input, int32_t& output) {
302 output = input * 2;
303 return absl::OkStatus();
304 };
305 constexpr std::array<int32_t, 6> kExpectedResult{2, 4, 6, 8, 10, 12};
306
307 EXPECT_THAT(ConvertTimeChannelToInterleaved(absl::MakeConstSpan(kInput),
308 kDoublingTransform, result),
309 IsOk());
310 EXPECT_THAT(result, ElementsAreArray(kExpectedResult));
311 }
312
313 } // namespace
314 } // namespace iamf_tools
315