blob: 0773e5fb7dfec94534ca1d65fee7bb5e21389748 [file] [log] [blame]
/*------------------------------------------------------------------------------
-- --
-- This software is confidential and proprietary and may be used --
-- only as expressly authorized by a licensing agreement from --
-- --
-- Hantro Products Oy. --
-- --
-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY --
-- ALL RIGHTS RESERVED --
-- --
-- The entire notice above must be reproduced --
-- on all copies and should not be removed. --
-- --
--------------------------------------------------------------------------------
*/
#include "vp8putbits.h"
#include <stdio.h>
#include "enccommon.h"
/*------------------------------------------------------------------------------
SetBuffer
Input buffer Pointer to the buffer structure.
data Pointer to data buffer.
size Size of data buffer.
Return ENCHW_OK Buffer status is OK.
ENCHW_NOK Buffer overflow.
------------------------------------------------------------------------------*/
int32_t VP8SetBuffer(vp8buffer* buffer, uint8_t* data, int32_t size) {
if ((buffer == NULL) || (data == NULL) || (size < 1)) return ENCHW_NOK;
buffer->data = data;
buffer->pData = data; /* First position of buffer */
buffer->size = size; /* Buffer size in bytes */
buffer->range = 255;
buffer->bottom = 0; /* PutBool bottom */
buffer->bitsLeft = 24;
buffer->byteCnt = 0;
return ENCHW_OK;
}
/*------------------------------------------------------------------------------
PutByte write byte literallyt to next place of buffer and advance data
pointer to next place
Input buffer Pointer to the buffer stucture
value Byte
------------------------------------------------------------------------------*/
void VP8PutByte(vp8buffer* buffer, int32_t byte) {
ASSERT((uint32_t)byte < 256);
ASSERT(buffer->data < buffer->pData + buffer->size);
*buffer->data++ = byte;
buffer->byteCnt++;
}
/*------------------------------------------------------------------------------
PutLit write "literal" bits to stream using PutBool() where probability
is 128. Note that real bits written to stream are not necessarily same
than literal value. Bit write order: MSB...LSB.
------------------------------------------------------------------------------*/
void VP8PutLit(vp8buffer* buffer, int32_t value, int32_t number) {
ASSERT(number < 32 && number > 0);
ASSERT(((value & (-1 << number)) == 0));
while (number--) {
VP8PutBool(buffer, 128, (value >> number) & 0x1);
}
}
/*------------------------------------------------------------------------------
PutBool
------------------------------------------------------------------------------*/
void VP8PutBool(vp8buffer* buffer, int32_t prob, int32_t boolValue) {
int32_t split = 1 + ((buffer->range - 1) * prob >> 8);
int32_t lengthBits = 0;
int32_t bits = 0;
if (boolValue) {
buffer->bottom += split;
buffer->range -= split;
} else {
buffer->range = split;
}
while (buffer->range < 128) {
/* Detect carry and add carry bit to already written
* buffer->data if needed */
if (buffer->bottom < 0) {
uint8_t* data = buffer->data;
while (*--data == 255) {
*data = 0;
}
(*data)++;
}
buffer->range <<= 1;
buffer->bottom <<= 1;
if (!--buffer->bitsLeft) {
lengthBits += 8;
bits <<= 8;
bits |= (buffer->bottom >> 24) & 0xff;
TRACE_BIT_STREAM(bits & 0xff, 8);
*buffer->data++ = (buffer->bottom >> 24) & 0xff;
buffer->byteCnt++;
buffer->bottom &= 0xffffff; /* Keep 3 bytes */
buffer->bitsLeft = 8;
/* TODO use big enough buffer and check buffer status
* for example in the beginning of mb row */
ASSERT(buffer->data < buffer->pData + buffer->size - 1);
}
}
}
/*------------------------------------------------------------------------------
PutTree
------------------------------------------------------------------------------*/
void VP8PutTree(vp8buffer* buffer, tree const* tree, int32_t* prob) {
int32_t value = tree->value;
int32_t number = tree->number;
int32_t const* index = tree->index;
while (number--) {
VP8PutBool(buffer, prob[*index++], (value >> number) & 1);
}
}
/*------------------------------------------------------------------------------
FlushBuffer put remaining buffer->bottom bits to the stream
------------------------------------------------------------------------------*/
void VP8FlushBuffer(vp8buffer* buffer) {
int32_t bitsLeft = buffer->bitsLeft;
int32_t bottom = buffer->bottom;
/* Detect (unlikely) carry and add carry bit to already written
* buffer->data if needed */
if (bottom & (1 << (32 - bitsLeft))) {
uint8_t* data = buffer->data;
while (*--data == 255) {
*data = 0;
}
(*data)++;
}
/* Move remaining bits to left until byte boundary */
bottom <<= (bitsLeft & 0x7);
/* Move remaining bytes to left until word boundary */
bottom <<= (bitsLeft >> 3) * 8;
/* Write valid (and possibly padded) bits to stream */
*buffer->data++ = 0xff & (bottom >> 24);
*buffer->data++ = 0xff & (bottom >> 16);
*buffer->data++ = 0xff & (bottom >> 8);
*buffer->data++ = 0xff & bottom;
buffer->byteCnt += 4;
TRACE_BIT_STREAM(bottom, 32);
COMMENT("flush");
}