]> git.sesse.net Git - vlc/blobdiff - include/vlc_bits.h
* include/vlc_bits.h: bit stream reader/writer.
[vlc] / include / vlc_bits.h
diff --git a/include/vlc_bits.h b/include/vlc_bits.h
new file mode 100644 (file)
index 0000000..87716e0
--- /dev/null
@@ -0,0 +1,185 @@
+/*****************************************************************************
+ * bits.h :
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: vlc_bits.h,v 1.1 2003/11/18 20:15:38 fenrir Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef _VLC_BITS_H
+#define _VLC_BITS_H 1
+
+typedef struct bs_s
+{
+    uint8_t *p_start;
+    uint8_t *p;
+    uint8_t *p_end;
+
+    int     i_left;    /* i_count number of available bits */
+} bs_t;
+
+static inline void bs_init( bs_t *s, void *p_data, int i_data )
+{
+    s->p_start = p_data;
+    s->p       = p_data;
+    s->p_end   = s->p + i_data;
+    s->i_left  = 8;
+}
+static inline int bs_pos( bs_t *s )
+{
+    return( 8 * ( s->p - s->p_start ) + 8 - s->i_left );
+}
+static inline int bs_eof( bs_t *s )
+{
+    return( s->p >= s->p_end ? 1: 0 );
+}
+static inline uint32_t bs_read( bs_t *s, int i_count )
+{
+     static uint32_t i_mask[33] =
+     {  0x00,
+        0x01,      0x03,      0x07,      0x0f,
+        0x1f,      0x3f,      0x7f,      0xff,
+        0x1ff,     0x3ff,     0x7ff,     0xfff,
+        0x1fff,    0x3fff,    0x7fff,    0xffff,
+        0x1ffff,   0x3ffff,   0x7ffff,   0xfffff,
+        0x1fffff,  0x3fffff,  0x7fffff,  0xffffff,
+        0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
+        0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
+    int      i_shr;
+    uint32_t i_result = 0;
+
+    while( i_count > 0 )
+    {
+        if( s->p >= s->p_end )
+        {
+            break;
+        }
+
+        if( ( i_shr = s->i_left - i_count ) >= 0 )
+        {
+            /* more in the buffer than requested */
+            i_result |= ( *s->p >> i_shr )&i_mask[i_count];
+            s->i_left -= i_count;
+            if( s->i_left == 0 )
+            {
+                s->p++;
+                s->i_left = 8;
+            }
+            return( i_result );
+        }
+        else
+        {
+            /* less in the buffer than requested */
+           i_result |= (*s->p&i_mask[s->i_left]) << -i_shr;
+           i_count  -= s->i_left;
+           s->p++;
+           s->i_left = 8;
+        }
+    }
+
+    return( i_result );
+}
+
+static inline uint32_t bs_read1( bs_t *s )
+{
+    if( s->p < s->p_end )
+    {
+        unsigned int i_result;
+
+        s->i_left--;
+        i_result = ( *s->p >> s->i_left )&0x01;
+        if( s->i_left == 0 )
+        {
+            s->p++;
+            s->i_left = 8;
+        }
+        return i_result;
+    }
+
+    return 0;
+}
+
+static inline uint32_t bs_show( bs_t *s, int i_count )
+{
+    bs_t     s_tmp = *s;
+    return bs_read( &s_tmp, i_count );
+}
+
+static inline void bs_skip( bs_t *s, int i_count )
+{
+    s->i_left -= i_count;
+
+    while( s->i_left <= 0 )
+    {
+        s->p++;
+        s->i_left += 8;
+    }
+}
+
+static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
+{
+    while( i_count > 0 )
+    {
+        if( s->p >= s->p_end )
+        {
+            break;
+        }
+
+        i_count--;
+
+        if( ( i_bits >> i_count )&0x01 )
+        {
+            *s->p |= 1 << ( s->i_left - 1 );
+        }
+        else
+        {
+            *s->p &= ~( 1 << ( s->i_left - 1 ) );
+        }
+        s->i_left--;
+        if( s->i_left == 0 )
+        {
+            s->p++;
+            s->i_left = 8;
+        }
+    }
+}
+
+static inline void bs_align( bs_t *s )
+{
+    if( s->i_left != 8 )
+    {
+        s->i_left = 8;
+        s->p++;
+    }
+}
+static inline void bs_align_0( bs_t *s )
+{
+    if( s->i_left != 8 )
+    {
+        bs_write( s, s->i_left, 0 );
+    }
+}
+static inline void bs_align_1( bs_t *s )
+{
+    while( s->i_left != 8 )
+    {
+        bs_write( s, 1, 1 );
+    }
+}
+
+#endif