Example #1
0
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;
        }
    }
}
Example #2
0
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;
}
Example #3
0
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;
}