• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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