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