tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

put_bits.h (11221B)


      1 /*
      2 * copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
      3 *
      4 * This file is part of FFmpeg.
      5 *
      6 * FFmpeg is free software; you can redistribute it and/or
      7 * modify it under the terms of the GNU Lesser General Public
      8 * License as published by the Free Software Foundation; either
      9 * version 2.1 of the License, or (at your option) any later version.
     10 *
     11 * FFmpeg is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with FFmpeg; if not, write to the Free Software
     18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19 */
     20 
     21 /**
     22 * @file
     23 * bitstream writer API
     24 */
     25 
     26 #ifndef AVCODEC_PUT_BITS_H
     27 #define AVCODEC_PUT_BITS_H
     28 
     29 #include <stdint.h>
     30 #include <stddef.h>
     31 
     32 #include "config.h"
     33 #include "libavutil/intreadwrite.h"
     34 #include "libavutil/avassert.h"
     35 #include "libavutil/common.h"
     36 
     37 #if ARCH_X86_64
     38 // TODO: Benchmark and optionally enable on other 64-bit architectures.
     39 typedef uint64_t BitBuf;
     40 #define AV_WBBUF AV_WB64
     41 #define AV_WLBUF AV_WL64
     42 #else
     43 typedef uint32_t BitBuf;
     44 #define AV_WBBUF AV_WB32
     45 #define AV_WLBUF AV_WL32
     46 #endif
     47 
     48 static const int BUF_BITS = 8 * sizeof(BitBuf);
     49 
     50 typedef struct PutBitContext {
     51    BitBuf bit_buf;
     52    int bit_left;
     53    uint8_t *buf, *buf_ptr, *buf_end;
     54 } PutBitContext;
     55 
     56 /**
     57 * Initialize the PutBitContext s.
     58 *
     59 * @param buffer the buffer where to put bits
     60 * @param buffer_size the size in bytes of buffer
     61 */
     62 static inline void init_put_bits(PutBitContext *s, uint8_t *buffer,
     63                                 int buffer_size)
     64 {
     65    if (buffer_size < 0) {
     66        buffer_size = 0;
     67        buffer      = NULL;
     68    }
     69 
     70    s->buf          = buffer;
     71    s->buf_end      = s->buf + buffer_size;
     72    s->buf_ptr      = s->buf;
     73    s->bit_left     = BUF_BITS;
     74    s->bit_buf      = 0;
     75 }
     76 
     77 /**
     78 * @return the total number of bits written to the bitstream.
     79 */
     80 static inline int put_bits_count(PutBitContext *s)
     81 {
     82    return (s->buf_ptr - s->buf) * 8 + BUF_BITS - s->bit_left;
     83 }
     84 
     85 /**
     86 * @return the number of bytes output so far; may only be called
     87 *         when the PutBitContext is freshly initialized or flushed.
     88 */
     89 static inline int put_bytes_output(const PutBitContext *s)
     90 {
     91    av_assert2(s->bit_left == BUF_BITS);
     92    return s->buf_ptr - s->buf;
     93 }
     94 
     95 /**
     96 * @param  round_up  When set, the number of bits written so far will be
     97 *                   rounded up to the next byte.
     98 * @return the number of bytes output so far.
     99 */
    100 static inline int put_bytes_count(const PutBitContext *s, int round_up)
    101 {
    102    return s->buf_ptr - s->buf + ((BUF_BITS - s->bit_left + (round_up ? 7 : 0)) >> 3);
    103 }
    104 
    105 /**
    106 * Rebase the bit writer onto a reallocated buffer.
    107 *
    108 * @param buffer the buffer where to put bits
    109 * @param buffer_size the size in bytes of buffer,
    110 *                    must be large enough to hold everything written so far
    111 */
    112 static inline void rebase_put_bits(PutBitContext *s, uint8_t *buffer,
    113                                   int buffer_size)
    114 {
    115    av_assert0(8*buffer_size >= put_bits_count(s));
    116 
    117    s->buf_end = buffer + buffer_size;
    118    s->buf_ptr = buffer + (s->buf_ptr - s->buf);
    119    s->buf     = buffer;
    120 }
    121 
    122 /**
    123 * @return the number of bits available in the bitstream.
    124 */
    125 static inline int put_bits_left(PutBitContext* s)
    126 {
    127    return (s->buf_end - s->buf_ptr) * 8 - BUF_BITS + s->bit_left;
    128 }
    129 
    130 /**
    131 * @param  round_up  When set, the number of bits written will be
    132 *                   rounded up to the next byte.
    133 * @return the number of bytes left.
    134 */
    135 static inline int put_bytes_left(const PutBitContext *s, int round_up)
    136 {
    137    return s->buf_end - s->buf_ptr - ((BUF_BITS - s->bit_left + (round_up ? 7 : 0)) >> 3);
    138 }
    139 
    140 /**
    141 * Pad the end of the output stream with zeros.
    142 */
    143 static inline void flush_put_bits(PutBitContext *s)
    144 {
    145 #ifndef BITSTREAM_WRITER_LE
    146    if (s->bit_left < BUF_BITS)
    147        s->bit_buf <<= s->bit_left;
    148 #endif
    149    while (s->bit_left < BUF_BITS) {
    150        av_assert0(s->buf_ptr < s->buf_end);
    151 #ifdef BITSTREAM_WRITER_LE
    152        *s->buf_ptr++ = s->bit_buf;
    153        s->bit_buf  >>= 8;
    154 #else
    155        *s->buf_ptr++ = s->bit_buf >> (BUF_BITS - 8);
    156        s->bit_buf  <<= 8;
    157 #endif
    158        s->bit_left  += 8;
    159    }
    160    s->bit_left = BUF_BITS;
    161    s->bit_buf  = 0;
    162 }
    163 
    164 static inline void flush_put_bits_le(PutBitContext *s)
    165 {
    166    while (s->bit_left < BUF_BITS) {
    167        av_assert0(s->buf_ptr < s->buf_end);
    168        *s->buf_ptr++ = s->bit_buf;
    169        s->bit_buf  >>= 8;
    170        s->bit_left  += 8;
    171    }
    172    s->bit_left = BUF_BITS;
    173    s->bit_buf  = 0;
    174 }
    175 
    176 #ifdef BITSTREAM_WRITER_LE
    177 #define ff_put_string ff_put_string_unsupported_here
    178 #define ff_copy_bits ff_copy_bits_unsupported_here
    179 #else
    180 
    181 /**
    182 * Put the string string in the bitstream.
    183 *
    184 * @param terminate_string 0-terminates the written string if value is 1
    185 */
    186 void ff_put_string(PutBitContext *pb, const char *string,
    187                       int terminate_string);
    188 
    189 /**
    190 * Copy the content of src to the bitstream.
    191 *
    192 * @param length the number of bits of src to copy
    193 */
    194 void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length);
    195 #endif
    196 
    197 static inline void put_bits_no_assert(PutBitContext *s, int n, BitBuf value)
    198 {
    199    BitBuf bit_buf;
    200    int bit_left;
    201 
    202    bit_buf  = s->bit_buf;
    203    bit_left = s->bit_left;
    204 
    205    /* XXX: optimize */
    206 #ifdef BITSTREAM_WRITER_LE
    207    bit_buf |= value << (BUF_BITS - bit_left);
    208    if (n >= bit_left) {
    209        if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
    210            AV_WLBUF(s->buf_ptr, bit_buf);
    211            s->buf_ptr += sizeof(BitBuf);
    212        } else {
    213            av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
    214            av_assert2(0);
    215        }
    216        bit_buf     = value >> bit_left;
    217        bit_left   += BUF_BITS;
    218    }
    219    bit_left -= n;
    220 #else
    221    if (n < bit_left) {
    222        bit_buf     = (bit_buf << n) | value;
    223        bit_left   -= n;
    224    } else {
    225        bit_buf   <<= bit_left;
    226        bit_buf    |= value >> (n - bit_left);
    227        if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
    228            AV_WBBUF(s->buf_ptr, bit_buf);
    229            s->buf_ptr += sizeof(BitBuf);
    230        } else {
    231            av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
    232            av_assert2(0);
    233        }
    234        bit_left   += BUF_BITS - n;
    235        bit_buf     = value;
    236    }
    237 #endif
    238 
    239    s->bit_buf  = bit_buf;
    240    s->bit_left = bit_left;
    241 }
    242 
    243 /**
    244 * Write up to 31 bits into a bitstream.
    245 * Use put_bits32 to write 32 bits.
    246 */
    247 static inline void put_bits(PutBitContext *s, int n, BitBuf value)
    248 {
    249    av_assert2(n <= 31 && value < (1UL << n));
    250    put_bits_no_assert(s, n, value);
    251 }
    252 
    253 static inline void put_bits_le(PutBitContext *s, int n, BitBuf value)
    254 {
    255    BitBuf bit_buf;
    256    int bit_left;
    257 
    258    av_assert2(n <= 31 && value < (1UL << n));
    259 
    260    bit_buf  = s->bit_buf;
    261    bit_left = s->bit_left;
    262 
    263    bit_buf |= value << (BUF_BITS - bit_left);
    264    if (n >= bit_left) {
    265        if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
    266            AV_WLBUF(s->buf_ptr, bit_buf);
    267            s->buf_ptr += sizeof(BitBuf);
    268        } else {
    269            av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
    270            av_assert2(0);
    271        }
    272        bit_buf     = value >> bit_left;
    273        bit_left   += BUF_BITS;
    274    }
    275    bit_left -= n;
    276 
    277    s->bit_buf  = bit_buf;
    278    s->bit_left = bit_left;
    279 }
    280 
    281 static inline void put_sbits(PutBitContext *pb, int n, int32_t value)
    282 {
    283    av_assert2(n >= 0 && n <= 31);
    284 
    285    put_bits(pb, n, av_zero_extend(value, n));
    286 }
    287 
    288 /**
    289 * Write exactly 32 bits into a bitstream.
    290 */
    291 static void av_unused put_bits32(PutBitContext *s, uint32_t value)
    292 {
    293    BitBuf bit_buf;
    294    int bit_left;
    295 
    296    if (BUF_BITS > 32) {
    297        put_bits_no_assert(s, 32, value);
    298        return;
    299    }
    300 
    301    bit_buf  = s->bit_buf;
    302    bit_left = s->bit_left;
    303 
    304 #ifdef BITSTREAM_WRITER_LE
    305    bit_buf |= (BitBuf)value << (BUF_BITS - bit_left);
    306    if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
    307        AV_WLBUF(s->buf_ptr, bit_buf);
    308        s->buf_ptr += sizeof(BitBuf);
    309    } else {
    310        av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
    311        av_assert2(0);
    312    }
    313    bit_buf     = (uint64_t)value >> bit_left;
    314 #else
    315    bit_buf     = (uint64_t)bit_buf << bit_left;
    316    bit_buf    |= (BitBuf)value >> (BUF_BITS - bit_left);
    317    if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
    318        AV_WBBUF(s->buf_ptr, bit_buf);
    319        s->buf_ptr += sizeof(BitBuf);
    320    } else {
    321        av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
    322        av_assert2(0);
    323    }
    324    bit_buf     = value;
    325 #endif
    326 
    327    s->bit_buf  = bit_buf;
    328    s->bit_left = bit_left;
    329 }
    330 
    331 /**
    332 * Write up to 64 bits into a bitstream.
    333 */
    334 static inline void put_bits64(PutBitContext *s, int n, uint64_t value)
    335 {
    336    av_assert2((n == 64) || (n < 64 && value < (UINT64_C(1) << n)));
    337 
    338    if (n < 32)
    339        put_bits(s, n, value);
    340    else if (n == 32)
    341        put_bits32(s, value);
    342    else if (n < 64) {
    343        uint32_t lo = value & 0xffffffff;
    344        uint32_t hi = value >> 32;
    345 #ifdef BITSTREAM_WRITER_LE
    346        put_bits32(s, lo);
    347        put_bits(s, n - 32, hi);
    348 #else
    349        put_bits(s, n - 32, hi);
    350        put_bits32(s, lo);
    351 #endif
    352    } else {
    353        uint32_t lo = value & 0xffffffff;
    354        uint32_t hi = value >> 32;
    355 #ifdef BITSTREAM_WRITER_LE
    356        put_bits32(s, lo);
    357        put_bits32(s, hi);
    358 #else
    359        put_bits32(s, hi);
    360        put_bits32(s, lo);
    361 #endif
    362 
    363    }
    364 }
    365 
    366 static inline void put_sbits63(PutBitContext *pb, int n, int64_t value)
    367 {
    368    av_assert2(n >= 0 && n < 64);
    369 
    370    put_bits64(pb, n, (uint64_t)(value) & (~(UINT64_MAX << n)));
    371 }
    372 
    373 /**
    374 * Return the pointer to the byte where the bitstream writer will put
    375 * the next bit.
    376 */
    377 static inline uint8_t *put_bits_ptr(PutBitContext *s)
    378 {
    379    return s->buf_ptr;
    380 }
    381 
    382 /**
    383 * Skip the given number of bytes.
    384 * PutBitContext must be flushed & aligned to a byte boundary before calling this.
    385 */
    386 static inline void skip_put_bytes(PutBitContext *s, int n)
    387 {
    388    av_assert2((put_bits_count(s) & 7) == 0);
    389    av_assert2(s->bit_left == BUF_BITS);
    390    av_assert0(n <= s->buf_end - s->buf_ptr);
    391    s->buf_ptr += n;
    392 }
    393 
    394 /**
    395 * Skip the given number of bits.
    396 * Must only be used if the actual values in the bitstream do not matter.
    397 * If n is < 0 the behavior is undefined.
    398 */
    399 static inline void skip_put_bits(PutBitContext *s, int n)
    400 {
    401    unsigned bits = BUF_BITS - s->bit_left + n;
    402    s->buf_ptr += sizeof(BitBuf) * (bits / BUF_BITS);
    403    s->bit_left = BUF_BITS - (bits & (BUF_BITS - 1));
    404 }
    405 
    406 /**
    407 * Change the end of the buffer.
    408 *
    409 * @param size the new size in bytes of the buffer where to put bits
    410 */
    411 static inline void set_put_bits_buffer_size(PutBitContext *s, int size)
    412 {
    413    av_assert0(size <= INT_MAX/8 - BUF_BITS);
    414    s->buf_end = s->buf + size;
    415 }
    416 
    417 /**
    418 * Pad the bitstream with zeros up to the next byte boundary.
    419 */
    420 static inline void align_put_bits(PutBitContext *s)
    421 {
    422    put_bits(s, s->bit_left & 7, 0);
    423 }
    424 
    425 #undef AV_WBBUF
    426 #undef AV_WLBUF
    427 
    428 #endif /* AVCODEC_PUT_BITS_H */