blob: 442054ed3359baa41a36526187d4a31ba6e42e1a [file] [log] [blame]
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license and patent
* grant that can be found in the LICENSE file in the root of the source
* tree. All contributing project authors may be found in the AUTHORS
* file in the root of the source tree.
*/
#include "dboolhuff.h"
#include "vpx_ports/mem.h"
#include "vpx_mem/vpx_mem.h"
DECLARE_ALIGNED(16, const unsigned int, vp8dx_bitreader_norm[256]) =
{
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static void copy_in(BOOL_DECODER *br, unsigned int to_write)
{
if (to_write > br->user_buffer_sz)
to_write = br->user_buffer_sz;
memcpy(br->write_ptr, br->user_buffer, to_write);
br->user_buffer += to_write;
br->user_buffer_sz -= to_write;
br->write_ptr = br_ptr_advance(br->write_ptr, to_write);
}
int vp8dx_start_decode_c(BOOL_DECODER *br, const unsigned char *source,
unsigned int source_sz)
{
br->lowvalue = 0;
br->range = 255;
br->count = 0;
br->user_buffer = source;
br->user_buffer_sz = source_sz;
if (source_sz && !source)
return 1;
/* Allocate the ring buffer backing store with alignment equal to the
* buffer size*2 so that a single pointer can be used for wrapping rather
* than a pointer+offset.
*/
br->decode_buffer = vpx_memalign(VP8_BOOL_DECODER_SZ * 2,
VP8_BOOL_DECODER_SZ);
if (!br->decode_buffer)
return 1;
/* Populate the buffer */
br->read_ptr = br->decode_buffer;
br->write_ptr = br->decode_buffer;
copy_in(br, VP8_BOOL_DECODER_SZ);
/* Read the first byte */
br->value = (*br->read_ptr++) << 8;
return 0;
}
void vp8dx_bool_decoder_fill_c(BOOL_DECODER *br)
{
int left, right;
/* Find available room in the buffer */
left = 0;
right = br->read_ptr - br->write_ptr;
if (right < 0)
{
/* Read pointer is behind the write pointer. We can write from the
* write pointer to the end of the buffer.
*/
right = VP8_BOOL_DECODER_SZ - (br->write_ptr - br->decode_buffer);
left = br->read_ptr - br->decode_buffer;
}
if (right + left < 128)
return;
if (right)
copy_in(br, right);
if (left)
{
br->write_ptr = br->decode_buffer;
copy_in(br, left);
}
}
void vp8dx_stop_decode_c(BOOL_DECODER *bc)
{
vpx_free(bc->decode_buffer);
bc->decode_buffer = 0;
}
#if 0
/*
* Until optimized versions of these functions are available, we
* keep the implementation in the header to allow inlining.
*
* The RTCD-style invocations are still in place so this can
* be switched by just uncommenting these functions here and
* the DBOOLHUFF_INVOKE calls in the header.
*/
int vp8dx_decode_bool_c(BOOL_DECODER *br, int probability)
{
unsigned int bit=0;
unsigned int split;
unsigned int bigsplit;
register unsigned int range = br->range;
register unsigned int value = br->value;
split = 1 + (((range-1) * probability) >> 8);
bigsplit = (split<<8);
range = split;
if(value >= bigsplit)
{
range = br->range-split;
value = value-bigsplit;
bit = 1;
}
/*if(range>=0x80)
{
br->value = value;
br->range = range;
return bit;
}*/
{
int count = br->count;
register unsigned int shift = vp8dx_bitreader_norm[range];
range <<= shift;
value <<= shift;
count -= shift;
if(count <= 0)
{
value |= (*br->read_ptr) << (-count);
br->read_ptr = br_ptr_advance(br->read_ptr, 1);
count += 8 ;
}
br->count = count;
}
br->value = value;
br->range = range;
return bit;
}
int vp8dx_decode_value_c(BOOL_DECODER *br, int bits)
{
int z = 0;
int bit;
for ( bit=bits-1; bit>=0; bit-- )
{
z |= (vp8dx_decode_bool(br, 0x80)<<bit);
}
return z;
}
#endif