• 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/cli/tests/cli_test_utils.h"
13 
14 #include <array>
15 #include <cstddef>
16 #include <cstdint>
17 #include <filesystem>
18 #include <fstream>
19 #include <ios>
20 #include <list>
21 #include <numeric>
22 #include <optional>
23 #include <vector>
24 
25 #include "absl/status/status.h"
26 #include "absl/status/status_matchers.h"
27 #include "absl/strings/string_view.h"
28 #include "absl/types/span.h"
29 #include "gmock/gmock.h"
30 #include "gtest/gtest.h"
31 #include "iamf/common/write_bit_buffer.h"
32 #include "iamf/obu/obu_base.h"
33 #include "iamf/obu/obu_header.h"
34 #include "iamf/obu/tests/obu_test_utils.h"
35 
36 namespace iamf_tools {
37 namespace {
38 
39 using ::absl_testing::IsOk;
40 using ::testing::Not;
41 
TEST(GetLogSpectralDistance,ReturnsCorrectValue)42 TEST(GetLogSpectralDistance, ReturnsCorrectValue) {
43   std::vector<double> first_log_spectrum(10);
44   std::iota(first_log_spectrum.begin(), first_log_spectrum.end(), 0);
45   std::vector<double> second_log_spectrum(10);
46   std::iota(second_log_spectrum.begin(), second_log_spectrum.end(), 1);
47   EXPECT_EQ(GetLogSpectralDistance(absl::MakeConstSpan(first_log_spectrum),
48                                    absl::MakeConstSpan(second_log_spectrum)),
49             10.0);
50 }
51 
TEST(ExpectLogSpectralDistanceBelowThreshold,ReturnsZeroWhenEqual)52 TEST(ExpectLogSpectralDistanceBelowThreshold, ReturnsZeroWhenEqual) {
53   std::vector<double> first_log_spectrum(10);
54   std::iota(first_log_spectrum.begin(), first_log_spectrum.end(), 1);
55   std::vector<double> second_log_spectrum(10);
56   std::iota(second_log_spectrum.begin(), second_log_spectrum.end(), 1);
57   EXPECT_EQ(GetLogSpectralDistance(absl::MakeConstSpan(first_log_spectrum),
58                                    absl::MakeConstSpan(second_log_spectrum)),
59             0.0);
60 }
61 
TEST(ReadFileToBytes,FailsIfFileDoesNotExist)62 TEST(ReadFileToBytes, FailsIfFileDoesNotExist) {
63   const std::filesystem::path file_path_does_not_exist(
64       GetAndCleanupOutputFileName(".bin"));
65 
66   ASSERT_FALSE(std::filesystem::exists(file_path_does_not_exist));
67 
68   std::vector<uint8_t> bytes;
69   EXPECT_FALSE(ReadFileToBytes(file_path_does_not_exist, bytes).ok());
70 }
71 
WriteVectorToFile(const std::filesystem::path filename,const std::vector<uint8_t> & bytes)72 void WriteVectorToFile(const std::filesystem::path filename,
73                        const std::vector<uint8_t>& bytes) {
74   std::filesystem::remove(filename);
75   WriteBitBuffer wb(0);
76 
77   ASSERT_THAT(wb.WriteUint8Span(absl::MakeConstSpan(bytes)), IsOk());
78   auto output_file = std::make_optional<std::fstream>(
79       filename.string(), std::ios::binary | std::ios::out);
80   ASSERT_THAT(wb.FlushAndWriteToFile(output_file), IsOk());
81   output_file->close();
82 }
83 
TEST(ReadFileToBytes,ReadsFileContents)84 TEST(ReadFileToBytes, ReadsFileContents) {
85   // Prepare a file to read back.
86   const std::filesystem::path file_to_read(GetAndCleanupOutputFileName(".bin"));
87   const std::vector<uint8_t> kExpectedBytes = {0x01, 0x02, 0x00, 0x03, 0x04};
88   WriteVectorToFile(file_to_read, kExpectedBytes);
89 
90   std::vector<uint8_t> bytes;
91   EXPECT_THAT(ReadFileToBytes(file_to_read, bytes), IsOk());
92 
93   EXPECT_EQ(bytes, kExpectedBytes);
94 }
95 
TEST(ReadFileToBytes,AppendsFileContents)96 TEST(ReadFileToBytes, AppendsFileContents) {
97   // Prepare a file to read back.
98   const std::filesystem::path file_to_read(GetAndCleanupOutputFileName(".bin"));
99   const std::vector<uint8_t> kExpectedBytes = {0x01, 0x02, 0x00, 0x03, 0x04};
100   WriteVectorToFile(file_to_read, kExpectedBytes);
101 
102   std::vector<uint8_t> bytes;
103   EXPECT_THAT(ReadFileToBytes(file_to_read, bytes), IsOk());
104   EXPECT_EQ(bytes.size(), kExpectedBytes.size());
105   // The vector grows with each read.
106   EXPECT_THAT(ReadFileToBytes(file_to_read, bytes), IsOk());
107   EXPECT_EQ(bytes.size(), kExpectedBytes.size() * 2);
108 }
109 
TEST(ReadFileToBytes,ReadsBinaryFileWithPlatformDependentControlCharacters)110 TEST(ReadFileToBytes, ReadsBinaryFileWithPlatformDependentControlCharacters) {
111   // Prepare a file to read back.
112   const std::filesystem::path file_to_read(GetAndCleanupOutputFileName(".bin"));
113   const std::vector<uint8_t> kBinaryDataWithPlatformDependentControlCharacters =
114       {'\n', '\r', '\n', '\r', '\x1a', '\r', '\n', '\n', ' ', '\n'};
115   WriteVectorToFile(file_to_read,
116                     kBinaryDataWithPlatformDependentControlCharacters);
117 
118   std::vector<uint8_t> bytes;
119   EXPECT_THAT(ReadFileToBytes(file_to_read, bytes), IsOk());
120 
121   EXPECT_THAT(bytes, kBinaryDataWithPlatformDependentControlCharacters);
122 }
123 
TEST(SerializeObusExpectOk,SerializesObus)124 TEST(SerializeObusExpectOk, SerializesObus) {
125   MockObu mock_obu(ObuHeader{}, ObuType::kObuIaCodecConfig);
126   constexpr size_t kObuHeaderSize = 2;
127   constexpr std::array<uint8_t, 6> kExpectedBytes = {// OBU header.
128                                                      0x00, 0x04,
129                                                      // OBU payload.
130                                                      0x01, 0x02, 0x00, 0x03};
131 
132   ON_CALL(mock_obu, ValidateAndWritePayload)
133       .WillByDefault([&](WriteBitBuffer& wb) {
134         return wb.WriteUint8Span(
135             absl::MakeConstSpan(kExpectedBytes).subspan(kObuHeaderSize));
136       });
137   const std::vector<uint8_t> serialized_obus =
138       SerializeObusExpectOk(std::list<const ObuBase*>{&mock_obu});
139 
140   EXPECT_EQ(absl::MakeConstSpan(serialized_obus),
141             absl::MakeConstSpan(kExpectedBytes));
142 }
143 
TEST(OneFrameDelayer,ValidatesInputShapeWithTooManyChannels)144 TEST(OneFrameDelayer, ValidatesInputShapeWithTooManyChannels) {
145   // Input shape validation is managed by `SampleProcessorBase`.
146   constexpr uint32_t kNumSamplesPerFrame = 3;
147   constexpr size_t kNumChannels = 1;
148   OneFrameDelayer one_frame_delayer(kNumSamplesPerFrame, kNumChannels);
149   const std::vector<std::vector<int32_t>> kInputFrameWithTooManyChannels(
150       kNumSamplesPerFrame, std::vector<int32_t>(kNumChannels + 1, 0));
151 
152   EXPECT_THAT(one_frame_delayer.PushFrame(kInputFrameWithTooManyChannels),
153               Not(IsOk()));
154 }
155 
TEST(OneFrameDelayer,ValidatesInputShapeWithTooManySamplesPerFrame)156 TEST(OneFrameDelayer, ValidatesInputShapeWithTooManySamplesPerFrame) {
157   // Input shape validation is managed by `SampleProcessorBase`.
158   constexpr uint32_t kNumSamplesPerFrame = 3;
159   constexpr size_t kNumChannels = 1;
160   OneFrameDelayer one_frame_delayer(kNumSamplesPerFrame, kNumChannels);
161   const std::vector<std::vector<int32_t>> kInputFrameWithTooFewSamples(
162       kNumSamplesPerFrame + 1, std::vector<int32_t>(kNumChannels, 0));
163 
164   EXPECT_THAT(one_frame_delayer.PushFrame(kInputFrameWithTooFewSamples),
165               Not(IsOk()));
166 }
167 
TEST(OneFrameDelayer,DelaysSamplesByOneFrame)168 TEST(OneFrameDelayer, DelaysSamplesByOneFrame) {
169   constexpr uint32_t kNumSamplesPerFrame = 5;
170   constexpr size_t kNumChannels = 4;
171   const std::vector<std::vector<int32_t>> kFirstInputFrame = {
172       {{1, 2, 3, 4},
173        {5, 6, 7, 8},
174        {9, 10, 11, 12},
175        {13, 14, 15, 16},
176        {17, 18, 19, 20}}};
177   const std::vector<std::vector<int32_t>> kSecondInputFrame = {
178       {{21, 22, 23, 24}}};
179   OneFrameDelayer one_frame_delayer(kNumSamplesPerFrame, kNumChannels);
180   // Nothing is available at the start.
181   EXPECT_TRUE(one_frame_delayer.GetOutputSamplesAsSpan().empty());
182   EXPECT_THAT(one_frame_delayer.PushFrame(kFirstInputFrame), IsOk());
183   // Still nothing is available because the samples are delayed by a frame.
184   EXPECT_TRUE(one_frame_delayer.GetOutputSamplesAsSpan().empty());
185 
186   // Pushing in a new frame will cause the first frame to be available.
187   EXPECT_THAT(one_frame_delayer.PushFrame(kSecondInputFrame), IsOk());
188 
189   EXPECT_THAT(one_frame_delayer.GetOutputSamplesAsSpan(), kFirstInputFrame);
190 }
191 
TEST(OneFrameDelayer,GetOutputSamplesAsSpanReturnsFinalFrameAfterFlush)192 TEST(OneFrameDelayer, GetOutputSamplesAsSpanReturnsFinalFrameAfterFlush) {
193   constexpr uint32_t kNumSamplesPerFrame = 5;
194   constexpr size_t kNumChannels = 4;
195   const std::vector<std::vector<int32_t>> kFirstInputFrame = {
196       {{1, 2, 3, 4},
197        {5, 6, 7, 8},
198        {9, 10, 11, 12},
199        {13, 14, 15, 16},
200        {17, 18, 19, 20}}};
201   OneFrameDelayer one_frame_delayer(kNumSamplesPerFrame, kNumChannels);
202   EXPECT_THAT(one_frame_delayer.PushFrame(kFirstInputFrame), IsOk());
203   // Nothing is available because the samples are delayed by a frame.
204   EXPECT_TRUE(one_frame_delayer.GetOutputSamplesAsSpan().empty());
205 
206   // Flushing will allow access to the final delayed frame.
207   EXPECT_THAT(one_frame_delayer.Flush(), IsOk());
208 
209   EXPECT_THAT(one_frame_delayer.GetOutputSamplesAsSpan(), kFirstInputFrame);
210 }
211 
212 }  // namespace
213 }  // namespace iamf_tools
214