[Tremor] bitwise.c question
Hans Petter Selasky
hselasky at c2i.net
Tue Feb 21 08:11:06 PST 2006
Hi,
First, your bitwise.c is very cleverly written. Second, I plan to change the
behaviour of oggpack_read(), so that it returns 0, if EOF is reached, instead
of -1. Then have a separate function oggpack_get_valid_1() that will return
true if there is 1 bit or more available in the buffer.
I see it is a pitfall that oggpack_read() can return -1. Consider this:
str = table[oggpack_read(&opb, 5)];
Does anyone have any comments on this change. Also I have a new bitwise.c that
is some percent faster. Up to 50% for "bits > 20":
/* new */
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
* *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
* BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
* *
********************************************************************
function: packing variable sized words into an octet stream
********************************************************************/
/* We're 'LSb' endian; if we write a word but read individual bits,
then we'll read the lsb first */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/endian.h>
#include "ogg.h"
static const u_int32_t mask[]=
{0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
0x3fffffff,0x7fffffff,0xffffffff };
/* the following will allow reading
* un-aligned 32-bit integers
* on some CPUs:
*/
struct u_int32_p {
u_int32_t data;
} __attribute__((__packed__));
typedef struct u_int32_p u_int32_p_t;
struct u_int16_p {
u_int16_t data;
} __attribute__((__packed__));
typedef struct u_int16_p u_int16_p_t;
static u_int32_t
oggpack_fetch_block(oggpack_buffer *buf)
{
register ogg_reference *ref = buf->data_next;
u_int32_t retval;
/* advance in chained list of buffers */
if (ref) {
buf->data_pointer =
ref->buffer->data +
ref->begin ;
buf->data_length =
ref->length;
buf->data_next =
ref->next;
retval = 0;
} else {
retval = 1;
}
return retval;
}
static void
oggpack_adv_byte(oggpack_buffer *buf)
{
if(buf->data_length) {
buf->data_pointer++;
buf->data_length--;
}
return;
}
static u_int32_t
oggpack_get_byte(oggpack_buffer *buf)
{
while (buf->data_length == 0) {
if(oggpack_fetch_block(buf)) {
break;
}
}
return buf->data_length ?
*(buf->data_pointer) : 0;
}
/* oggpack_readinit - initialize a "oggpack_buffer"
*
*/
void
oggpack_readinit(oggpack_buffer *buf, ogg_reference *ref)
{
bzero(buf, sizeof(*buf));
buf->data_next = ref;
return;
}
/* oggpack_read - read 'bits' number of bits and
* advance the logical data stream
*
* NOTE: "bits <= 32"
*/
u_int32_t
oggpack_read_m(oggpack_buffer *buf, u_int32_t bits)
{
u_int32_t temp;
u_int32_t shift;
u_int8_t *ptr;
u_int8_t buffer[5];
if (bits > 32) {
/* should not happen */
bits = 32;
}
/* get mask */
temp = mask[bits];
/* get right-shift */
shift = buf->data_bit_level;
/* compute position of end-bit, exclusive */
bits += shift;
buf->data_bit_level = (bits & 7);
if (buf->data_length < 5) {
/* slow way to get the data */
ptr = &buffer[0];
*ptr++ = oggpack_get_byte(buf);
while(bits >= 8) {
oggpack_adv_byte(buf);
if (bits > 8) {
*ptr++ = oggpack_get_byte(buf);
}
bits -= 8;
}
ptr = &buffer[0];
bits = 4; /* bytes */
} else {
ptr = buf->data_pointer;
/* the fast way to get data;
* 99% of the requests go here
*/
bits >>= 3;
buf->data_length -= bits;
buf->data_pointer += bits;
}
if (bits >= 2) {
temp &= htole32(((u_int32_p_t *)ptr)->data) >> shift;
if (bits >= 4) {
if (shift) {
temp &= ptr[4] << (32-shift);
}
}
} else {
temp &= htole16(((u_int16_p_t *)ptr)->data) >> shift;
}
return temp;
}
/* oggpack_look - read 'bits' number of bits and
* do not advance the logical data stream
*
* NOTE: "bits <= 32"
*/
u_int32_t
oggpack_look_m(oggpack_buffer *buf, u_int32_t bits)
{
oggpack_buffer buf_old = *buf;
u_int32_t temp = oggpack_read_m(buf, bits);
*buf = buf_old;
return temp;
}
/* oggpack_adv - advance the logical data stream
* 'bits' number of bits
*
* NOTE: "bits <= 32"
*/
void
oggpack_adv_m(oggpack_buffer *buf, u_int32_t bits)
{
(void) oggpack_read_m(buf, bits);
return;
}
Any comments ?
--HPS
More information about the Tremor
mailing list