summaryrefslogtreecommitdiff
path: root/libavcodec/bitstream.h
blob: 3fa63695d3fc07de52da04dba49a2df394050cb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Copyright (c) 2016 Alexandra Hájková
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg 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 (at your option) any later version.
 *
 * FFmpeg 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**
 * @file
 * bitstream reader API header.
 */

#ifndef AVCODEC_BITSTREAM_H
#define AVCODEC_BITSTREAM_H

#include <stdint.h>

#include "config.h"

#include "libavutil/common.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/log.h"

#include "mathops.h"
#include "vlc.h"

#ifndef UNCHECKED_BITSTREAM_READER
#define UNCHECKED_BITSTREAM_READER !CONFIG_SAFE_BITSTREAM_READER
#endif

typedef struct BitstreamContext {
    uint64_t bits;      // stores bits read from the buffer
    const uint8_t *buffer, *buffer_end;
    const uint8_t *ptr; // pointer to the position inside a buffer
    unsigned bits_left; // number of bits left in bits field
    unsigned size_in_bits;
} BitstreamContext;

/**
 * Return number of bits already read.
 */
static inline int bitstream_tell(const BitstreamContext *bc)
{
    return (bc->ptr - bc->buffer) * 8 - bc->bits_left;
}

/**
 * Return buffer size in bits.
 */
static inline int bitstream_tell_size(const BitstreamContext *bc)
{
    return bc->size_in_bits;
}

/**
 * Return the number of the bits left in a buffer.
 */
static inline int bitstream_bits_left(const BitstreamContext *bc)
{
    return (bc->buffer - bc->ptr) * 8 + bc->size_in_bits + bc->bits_left;
}

/* Unwind the cache so a refill_32 can fill it again. */
static inline void bitstream_unwind(BitstreamContext *bc)
{
    int unwind = 4;
    int unwind_bits = unwind * 8;

    if (bc->bits_left < unwind_bits)
        return;

    bc->bits      >>= unwind_bits;
    bc->bits      <<= unwind_bits;
    bc->bits_left  -= unwind_bits;
    bc->ptr        -= unwind;
}

/* Unget up to 32 bits. */
static inline void bitstream_unget(BitstreamContext *bc, uint64_t value,
                                   size_t amount)
{
    size_t cache_size = sizeof(bc->bits) * 8;

    if (bc->bits_left + amount > cache_size)
        bitstream_unwind(bc);

    bc->bits       = (bc->bits >> amount) | (value << (cache_size - amount));
    bc->bits_left += amount;
}

#define BITSTREAM_LE
#include "bitstream_template.h"

#undef BITSTREAM_LE
#include "bitstream_template.h"

#define bitstream_init          bitstream_init_be
#define bitstream_init8         bitstream_init8_be
#define bitstream_read_bit      bitstream_read_bit_be
#define bitstream_read_63       bitstream_read_63_be
#define bitstream_read          bitstream_read_be
#define bitstream_read_signed   bitstream_read_signed_be
#define bitstream_peek          bitstream_peek_be
#define bitstream_peek_signed   bitstream_peek_signed_be
#define bitstream_skip          bitstream_skip_be
#define bitstream_seek          bitstream_seek_be
#define bitstream_align         bitstream_align_be
#define bitstream_read_xbits    bitstream_read_xbits_be
#define bitstream_decode012     bitstream_decode012_be
#define bitstream_decode210     bitstream_decode210_be
#define bitstream_apply_sign    bitstream_apply_sign_be
#define bitstream_read_vlc      bitstream_read_vlc_be

#define BITSTREAM_RL_VLC(level, run, bc, table, bits, max_depth) \
    do {                                                         \
        int n, nb_bits;                                          \
        unsigned int index = bitstream_peek(bc, bits);           \
        level = table[index].level;                              \
        n     = table[index].len;                                \
                                                                 \
        if (max_depth > 1 && n < 0) {                            \
            bitstream_skip(bc, bits);                            \
                                                                 \
            nb_bits = -n;                                        \
                                                                 \
            index = bitstream_peek(bc, nb_bits) + level;         \
            level = table[index].level;                          \
            n     = table[index].len;                            \
            if (max_depth > 2 && n < 0) {                        \
                bitstream_skip(bc, nb_bits);                     \
                nb_bits = -n;                                    \
                                                                 \
                index = bitstream_peek(bc, nb_bits) + level;     \
                level = table[index].level;                      \
                n     = table[index].len;                        \
            }                                                    \
        }                                                        \
        run = table[index].run;                                  \
        bitstream_skip(bc, n);                                   \
    } while (0)

#endif /* AVCODEC_BITSTREAM_H */