xref: /aosp_15_r20/system/media/audio_utils/tests/spdif_tests.cpp (revision b9df5ad1c9ac98a7fefaac271a55f7ae3db05414)
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