SmartAudio/package/allwinner/liballwinner_tina/liballwinner/LIBRARY/DEMUX/BASE/CdxBitReader.c

155 lines
3.4 KiB
C
Executable File

/*
* Copyright (c) 2008-2016 Allwinner Technology Co. Ltd.
* All rights reserved.
*
* File : CdxBitReader.c
* Description : BitReader
* History :
*
*/
#include <CdxBitReader.h>
#include <CdxMemory.h>
#include <CdxLog.h>
struct CdxBitReaderImplS
{
struct CdxBitReaderS base;
const cdx_uint8 *mData;
cdx_uint32 mSize;
cdx_uint32 mReservoir; // left-aligned bits
cdx_uint32 mNumBitsLeft;
};
cdx_void CdxBitReaderDestroy(struct CdxBitReaderS *br)
{
CDX_CHECK(br);
struct CdxBitReaderImplS *impl = NULL;
impl = CdxContainerOf(br, struct CdxBitReaderImplS, base);
free(impl);
return ;
}
static cdx_void onFillReservoir(struct CdxBitReaderImplS *impl)
{
cdx_uint32 i;
CDX_CHECK(impl->mSize > 0u);
impl->mReservoir = 0;
for (i = 0; impl->mSize > 0 && i < 4; ++i) {
impl->mReservoir = (impl->mReservoir << 8) | *(impl->mData);
++(impl->mData);
--(impl->mSize);
}
impl->mNumBitsLeft = 8 * i;
impl->mReservoir <<= 32 - impl->mNumBitsLeft;
return ;
}
cdx_uint32 CdxBitReaderGetBits(struct CdxBitReaderS *br, cdx_uint32 n)
{
CDX_CHECK(br);
struct CdxBitReaderImplS *impl = NULL;
impl = CdxContainerOf(br, struct CdxBitReaderImplS, base);
cdx_uint32 result = 0;
CDX_CHECK(n <= 32u);
while (n > 0) {
cdx_uint32 m;
if (impl->mNumBitsLeft == 0) {
onFillReservoir(impl);
}
m = n;
if (m > impl->mNumBitsLeft) {
m = impl->mNumBitsLeft;
}
result = (result << m) | (impl->mReservoir >> (32 - m));
impl->mReservoir <<= m;
impl->mNumBitsLeft -= m;
n -= m;
}
return result;
}
cdx_void CdxBitReaderSkipBits(struct CdxBitReaderS *br, cdx_uint32 n)
{
CDX_CHECK(br);
while (n > 32)
{
CdxBitReaderGetBits(br, 32);
n -= 32;
}
if (n > 0)
{
CdxBitReaderGetBits(br, n);
}
}
void CdxBitReaderPutBits(struct CdxBitReaderS *br, cdx_uint32 x, cdx_uint32 n)
{
CDX_CHECK(br);
struct CdxBitReaderImplS *impl = NULL;
impl = CdxContainerOf(br, struct CdxBitReaderImplS, base);
CDX_CHECK(n < 32u);
while (impl->mNumBitsLeft + n > 32) {
impl->mNumBitsLeft -= 8;
--impl->mData;
++impl->mSize;
}
impl->mReservoir = (impl->mReservoir >> n) | (x << (32 - n));
impl->mNumBitsLeft += n;
}
cdx_uint32 CdxBitReaderNumBitsLeft(struct CdxBitReaderS *br)
{
CDX_CHECK(br);
struct CdxBitReaderImplS *impl = NULL;
impl = CdxContainerOf(br, struct CdxBitReaderImplS, base);
return impl->mSize * 8 + impl->mNumBitsLeft;
}
const cdx_uint8 *CdxBitReaderData(struct CdxBitReaderS *br)
{
CDX_CHECK(br);
struct CdxBitReaderImplS *impl = NULL;
impl = CdxContainerOf(br, struct CdxBitReaderImplS, base);
return impl->mData - (impl->mNumBitsLeft + 7) / 8;
}
static struct CdxBitReaderOpsS gBitReaderOps =
{
.destroy = CdxBitReaderDestroy,
.getBits = CdxBitReaderGetBits,
.skipBits = CdxBitReaderSkipBits,
.putBits = CdxBitReaderPutBits,
.numBitsLeft = CdxBitReaderNumBitsLeft,
.data = CdxBitReaderData
};
CdxBitReaderT *CdxBitReaderCreate(const cdx_uint8 *data, cdx_uint32 size)
{
struct CdxBitReaderImplS *impl;
impl = malloc(sizeof(*impl));
CDX_FORCE_CHECK(impl);
impl->mData = data;
impl->mSize = size;
impl->mReservoir = 0;
impl->mNumBitsLeft = 0;
impl->base.ops = &gBitReaderOps;
return &impl->base;
}