vlc_bits.h 5.33 KB
Newer Older
1
/*****************************************************************************
Pere Orga's avatar
Pere Orga committed
2
 * vlc_bits.h : Bit handling helpers
3
 *****************************************************************************
4
 * Copyright (C) 2001, 2002, 2003, 2006, 2015 VLC authors and VideoLAN
5
 * $Id$
6 7
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 9
 *          Gildas Bazin <gbazin at videolan dot org>
 *          Rafaël Carré <funman at videolan dot org>
10
 *
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
11 12 13
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
14 15 16 17
 * (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
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
18 19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
20
 *
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
21 22 23
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24
 *****************************************************************************/
25 26
#ifndef VLC_BITS_H
#define VLC_BITS_H 1
27

28
#include <vlc_common.h>
29

30 31 32 33 34
/**
 * \file
 * This file defines functions, structures for handling streams of bits in vlc
 */

35 36 37 38 39 40
typedef struct bs_s
{
    uint8_t *p_start;
    uint8_t *p;
    uint8_t *p_end;

41
    ssize_t  i_left;    /* i_count number of available bits */
42
    bool     b_read_only;
43
} bs_t;
44

45
static inline void bs_write_init( bs_t *s, void *p_data, size_t i_data )
46
{
47
    s->p_start = (uint8_t *)p_data;
48 49
    s->p       = s->p_start;
    s->p_end   = s->p_start + i_data;
50
    s->i_left  = 8;
51 52 53 54 55 56 57
    s->b_read_only = false;
}

static inline void bs_init( bs_t *s, const void *p_data, size_t i_data )
{
    bs_write_init( s, (void*) p_data, i_data );
    s->b_read_only = true;
58
}
59

60
static inline int bs_pos( const bs_t *s )
61 62 63
{
    return( 8 * ( s->p - s->p_start ) + 8 - s->i_left );
}
64

65
static inline int bs_eof( const bs_t *s )
66 67 68
{
    return( s->p >= s->p_end ? 1: 0 );
}
69

70 71
static inline uint32_t bs_read( bs_t *s, int i_count )
{
72
     static const uint32_t i_mask[33] =
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
     {  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 );
}

142
static inline void bs_skip( bs_t *s, ssize_t i_count )
143 144 145
{
    s->i_left -= i_count;

Laurent Aimar's avatar
Laurent Aimar committed
146
    if( s->i_left <= 0 )
147
    {
Laurent Aimar's avatar
Laurent Aimar committed
148 149 150 151
        const int i_bytes = ( -s->i_left + 8 ) / 8;

        s->p += i_bytes;
        s->i_left += 8 * i_bytes;
152 153 154
    }
}

155
static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
156
{
157 158 159
    if( s->b_read_only )
        return;

160 161 162
    while( i_count > 0 )
    {
        if( s->p >= s->p_end )
163
        {
164
            break;
165
        }
166 167 168 169

        i_count--;

        if( ( i_bits >> i_count )&0x01 )
170
        {
171
            *s->p |= 1 << ( s->i_left - 1 );
172
        }
173
        else
174
        {
175
            *s->p &= ~( 1 << ( s->i_left - 1 ) );
176
        }
177 178 179 180 181 182 183 184 185
        s->i_left--;
        if( s->i_left == 0 )
        {
            s->p++;
            s->i_left = 8;
        }
    }
}

186
static inline void bs_align( bs_t *s )
187 188 189 190 191 192 193
{
    if( s->i_left != 8 )
    {
        s->i_left = 8;
        s->p++;
    }
}
194

195
static inline void bs_align_0( bs_t *s )
196 197
{
    if( s->i_left != 8 )
198 199 200
    {
        bs_write( s, s->i_left, 0 );
    }
201
}
202

203
static inline void bs_align_1( bs_t *s )
204
{
205
    while( !s->b_read_only && s->i_left != 8 )
206 207 208
    {
        bs_write( s, 1, 1 );
    }
209 210
}

211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
/* Read unsigned Exp-Golomb code */
static inline uint32_t bs_read_ue( bs_t * bs )
{
    int32_t i = 0;

    while( bs_read1( bs ) == 0 && bs->p < bs->p_end && i < 32 )
        i++;

    return (1 << i) - 1 + bs_read( bs, i );
}

/* Read signed Exp-Golomb code */
static inline int32_t bs_read_se( bs_t *s )
{
    int val = bs_read_ue( s );

    return val&0x01 ? (val+1)/2 : -(val/2);
}

230
#endif