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