blob: 62f547d99836220e4a46fc68c54b1c762a96397e [file] [log] [blame]
Tim Yao72bc0fb2019-12-03 11:04:19 -08001/*
2 * Copyright 2014, 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 <stdint.h>
18#include <string.h>
19
20#define LOG_TAG "AudioSPDIF"
21#include <cutils/log.h>
22#include <audio_utils/spdif/SPDIFEncoder.h>
23
24#include "AC3FrameScanner.h"
25#include "DTSFrameScanner.h"
Tim Yaocd4e4eb2020-07-24 01:47:28 -070026#include "MatFrameScanner.h"
Tim Yao72bc0fb2019-12-03 11:04:19 -080027
28namespace android {
29
30// Burst Preamble defined in IEC61937-1
31const uint16_t SPDIFEncoder::kSPDIFSync1 = 0xF872; // Pa
32const uint16_t SPDIFEncoder::kSPDIFSync2 = 0x4E1F; // Pb
33
34static int32_t sEndianDetector = 1;
35#define isLittleEndian() (*((uint8_t *)&sEndianDetector))
36
37SPDIFEncoder::SPDIFEncoder(audio_format_t format)
38 : mFramer(NULL)
39 , mSampleRate(48000)
40 , mBurstBuffer(NULL)
41 , mBurstBufferSizeBytes(0)
42 , mRateMultiplier(1)
43 , mBurstFrames(0)
44 , mByteCursor(0)
45 , mBitstreamNumber(0)
46 , mPayloadBytesPending(0)
47 , mScanning(true)
48{
49 switch(format) {
50 case AUDIO_FORMAT_AC3:
51 case AUDIO_FORMAT_E_AC3:
52 mFramer = new AC3FrameScanner(format);
53 break;
54 case AUDIO_FORMAT_DTS:
55 case AUDIO_FORMAT_DTS_HD:
56 mFramer = new DTSFrameScanner();
57 break;
Tim Yaocd4e4eb2020-07-24 01:47:28 -070058 case AUDIO_FORMAT_MAT:
59 mFramer = new MatFrameScanner();
60 break;
Tim Yao72bc0fb2019-12-03 11:04:19 -080061 default:
62 break;
63 }
64
65 // This a programmer error. Call isFormatSupported() first.
66 LOG_ALWAYS_FATAL_IF((mFramer == NULL),
67 "SPDIFEncoder: invalid audio format = 0x%08X", format);
68
69 mBurstBufferSizeBytes = sizeof(uint16_t)
70 * SPDIF_ENCODED_CHANNEL_COUNT
71 * mFramer->getMaxSampleFramesPerSyncFrame();
72
73 ALOGI("SPDIFEncoder: mBurstBufferSizeBytes = %zu, littleEndian = %d",
74 mBurstBufferSizeBytes, isLittleEndian());
75 mBurstBuffer = new uint16_t[mBurstBufferSizeBytes >> 1];
76 clearBurstBuffer();
77}
78
79SPDIFEncoder::SPDIFEncoder()
80 : SPDIFEncoder(AUDIO_FORMAT_AC3)
81{
82}
83
84SPDIFEncoder::~SPDIFEncoder()
85{
86 delete[] mBurstBuffer;
87 delete mFramer;
88}
89
90bool SPDIFEncoder::isFormatSupported(audio_format_t format)
91{
92 switch(format) {
93 case AUDIO_FORMAT_AC3:
94 case AUDIO_FORMAT_E_AC3:
95 case AUDIO_FORMAT_DTS:
96 case AUDIO_FORMAT_DTS_HD:
97 return true;
98 default:
99 return false;
100 }
101}
102
103int SPDIFEncoder::getBytesPerOutputFrame()
104{
105 return SPDIF_ENCODED_CHANNEL_COUNT * sizeof(int16_t);
106}
107
108void SPDIFEncoder::writeBurstBufferShorts(const uint16_t *buffer, size_t numShorts)
109{
110 // avoid static analyser warning
111 LOG_ALWAYS_FATAL_IF((mBurstBuffer == NULL), "mBurstBuffer never allocated");
112 mByteCursor = (mByteCursor + 1) & ~1; // round up to even byte
113 size_t bytesToWrite = numShorts * sizeof(uint16_t);
114 if ((mByteCursor + bytesToWrite) > mBurstBufferSizeBytes) {
115 ALOGE("SPDIFEncoder: Burst buffer overflow!");
116 reset();
117 return;
118 }
119 memcpy(&mBurstBuffer[mByteCursor >> 1], buffer, bytesToWrite);
120 mByteCursor += bytesToWrite;
121}
122
123// Pack the bytes into the short buffer in the order:
124// byte[0] -> short[0] MSB
125// byte[1] -> short[0] LSB
126// byte[2] -> short[1] MSB
127// byte[3] -> short[1] LSB
128// etcetera
129// This way they should come out in the correct order for SPDIF on both
130// Big and Little Endian CPUs.
131void SPDIFEncoder::writeBurstBufferBytes(const uint8_t *buffer, size_t numBytes)
132{
133 size_t bytesToWrite = numBytes;
134 if ((mByteCursor + bytesToWrite) > mBurstBufferSizeBytes) {
135 ALOGE("SPDIFEncoder: Burst buffer overflow!");
136 clearBurstBuffer();
137 return;
138 }
139 uint16_t pad = mBurstBuffer[mByteCursor >> 1];
140 for (size_t i = 0; i < bytesToWrite; i++) {
141 if (mByteCursor & 1 ) {
142 pad |= *buffer++; // put second byte in LSB
143 mBurstBuffer[mByteCursor >> 1] = pad;
144 pad = 0;
145 } else {
146 pad |= (*buffer++) << 8; // put first byte in MSB
147 }
148 mByteCursor++;
149 }
150 // Save partially filled short.
151 if (mByteCursor & 1 ){
152 mBurstBuffer[mByteCursor >> 1] = pad;
153 }
154}
155
156void SPDIFEncoder::sendZeroPad()
157{
158 // Pad remainder of burst with zeros.
159 size_t burstSize = mFramer->getSampleFramesPerSyncFrame() * sizeof(uint16_t)
160 * SPDIF_ENCODED_CHANNEL_COUNT;
161 if (mByteCursor > burstSize) {
162 ALOGE("SPDIFEncoder: Burst buffer, contents too large!");
163 clearBurstBuffer();
164 } else {
165 // We don't have to write zeros because buffer already set to zero
166 // by clearBurstBuffer(). Just pretend we wrote zeros by
167 // incrementing cursor.
168 mByteCursor = burstSize;
169 }
170}
171
172void SPDIFEncoder::reset()
173{
174 ALOGV("SPDIFEncoder: reset()");
175 clearBurstBuffer();
176 if (mFramer != NULL) {
177 mFramer->resetBurst();
178 }
179 mPayloadBytesPending = 0;
180 mScanning = true;
181}
182
183void SPDIFEncoder::flushBurstBuffer()
184{
185 const int preambleSize = 4 * sizeof(uint16_t);
186 if (mByteCursor > preambleSize) {
187 // Set lengthCode for valid payload before zeroPad.
188 uint16_t numBytes = (mByteCursor - preambleSize);
189 mBurstBuffer[3] = mFramer->convertBytesToLengthCode(numBytes);
190
191 sendZeroPad();
192 writeOutput(mBurstBuffer, mByteCursor);
193 }
194 reset();
195}
196
197void SPDIFEncoder::clearBurstBuffer()
198{
199 if (mBurstBuffer) {
200 memset(mBurstBuffer, 0, mBurstBufferSizeBytes);
201 }
202 mByteCursor = 0;
203}
204
205void SPDIFEncoder::startDataBurst()
206{
207 // Encode IEC61937-1 Burst Preamble
208 uint16_t preamble[4];
209
210 uint16_t burstInfo = (mBitstreamNumber << 13)
211 | (mFramer->getDataTypeInfo() << 8)
212 | mFramer->getDataType();
213
214 mRateMultiplier = mFramer->getRateMultiplier();
215
216 preamble[0] = kSPDIFSync1;
217 preamble[1] = kSPDIFSync2;
218 preamble[2] = burstInfo;
219 preamble[3] = 0; // lengthCode - This will get set after the buffer is full.
220 writeBurstBufferShorts(preamble, 4);
221}
222
223size_t SPDIFEncoder::startSyncFrame()
224{
225 // Write start of encoded frame that was buffered in frame detector.
226 size_t syncSize = mFramer->getHeaderSizeBytes();
227 writeBurstBufferBytes(mFramer->getHeaderAddress(), syncSize);
228 return mFramer->getFrameSizeBytes() - syncSize;
229}
230
231// Wraps raw encoded data into a data burst.
232ssize_t SPDIFEncoder::write( const void *buffer, size_t numBytes )
233{
234 size_t bytesLeft = numBytes;
235 const uint8_t *data = (const uint8_t *)buffer;
236 ALOGV("SPDIFEncoder: mScanning = %d, write(buffer[0] = 0x%02X, numBytes = %zu)",
237 mScanning, (uint) *data, numBytes);
238 while (bytesLeft > 0) {
239 if (mScanning) {
240 // Look for beginning of next encoded frame.
241 if (mFramer->scan(*data)) {
242 if (mByteCursor == 0) {
243 startDataBurst();
244 } else if (mFramer->isFirstInBurst()) {
245 // Make sure that this frame is at the beginning of the data burst.
246 flushBurstBuffer();
247 startDataBurst();
248 }
249 mPayloadBytesPending = startSyncFrame();
250 mScanning = false;
251 }
252 data++;
253 bytesLeft--;
254 } else {
255 // Write payload until we hit end of frame.
256 size_t bytesToWrite = bytesLeft;
257 // Only write as many as we need to finish the frame.
258 if (bytesToWrite > mPayloadBytesPending) {
259 bytesToWrite = mPayloadBytesPending;
260 }
261 writeBurstBufferBytes(data, bytesToWrite);
262
263 data += bytesToWrite;
264 bytesLeft -= bytesToWrite;
265 mPayloadBytesPending -= bytesToWrite;
266
267 // If we have all the payload then send a data burst.
268 if (mPayloadBytesPending == 0) {
269 if (mFramer->isLastInBurst()) {
270 flushBurstBuffer();
271 }
272 mScanning = true;
273 }
274 }
275 }
276 return numBytes;
277}
278
279} // namespace android