1 /******************************************************************************
2 *
3 * Copyright (C) 2014 The Android Open Source Project
4 * Copyright 2006 Open Interface North America, Inc. All rights reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 ******************************************************************************/
19
20 /**********************************************************************************
21 $Revision: #1 $
22 ***********************************************************************************/
23
24 /** @file
25 @ingroup codec_internal
26 */
27
28 /**@addtogroup codec_internal */
29 /**@{*/
30
31 #include "oi_codec_sbc_private.h"
32 #include "oi_bitstream.h"
33
34 #define SPECIALIZE_READ_SAMPLES_JOINT
35
36 /**
37 * Scans through a buffer looking for a codec syncword. If the decoder has been
38 * set for enhanced operation using OI_CODEC_SBC_DecoderReset(), it will search
39 * for both a standard and an enhanced syncword.
40 */
FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT * context,const OI_BYTE ** frameData,OI_UINT32 * frameBytes)41 PRIVATE OI_STATUS FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT *context,
42 const OI_BYTE **frameData,
43 OI_UINT32 *frameBytes)
44 {
45 #ifdef SBC_ENHANCED
46 OI_BYTE search1 = OI_SBC_SYNCWORD;
47 OI_BYTE search2 = OI_SBC_ENHANCED_SYNCWORD;
48 #endif // SBC_ENHANCED
49
50 if (*frameBytes == 0) {
51 return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA;
52 }
53
54 #ifdef SBC_ENHANCED
55 if (context->limitFrameFormat && context->enhancedEnabled){
56 /* If the context is restricted, only search for specified SYNCWORD */
57 search1 = search2;
58 } else if (context->enhancedEnabled == FALSE) {
59 /* If enhanced is not enabled, only search for classic SBC SYNCWORD*/
60 search2 = search1;
61 }
62 while (*frameBytes && (**frameData != search1) && (**frameData != search2)) {
63 (*frameBytes)--;
64 (*frameData)++;
65 }
66 if (*frameBytes) {
67 /* Syncword found, *frameData points to it, and *frameBytes correctly
68 * reflects the number of bytes available to read, including the
69 * syncword. */
70 context->common.frameInfo.enhanced = (**frameData == OI_SBC_ENHANCED_SYNCWORD);
71 return OI_OK;
72 } else {
73 /* No syncword was found anywhere in the provided input data.
74 * *frameData points past the end of the original input, and
75 * *frameBytes is 0. */
76 return OI_CODEC_SBC_NO_SYNCWORD;
77 }
78 #else // SBC_ENHANCED
79 while (*frameBytes && (**frameData != OI_SBC_SYNCWORD)) {
80 (*frameBytes)--;
81 (*frameData)++;
82 }
83 if (*frameBytes) {
84 /* Syncword found, *frameData points to it, and *frameBytes correctly
85 * reflects the number of bytes available to read, including the
86 * syncword. */
87 context->common.frameInfo.enhanced = FALSE;
88 return OI_OK;
89 } else {
90 /* No syncword was found anywhere in the provided input data.
91 * *frameData points past the end of the original input, and
92 * *frameBytes is 0. */
93 return OI_CODEC_SBC_NO_SYNCWORD;
94 }
95 #endif // SBC_ENHANCED
96 }
97
DecodeBody(OI_CODEC_SBC_DECODER_CONTEXT * context,const OI_BYTE * bodyData,OI_INT16 * pcmData,OI_UINT32 * pcmBytes,OI_BOOL allowPartial)98 static OI_STATUS DecodeBody(OI_CODEC_SBC_DECODER_CONTEXT *context,
99 const OI_BYTE *bodyData,
100 OI_INT16 *pcmData,
101 OI_UINT32 *pcmBytes,
102 OI_BOOL allowPartial)
103 {
104 OI_BITSTREAM bs;
105 OI_UINT frameSamples = context->common.frameInfo.nrof_blocks * context->common.frameInfo.nrof_subbands;
106 OI_UINT decode_block_count;
107
108 /*
109 * Based on the header data, make sure that there is enough room to write the output samples.
110 */
111 if (*pcmBytes < (sizeof(OI_INT16) * frameSamples * context->common.pcmStride) && !allowPartial) {
112 /* If we're not allowing partial decodes, we need room for the entire
113 * codec frame */
114 TRACE(("-OI_CODEC_SBC_Decode: OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA"));
115 return OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA;
116 } else if (*pcmBytes < sizeof (OI_INT16) * context->common.frameInfo.nrof_subbands * context->common.pcmStride) {
117 /* Even if we're allowing partials, we can still only decode on a frame
118 * boundary */
119 return OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA;
120 }
121
122 if (context->bufferedBlocks == 0) {
123 TRACE(("Reading scalefactors"));
124 OI_SBC_ReadScalefactors(&context->common, bodyData, &bs);
125
126 TRACE(("Computing bit allocation"));
127 OI_SBC_ComputeBitAllocation(&context->common);
128
129 TRACE(("Reading samples"));
130 if (context->common.frameInfo.mode == SBC_JOINT_STEREO) {
131 OI_SBC_ReadSamplesJoint(context, &bs);
132 } else {
133 OI_SBC_ReadSamples(context, &bs);
134 }
135
136 context->bufferedBlocks = context->common.frameInfo.nrof_blocks;
137 }
138
139 if (allowPartial) {
140 decode_block_count = *pcmBytes / sizeof(OI_INT16) / context->common.pcmStride / context->common.frameInfo.nrof_subbands;
141
142 if (decode_block_count > context->bufferedBlocks) {
143 decode_block_count = context->bufferedBlocks;
144 }
145
146 } else {
147 decode_block_count = context->common.frameInfo.nrof_blocks;
148 }
149
150 TRACE(("Synthesizing frame"));
151 {
152 OI_UINT start_block = context->common.frameInfo.nrof_blocks - context->bufferedBlocks;
153 OI_SBC_SynthFrame(context, pcmData, start_block, decode_block_count);
154 }
155
156 OI_ASSERT(context->bufferedBlocks >= decode_block_count);
157 context->bufferedBlocks -= decode_block_count;
158
159 frameSamples = decode_block_count * context->common.frameInfo.nrof_subbands;
160
161 /*
162 * When decoding mono into a stride-2 array, copy pcm data to second channel
163 */
164 if (context->common.frameInfo.nrof_channels == 1 && context->common.pcmStride == 2) {
165 OI_UINT i;
166 for (i = 0; i < frameSamples; ++i) {
167 pcmData[2*i+1] = pcmData[2*i];
168 }
169 }
170
171 /*
172 * Return number of pcm bytes generated by the decode operation.
173 */
174 *pcmBytes = frameSamples * sizeof(OI_INT16) * context->common.pcmStride;
175 if (context->bufferedBlocks > 0) {
176 return OI_CODEC_SBC_PARTIAL_DECODE;
177 } else {
178 return OI_OK;
179 }
180 }
181
internal_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT * context,OI_UINT8 bitpool,const OI_BYTE ** frameData,OI_UINT32 * frameBytes,OI_INT16 * pcmData,OI_UINT32 * pcmBytes)182 PRIVATE OI_STATUS internal_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
183 OI_UINT8 bitpool,
184 const OI_BYTE **frameData,
185 OI_UINT32 *frameBytes,
186 OI_INT16 *pcmData,
187 OI_UINT32 *pcmBytes)
188 {
189 OI_STATUS status;
190 OI_UINT bodyLen;
191
192 TRACE(("+OI_CODEC_SBC_DecodeRaw"));
193
194 if (context->bufferedBlocks == 0) {
195 /*
196 * The bitallocator needs to know the bitpool value.
197 */
198 context->common.frameInfo.bitpool = bitpool;
199 /*
200 * Compute the frame length and check we have enough frame data to proceed
201 */
202 bodyLen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo) - SBC_HEADER_LEN;
203 if (*frameBytes < bodyLen) {
204 TRACE(("-OI_CODEC_SBC_Decode: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA"));
205 return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA;
206 }
207 } else {
208 bodyLen = 0;
209 }
210 /*
211 * Decode the SBC data. Pass TRUE to DecodeBody to allow partial decoding of
212 * tones.
213 */
214 status = DecodeBody(context, *frameData, pcmData, pcmBytes, TRUE);
215 if (OI_SUCCESS(status) || status == OI_CODEC_SBC_PARTIAL_DECODE) {
216 *frameData += bodyLen;
217 *frameBytes -= bodyLen;
218 }
219 TRACE(("-OI_CODEC_SBC_DecodeRaw: %d", status));
220 return status;
221 }
222
OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT * context,OI_UINT32 * decoderData,OI_UINT32 decoderDataBytes,OI_UINT8 maxChannels,OI_UINT8 pcmStride,OI_BOOL enhanced)223 OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
224 OI_UINT32 *decoderData,
225 OI_UINT32 decoderDataBytes,
226 OI_UINT8 maxChannels,
227 OI_UINT8 pcmStride,
228 OI_BOOL enhanced)
229 {
230 return internal_DecoderReset(context, decoderData, decoderDataBytes, maxChannels, pcmStride, enhanced);
231 }
232
OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT * context,const OI_BYTE ** frameData,OI_UINT32 * frameBytes,OI_INT16 * pcmData,OI_UINT32 * pcmBytes)233 OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context,
234 const OI_BYTE **frameData,
235 OI_UINT32 *frameBytes,
236 OI_INT16 *pcmData,
237 OI_UINT32 *pcmBytes)
238 {
239 OI_STATUS status;
240 OI_UINT framelen;
241 OI_UINT8 crc;
242
243 TRACE(("+OI_CODEC_SBC_DecodeFrame"));
244
245 TRACE(("Finding syncword"));
246 status = FindSyncword(context, frameData, frameBytes);
247 if (!OI_SUCCESS(status)) {
248 return status;
249 }
250
251 /* Make sure enough data remains to read the header. */
252 if (*frameBytes < SBC_HEADER_LEN) {
253 TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA"));
254 return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA;
255 }
256
257 TRACE(("Reading Header"));
258 OI_SBC_ReadHeader(&context->common, *frameData);
259
260 /*
261 * Some implementations load the decoder into RAM and use overlays for 4 vs 8 subbands. We need
262 * to ensure that the SBC parameters for this frame are compatible with the restrictions imposed
263 * by the loaded overlays.
264 */
265 if (context->limitFrameFormat && (context->common.frameInfo.subbands != context->restrictSubbands)) {
266 ERROR(("SBC parameters incompatible with loaded overlay"));
267 return OI_STATUS_INVALID_PARAMETERS;
268 }
269
270 if (context->common.frameInfo.nrof_channels > context->common.maxChannels) {
271 ERROR(("SBC parameters incompatible with number of channels specified during reset"));
272 return OI_STATUS_INVALID_PARAMETERS;
273 }
274
275 if (context->common.pcmStride < 1 || context->common.pcmStride > 2) {
276 ERROR(("PCM stride not set correctly during reset"));
277 return OI_STATUS_INVALID_PARAMETERS;
278 }
279
280 /*
281 * At this point a header has been read. However, it's possible that we found a false syncword,
282 * so the header data might be invalid. Make sure we have enough bytes to read in the
283 * CRC-protected header, but don't require we have the whole frame. That way, if it turns out
284 * that we're acting on bogus header data, we don't stall the decoding process by waiting for
285 * data that we don't actually need.
286 */
287 framelen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo);
288 if (*frameBytes < framelen) {
289 TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA"));
290 return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA;
291 }
292
293 TRACE(("Calculating checksum"));
294
295 crc = OI_SBC_CalculateChecksum(&context->common.frameInfo, *frameData);
296 if (crc != context->common.frameInfo.crc) {
297 TRACE(("CRC Mismatch: calc=%02x read=%02x\n", crc, context->common.frameInfo.crc));
298 TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_CHECKSUM_MISMATCH"));
299 return OI_CODEC_SBC_CHECKSUM_MISMATCH;
300 }
301
302 #ifdef OI_DEBUG
303 /*
304 * Make sure the bitpool values are sane.
305 */
306 if ((context->common.frameInfo.bitpool < SBC_MIN_BITPOOL) && !context->common.frameInfo.enhanced) {
307 ERROR(("Bitpool too small: %d (must be >= 2)", context->common.frameInfo.bitpool));
308 return OI_STATUS_INVALID_PARAMETERS;
309 }
310 if (context->common.frameInfo.bitpool > OI_SBC_MaxBitpool(&context->common.frameInfo)) {
311 ERROR(("Bitpool too large: %d (must be <= %ld)", context->common.frameInfo.bitpool, OI_SBC_MaxBitpool(&context->common.frameInfo)));
312 return OI_STATUS_INVALID_PARAMETERS;
313 }
314 #endif
315
316 /*
317 * Now decode the SBC data. Partial decode is not yet implemented for an SBC
318 * stream, so pass FALSE to decode body to have it enforce the old rule that
319 * you have to decode a whole packet at a time.
320 */
321 status = DecodeBody(context, *frameData + SBC_HEADER_LEN, pcmData, pcmBytes, FALSE);
322 if (OI_SUCCESS(status)) {
323 *frameData += framelen;
324 *frameBytes -= framelen;
325 }
326 TRACE(("-OI_CODEC_SBC_DecodeFrame: %d", status));
327
328 return status;
329 }
330
OI_CODEC_SBC_SkipFrame(OI_CODEC_SBC_DECODER_CONTEXT * context,const OI_BYTE ** frameData,OI_UINT32 * frameBytes)331 OI_STATUS OI_CODEC_SBC_SkipFrame(OI_CODEC_SBC_DECODER_CONTEXT *context,
332 const OI_BYTE **frameData,
333 OI_UINT32 *frameBytes)
334 {
335 OI_STATUS status;
336 OI_UINT framelen;
337 OI_UINT headerlen;
338 OI_UINT8 crc;
339
340 status = FindSyncword(context, frameData, frameBytes);
341 if (!OI_SUCCESS(status)) {
342 return status;
343 }
344 if (*frameBytes < SBC_HEADER_LEN) {
345 return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA;
346 }
347 OI_SBC_ReadHeader(&context->common, *frameData);
348 framelen = OI_SBC_CalculateFrameAndHeaderlen(&context->common.frameInfo, &headerlen);
349 if (*frameBytes < headerlen) {
350 return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA;
351 }
352 crc = OI_SBC_CalculateChecksum(&context->common.frameInfo, *frameData);
353 if (crc != context->common.frameInfo.crc) {
354 return OI_CODEC_SBC_CHECKSUM_MISMATCH;
355 }
356 if (*frameBytes < framelen) {
357 return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA;
358 }
359 context->bufferedBlocks = 0;
360 *frameData += framelen;
361 *frameBytes -= framelen;
362 return OI_OK;
363 }
364
OI_CODEC_SBC_FrameCount(OI_BYTE * frameData,OI_UINT32 frameBytes)365 OI_UINT8 OI_CODEC_SBC_FrameCount(OI_BYTE *frameData,
366 OI_UINT32 frameBytes)
367 {
368 OI_UINT8 mode;
369 OI_UINT8 blocks;
370 OI_UINT8 subbands;
371 OI_UINT8 frameCount = 0;
372 OI_UINT frameLen;
373
374 while (frameBytes){
375 while (frameBytes && ((frameData[0] & 0xFE) != 0x9C)){
376 frameData++;
377 frameBytes--;
378 }
379
380 if (frameBytes < SBC_HEADER_LEN) {
381 return frameCount;
382 }
383
384 /* Extract and translate required fields from Header */
385 subbands = mode = blocks = frameData[1];;
386 mode = (mode & (BIT3 | BIT2)) >> 2;
387 blocks = block_values[(blocks & (BIT5 | BIT4)) >> 4];
388 subbands = band_values[(subbands & BIT0)];
389
390 /* Inline logic to avoid corrupting context */
391 frameLen = blocks * frameData[2];
392 switch (mode){
393 case SBC_JOINT_STEREO:
394 frameLen += subbands + (8 * subbands);
395 break;
396
397 case SBC_DUAL_CHANNEL:
398 frameLen *= 2;
399 /* fall through */
400
401 default:
402 if (mode == SBC_MONO){
403 frameLen += 4*subbands;
404 } else {
405 frameLen += 8*subbands;
406 }
407 }
408
409 frameCount++;
410 frameLen = SBC_HEADER_LEN + (frameLen + 7) / 8;
411 if (frameBytes > frameLen){
412 frameBytes -= frameLen;
413 frameData += frameLen;
414 } else {
415 frameBytes = 0;
416 }
417 }
418 return frameCount;
419 }
420
421 /** Read quantized subband samples from the input bitstream and expand them. */
422
423 #ifdef SPECIALIZE_READ_SAMPLES_JOINT
424
OI_SBC_ReadSamplesJoint4(OI_CODEC_SBC_DECODER_CONTEXT * context,OI_BITSTREAM * global_bs)425 PRIVATE void OI_SBC_ReadSamplesJoint4(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs)
426 {
427 #define NROF_SUBBANDS 4
428 #include "readsamplesjoint.inc"
429 #undef NROF_SUBBANDS
430 }
431
OI_SBC_ReadSamplesJoint8(OI_CODEC_SBC_DECODER_CONTEXT * context,OI_BITSTREAM * global_bs)432 PRIVATE void OI_SBC_ReadSamplesJoint8(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs)
433 {
434 #define NROF_SUBBANDS 8
435 #include "readsamplesjoint.inc"
436 #undef NROF_SUBBANDS
437 }
438
439 typedef void (*READ_SAMPLES)(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs);
440
441 static const READ_SAMPLES SpecializedReadSamples[] = {
442 OI_SBC_ReadSamplesJoint4,
443 OI_SBC_ReadSamplesJoint8
444 };
445
446 #endif /* SPECIALIZE_READ_SAMPLES_JOINT */
447
448
OI_SBC_ReadSamplesJoint(OI_CODEC_SBC_DECODER_CONTEXT * context,OI_BITSTREAM * global_bs)449 PRIVATE void OI_SBC_ReadSamplesJoint(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs)
450 {
451 OI_CODEC_SBC_COMMON_CONTEXT *common = &context->common;
452 OI_UINT nrof_subbands = common->frameInfo.nrof_subbands;
453 #ifdef SPECIALIZE_READ_SAMPLES_JOINT
454 OI_ASSERT((nrof_subbands >> 3u) <= 1u);
455 SpecializedReadSamples[nrof_subbands >> 3](context, global_bs);
456 #else
457
458 #define NROF_SUBBANDS nrof_subbands
459 #include "readsamplesjoint.inc"
460 #undef NROF_SUBBANDS
461 #endif /* SPECIALIZE_READ_SAMPLES_JOINT */
462 }
463
464 /**@}*/
465
466