void Inflator::ProcessInput(bool flush) { while (true) { switch (m_state) { case PRE_STREAM: if (!flush && m_inQueue.CurrentSize() < MaxPrestreamHeaderSize()) return; ProcessPrestreamHeader(); m_state = WAIT_HEADER; m_wrappedAround = false; m_current = 0; m_lastFlush = 0; m_window.New(1 << GetLog2WindowSize()); break; case WAIT_HEADER: { // maximum number of bytes before actual compressed data starts const size_t MAX_HEADER_SIZE = BitsToBytes(3+5+5+4+19*7+286*15+19*15); if (m_inQueue.CurrentSize() < (flush ? 1 : MAX_HEADER_SIZE)) return; DecodeHeader(); break; } case DECODING_BODY: if (!DecodeBody()) return; break; case POST_STREAM: if (!flush && m_inQueue.CurrentSize() < MaxPoststreamTailSize()) return; ProcessPoststreamTail(); m_state = m_repeat ? PRE_STREAM : AFTER_END; Output(0, NULL, 0, GetAutoSignalPropagation(), true); // TODO: non-blocking if (m_inQueue.IsEmpty()) return; break; case AFTER_END: m_inQueue.TransferTo(*AttachedTransformation()); return; } } }
PRIVATE OI_STATUS internal_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_UINT8 bitpool, const OI_BYTE **frameData, OI_UINT32 *frameBytes, OI_INT16 *pcmData, OI_UINT32 *pcmBytes) { OI_STATUS status; OI_UINT bodyLen; TRACE(("+OI_CODEC_SBC_DecodeRaw")); if (context->bufferedBlocks == 0) { /* * The bitallocator needs to know the bitpool value. */ context->common.frameInfo.bitpool = bitpool; /* * Compute the frame length and check we have enough frame data to proceed */ bodyLen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo) - SBC_HEADER_LEN; if (*frameBytes < bodyLen) { TRACE(("-OI_CODEC_SBC_Decode: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA")); return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA; } } else { bodyLen = 0; } /* * Decode the SBC data. Pass TRUE to DecodeBody to allow partial decoding of * tones. */ status = DecodeBody(context, *frameData, pcmData, pcmBytes, TRUE); if (OI_SUCCESS(status) || status == OI_CODEC_SBC_PARTIAL_DECODE) { *frameData += bodyLen; *frameBytes -= bodyLen; } TRACE(("-OI_CODEC_SBC_DecodeRaw: %d", status)); return status; }
OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, const OI_BYTE **frameData, OI_UINT32 *frameBytes, OI_INT16 *pcmData, OI_UINT32 *pcmBytes) { OI_STATUS status; OI_UINT framelen; OI_UINT8 crc; TRACE(("+OI_CODEC_SBC_DecodeFrame")); TRACE(("Finding syncword")); status = FindSyncword(context, frameData, frameBytes); if (!OI_SUCCESS(status)) { return status; } /* Make sure enough data remains to read the header. */ if (*frameBytes < SBC_HEADER_LEN) { TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA")); return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA; } TRACE(("Reading Header")); OI_SBC_ReadHeader(&context->common, *frameData); /* * Some implementations load the decoder into RAM and use overlays for 4 vs 8 subbands. We need * to ensure that the SBC parameters for this frame are compatible with the restrictions imposed * by the loaded overlays. */ if (context->limitFrameFormat && (context->common.frameInfo.subbands != context->restrictSubbands)) { ERROR(("SBC parameters incompatible with loaded overlay")); return OI_STATUS_INVALID_PARAMETERS; } if (context->common.frameInfo.nrof_channels > context->common.maxChannels) { ERROR(("SBC parameters incompatible with number of channels specified during reset")); return OI_STATUS_INVALID_PARAMETERS; } if (context->common.pcmStride < 1 || context->common.pcmStride > 2) { ERROR(("PCM stride not set correctly during reset")); return OI_STATUS_INVALID_PARAMETERS; } /* * At this point a header has been read. However, it's possible that we found a false syncword, * so the header data might be invalid. Make sure we have enough bytes to read in the * CRC-protected header, but don't require we have the whole frame. That way, if it turns out * that we're acting on bogus header data, we don't stall the decoding process by waiting for * data that we don't actually need. */ framelen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo); if (*frameBytes < framelen) { TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA")); return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA; } TRACE(("Calculating checksum")); crc = OI_SBC_CalculateChecksum(&context->common.frameInfo, *frameData); if (crc != context->common.frameInfo.crc) { TRACE(("CRC Mismatch: calc=%02x read=%02x\n", crc, context->common.frameInfo.crc)); TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_CHECKSUM_MISMATCH")); return OI_CODEC_SBC_CHECKSUM_MISMATCH; } #ifdef OI_DEBUG /* * Make sure the bitpool values are sane. */ if ((context->common.frameInfo.bitpool < SBC_MIN_BITPOOL) && !context->common.frameInfo.enhanced) { ERROR(("Bitpool too small: %d (must be >= 2)", context->common.frameInfo.bitpool)); return OI_STATUS_INVALID_PARAMETERS; } if (context->common.frameInfo.bitpool > OI_SBC_MaxBitpool(&context->common.frameInfo)) { ERROR(("Bitpool too large: %d (must be <= %ld)", context->common.frameInfo.bitpool, OI_SBC_MaxBitpool(&context->common.frameInfo))); return OI_STATUS_INVALID_PARAMETERS; } #endif /* * Now decode the SBC data. Partial decode is not yet implemented for an SBC * stream, so pass FALSE to decode body to have it enforce the old rule that * you have to decode a whole packet at a time. */ status = DecodeBody(context, *frameData + SBC_HEADER_LEN, pcmData, pcmBytes, FALSE); if (OI_SUCCESS(status)) { *frameData += framelen; *frameBytes -= framelen; } TRACE(("-OI_CODEC_SBC_DecodeFrame: %d", status)); return status; }