• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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