1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <array>
18 #include <climits>
19 #include <cmath>
20 #include <cstring>
21 #include <memory>
22 #include <vector>
23
24 #include <gtest/gtest.h>
25
26 #include <audio_utils/spdif/SPDIFDecoder.h>
27 #include <audio_utils/spdif/SPDIFEncoder.h>
28
29 using namespace android;
30
31 class MySPDIFEncoder : public SPDIFEncoder {
32 public:
33
MySPDIFEncoder(audio_format_t format)34 explicit MySPDIFEncoder(audio_format_t format)
35 : SPDIFEncoder(format)
36 {
37 }
38 // Defaults to AC3 format. Was in original API.
39 MySPDIFEncoder() = default;
40
writeOutput(const void *,size_t numBytes)41 ssize_t writeOutput( const void* /* buffer */, size_t numBytes ) override {
42 mOutputSizeBytes = numBytes;
43 return numBytes;
44 }
45
getFramer() const46 FrameScanner *getFramer() const { return mFramer; }
getByteCursor() const47 size_t getByteCursor() const { return mByteCursor; }
getPayloadBytesPending() const48 size_t getPayloadBytesPending() const { return mPayloadBytesPending; }
getBurstBufferSizeBytes() const49 size_t getBurstBufferSizeBytes() const { return mBurstBufferSizeBytes; }
50
51 size_t mOutputSizeBytes = 0;
52 };
53
54 class MySPDIFDecoder : public SPDIFDecoder {
55 public:
MySPDIFDecoder(audio_format_t format,const std::vector<uint8_t> && inputData)56 MySPDIFDecoder(audio_format_t format, const std::vector<uint8_t>&& inputData)
57 : SPDIFDecoder(format)
58 , mBurstGenerator(std::make_unique<BurstGenerator>(std::move(inputData),
59 mFramer->getSampleFramesPerSyncFrame() * kSpdifEncodedChannelCount * sizeof(int16_t))) {
60 }
61 // This constructor creates an instance that will return error on reading input.
MySPDIFDecoder(audio_format_t format)62 explicit MySPDIFDecoder(audio_format_t format)
63 : SPDIFDecoder(format)
64 , mBurstGenerator(nullptr) {
65 }
66
readInput(void * buffer,size_t numBytes)67 ssize_t readInput(void* buffer, size_t numBytes) override {
68 return mBurstGenerator == nullptr ? -1
69 : mBurstGenerator->read(reinterpret_cast<uint8_t *>(buffer), numBytes);
70 }
71
getFramer() const72 FrameScanner &getFramer() const { return *mFramer; }
73
74 private:
75 // Generates data bursts of a given size with the provided input data.
76 // If there are remaining bytes in the data burst after input data, they are filled with
77 // incrementing values that wrap around.
78 class BurstGenerator {
79 public:
BurstGenerator(const std::vector<uint8_t> && inputData,size_t burstSizeBytes)80 BurstGenerator(const std::vector<uint8_t> &&inputData, size_t burstSizeBytes)
81 : kBurstSizeBytes(burstSizeBytes)
82 , mBurstBytesRead(0)
83 , mInputData(inputData) {
84 }
85
read(uint8_t * buffer,size_t numBytes)86 ssize_t read(uint8_t* buffer, size_t numBytes) {
87 auto bytesLeft = numBytes;
88 while (bytesLeft > 0) {
89 if (mBurstBytesRead < mInputData.size()) {
90 const auto bytesToRead = std::min(bytesLeft,
91 mInputData.size() - mBurstBytesRead);
92 memcpy(buffer, &mInputData[mBurstBytesRead], bytesToRead);
93 mBurstBytesRead += bytesToRead;
94 bytesLeft -= bytesToRead;
95 buffer += bytesToRead;
96 } else if (mBurstBytesRead < kBurstSizeBytes) {
97 const auto bytesToRead = std::min(bytesLeft, kBurstSizeBytes - mBurstBytesRead);
98 // Pad remaining bytes with incrementing values that wrap around.
99 for (auto i = 0; i < bytesToRead; ++i) {
100 *buffer++ = (mBurstBytesRead++ - mInputData.size()) % 256;
101 }
102 bytesLeft -= bytesToRead;
103 buffer += bytesToRead;
104 } else {
105 mBurstBytesRead = 0;
106 }
107 }
108 return numBytes;
109 }
110
111 private:
112 const size_t kBurstSizeBytes;
113 size_t mBurstBytesRead;
114 const std::vector<uint8_t> mInputData;
115 };
116
117 const std::unique_ptr<BurstGenerator> mBurstGenerator;
118 };
119
120 // This is the beginning of the file voice1-48k-64kbps-15s.ac3
121 static const uint8_t sVoice1ch48k_AC3[] = {
122 0x0b, 0x77, 0x44, 0xcd, 0x08, 0x40, 0x2f, 0x84, 0x29, 0xca, 0x6e, 0x44, 0xa4, 0xfd, 0xce, 0xf7,
123 0xc9, 0x9f, 0x3e, 0x74, 0xfa, 0x01, 0x0a, 0xda, 0xb3, 0x3e, 0xb0, 0x95, 0xf2, 0x5a, 0xef, 0x9e
124 };
125
126 // This is the beginning of the file channelcheck_48k6ch.eac3
127 static const uint8_t sChannel6ch48k_EAC3[] = {
128 0x0b, 0x77, 0x01, 0xbf, 0x3f, 0x85, 0x7f, 0xe8, 0x1e, 0x40, 0x82, 0x10, 0x00, 0x00, 0x00, 0x01,
129 0x00, 0x00, 0x00, 0x03, 0xfc, 0x60, 0x80, 0x7e, 0x59, 0x00, 0xfc, 0xf3, 0xcf, 0x01, 0xf9, 0xe7
130 };
131
132 // Size of the first frame of channelcheck_48k6ch.eac3, in number of bytes
133 static constexpr auto sChannel6ch48k_EAC3_frameSize = 896u;
134
135 // This is the beginning of the file channelcheck_48k6ch.eac3 after encapulating in IEC61937.
136 static const uint8_t sSpdif_Channel6ch48k_EAC3[] = {
137 0x72, 0xf8, 0x1f, 0x4e, 0x15, 0x00, 0x80, 0x03, 0x77, 0x0b, 0xbf, 0x01, 0x85, 0x3f, 0xe8, 0x7f,
138 0x40, 0x1e, 0x10, 0x82, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0xfc, 0x7e, 0x80
139 };
140
141 static const uint8_t sZeros[32] = { 0 };
142
143 static constexpr int kBytesPerOutputFrame = 2 * sizeof(int16_t); // stereo
144
145 static constexpr auto kIEC61937HeaderSize = 4 * sizeof(uint16_t);
146
TEST(audio_utils_spdif,SupportedFormats)147 TEST(audio_utils_spdif, SupportedFormats)
148 {
149 ASSERT_FALSE(SPDIFEncoder::isFormatSupported(AUDIO_FORMAT_PCM_FLOAT));
150 ASSERT_FALSE(SPDIFEncoder::isFormatSupported(AUDIO_FORMAT_PCM_16_BIT));
151 ASSERT_FALSE(SPDIFEncoder::isFormatSupported(AUDIO_FORMAT_MP3));
152
153 ASSERT_TRUE(SPDIFEncoder::isFormatSupported(AUDIO_FORMAT_AC3));
154 ASSERT_TRUE(SPDIFEncoder::isFormatSupported(AUDIO_FORMAT_E_AC3));
155 ASSERT_TRUE(SPDIFEncoder::isFormatSupported(AUDIO_FORMAT_DTS));
156 ASSERT_TRUE(SPDIFEncoder::isFormatSupported(AUDIO_FORMAT_DTS_HD));
157 }
158
TEST(audio_utils_spdif,ScanAC3)159 TEST(audio_utils_spdif, ScanAC3)
160 {
161 MySPDIFEncoder encoder(AUDIO_FORMAT_AC3);
162 FrameScanner *scanner = encoder.getFramer();
163 // It should recognize the valid AC3 header.
164 int i = 0;
165 while (i < 5) {
166 ASSERT_FALSE(scanner->scan(sVoice1ch48k_AC3[i++]));
167 }
168 ASSERT_TRUE(scanner->scan(sVoice1ch48k_AC3[i++]));
169 ASSERT_FALSE(scanner->scan(sVoice1ch48k_AC3[i++]));
170 }
171
TEST(audio_utils_spdif,WriteAC3)172 TEST(audio_utils_spdif, WriteAC3)
173 {
174 MySPDIFEncoder encoder(AUDIO_FORMAT_AC3);
175 encoder.write(sVoice1ch48k_AC3, sizeof(sVoice1ch48k_AC3));
176 ASSERT_EQ(48000, encoder.getFramer()->getSampleRate());
177 ASSERT_EQ(kBytesPerOutputFrame, encoder.getBytesPerOutputFrame());
178 ASSERT_EQ(1, encoder.getRateMultiplier());
179
180 // Check to make sure that the pending bytes calculation did not overflow.
181 size_t burstBufferSizeBytes = encoder.getBurstBufferSizeBytes(); // allocated maximum size
182 size_t pendingBytes = encoder.getPayloadBytesPending();
183 ASSERT_GE(burstBufferSizeBytes, pendingBytes);
184
185 // Write some fake compressed audio to force an output data burst.
186 for (int i = 0; i < 7; i++) {
187 auto result = encoder.write(sZeros, sizeof(sZeros));
188 ASSERT_EQ(sizeof(sZeros), result);
189 }
190 // This value is calculated in SPDIFEncoder::sendZeroPad()
191 // size_t burstSize = mFramer->getSampleFramesPerSyncFrame() * sizeof(uint16_t)
192 // * kSpdifEncodedChannelCount;
193 // If it changes then there is probably a regression.
194 const int kExpectedBurstSize = 6144;
195 ASSERT_EQ(kExpectedBurstSize, encoder.mOutputSizeBytes);
196 }
197
TEST(audio_utils_spdif,ValidEAC3)198 TEST(audio_utils_spdif, ValidEAC3)
199 {
200 MySPDIFEncoder encoder(AUDIO_FORMAT_E_AC3);
201 auto result = encoder.write(sChannel6ch48k_EAC3, sizeof(sChannel6ch48k_EAC3));
202 ASSERT_EQ(sizeof(sChannel6ch48k_EAC3), result);
203 ASSERT_EQ(kSpdifRateMultiplierEac3, encoder.getRateMultiplier());
204 ASSERT_EQ(48000, encoder.getFramer()->getSampleRate());
205 ASSERT_EQ(kBytesPerOutputFrame, encoder.getBytesPerOutputFrame());
206
207 // Check to make sure that the pending bytes calculation did not overflow.
208 size_t bufferSize = encoder.getBurstBufferSizeBytes();
209 size_t pendingBytes = encoder.getPayloadBytesPending();
210 ASSERT_GE(bufferSize, pendingBytes);
211 }
212
TEST(audio_utils_spdif,InvalidLengthEAC3)213 TEST(audio_utils_spdif, InvalidLengthEAC3)
214 {
215 MySPDIFEncoder encoder(AUDIO_FORMAT_E_AC3);
216 // Mangle a valid header and try to force a numeric overflow.
217 uint8_t mangled[sizeof(sChannel6ch48k_EAC3)] = {0};
218 memcpy(mangled, sChannel6ch48k_EAC3, sizeof(sChannel6ch48k_EAC3));
219
220 // force frmsiz to zero!
221 mangled[2] = mangled[2] & 0xF8;
222 mangled[3] = 0;
223 auto result = encoder.write(mangled, sizeof(mangled));
224 ASSERT_EQ(sizeof(mangled), result);
225
226 // Check to make sure that the pending bytes calculation did not overflow.
227 size_t bufferSize = encoder.getBurstBufferSizeBytes();
228 size_t pendingBytes = encoder.getPayloadBytesPending();
229 ASSERT_GE(bufferSize, pendingBytes);
230
231 }
232
TEST(audio_utils_spdif,ScanSPDIF)233 TEST(audio_utils_spdif, ScanSPDIF)
234 {
235 std::vector<uint8_t> tmp;
236 MySPDIFDecoder decoder(AUDIO_FORMAT_E_AC3, std::move(tmp));
237 FrameScanner &scanner = decoder.getFramer();
238 // It should recognize a valid IEC61937 header.
239 int i = 0;
240 while (i < kIEC61937HeaderSize - 1) {
241 ASSERT_FALSE(scanner.scan(sSpdif_Channel6ch48k_EAC3[i++]));
242 }
243 ASSERT_TRUE(scanner.scan(sSpdif_Channel6ch48k_EAC3[i++]));
244 ASSERT_FALSE(scanner.scan(sSpdif_Channel6ch48k_EAC3[i++]));
245 ASSERT_EQ(kIEC61937HeaderSize, scanner.getHeaderSizeBytes());
246 ASSERT_EQ(kSpdifDataTypeEac3, scanner.getDataType());
247 ASSERT_EQ(kSpdifRateMultiplierEac3, scanner.getRateMultiplier());
248 ASSERT_EQ(kSpdifRateMultiplierEac3 * 1536, scanner.getMaxSampleFramesPerSyncFrame());
249 ASSERT_EQ(kSpdifRateMultiplierEac3 * 1536, scanner.getSampleFramesPerSyncFrame());
250 ASSERT_EQ(sChannel6ch48k_EAC3_frameSize, scanner.getFrameSizeBytes());
251 }
252
TEST(audio_utils_spdif,ReadEAC3)253 TEST(audio_utils_spdif, ReadEAC3)
254 {
255 constexpr auto kNumFrames = 2; // Number of IEC61937 frames to read
256 const std::vector<uint8_t> inputData(sSpdif_Channel6ch48k_EAC3,
257 sSpdif_Channel6ch48k_EAC3 + sizeof(sSpdif_Channel6ch48k_EAC3));
258 MySPDIFDecoder decoder(AUDIO_FORMAT_E_AC3, std::move(inputData));
259 for (int n = 0; n < kNumFrames; ++n) {
260 std::vector<uint8_t> buffer(sChannel6ch48k_EAC3_frameSize, 0xff);
261 constexpr auto kChunkSize = 32u;
262 for (int i = 0; i < sChannel6ch48k_EAC3_frameSize / kChunkSize; ++i) {
263 ASSERT_EQ(kChunkSize, decoder.read(buffer.data() + i * kChunkSize, kChunkSize));
264 }
265 // Check the burst payload read from the decoder is correct
266 constexpr auto kNumExtractedEac3Bytes = sizeof(sSpdif_Channel6ch48k_EAC3)
267 - kIEC61937HeaderSize;
268 ASSERT_EQ(0, memcmp(sChannel6ch48k_EAC3, buffer.data(), kNumExtractedEac3Bytes));
269 uint16_t *p = reinterpret_cast<uint16_t *>(buffer.data());
270 for (auto i = 0; i < (sChannel6ch48k_EAC3_frameSize - kNumExtractedEac3Bytes) / 2; ++i) {
271 ASSERT_EQ(((i * 2) % 256) << 8 | ((i * 2 + 1) % 256),
272 p[kNumExtractedEac3Bytes / 2 + i]);
273 }
274 }
275 }
276
TEST(audio_utils_spdif,ReadErrorEAC3)277 TEST(audio_utils_spdif, ReadErrorEAC3)
278 {
279 MySPDIFDecoder decoder(AUDIO_FORMAT_E_AC3);
280 std::vector<uint8_t> buffer(sChannel6ch48k_EAC3_frameSize, 0xff);
281 constexpr auto kChunkSize = 32u;
282 ASSERT_EQ(-1, decoder.read(buffer.data(), kChunkSize));
283 }
284
TEST(audio_utils_spdif,ReadAfterResetEAC3)285 TEST(audio_utils_spdif, ReadAfterResetEAC3)
286 {
287 const std::vector<uint8_t> inputData(sSpdif_Channel6ch48k_EAC3,
288 sSpdif_Channel6ch48k_EAC3 + sizeof(sSpdif_Channel6ch48k_EAC3));
289 MySPDIFDecoder decoder(AUDIO_FORMAT_E_AC3, std::move(inputData));
290 constexpr auto kChunkSize = 32u;
291 std::vector<uint8_t> buffer(sChannel6ch48k_EAC3_frameSize, 0xff);
292 ASSERT_EQ(kChunkSize, decoder.read(buffer.data(), kChunkSize));
293 constexpr auto kNumExtractedEac3Bytes = sizeof(sSpdif_Channel6ch48k_EAC3)
294 - kIEC61937HeaderSize;
295 ASSERT_EQ(0, memcmp(sChannel6ch48k_EAC3, buffer.data(), kNumExtractedEac3Bytes));
296
297 // Reset after partial read and ensure decoder is able to resync to next data burst
298 decoder.reset();
299 for (int i = 0; i < sChannel6ch48k_EAC3_frameSize / kChunkSize; ++i) {
300 ASSERT_EQ(kChunkSize, decoder.read(buffer.data() + i * kChunkSize, kChunkSize));
301 }
302 // Check the burst payload read from the decoder is correct
303 ASSERT_EQ(0, memcmp(sChannel6ch48k_EAC3, buffer.data(), kNumExtractedEac3Bytes));
304 uint16_t *p = reinterpret_cast<uint16_t *>(buffer.data());
305 for (auto i = 0; i < (sChannel6ch48k_EAC3_frameSize - kNumExtractedEac3Bytes) / 2; ++i) {
306 ASSERT_EQ(((i * 2) % 256) << 8 | ((i * 2 + 1) % 256), p[kNumExtractedEac3Bytes / 2 + i]);
307 }
308 }
309