bitreader.c revision 7ce0a1d1337c01056ba24006efab21f00e179e04
1/*
2 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10#include <stdlib.h>
11
12#include "./vpx_config.h"
13
14#include "vpx_dsp/bitreader.h"
15#include "vpx_dsp/prob.h"
16#include "vpx_ports/mem.h"
17#include "vpx_mem/vpx_mem.h"
18#include "vpx_util/endian_inl.h"
19
20int vpx_reader_init(vpx_reader *r,
21                    const uint8_t *buffer,
22                    size_t size,
23                    vpx_decrypt_cb decrypt_cb,
24                    void *decrypt_state) {
25  if (size && !buffer) {
26    return 1;
27  } else {
28    r->buffer_end = buffer + size;
29    r->buffer = buffer;
30    r->value = 0;
31    r->count = -8;
32    r->range = 255;
33    r->decrypt_cb = decrypt_cb;
34    r->decrypt_state = decrypt_state;
35    vpx_reader_fill(r);
36    return vpx_read_bit(r) != 0;  // marker bit
37  }
38}
39
40void vpx_reader_fill(vpx_reader *r) {
41  const uint8_t *const buffer_end = r->buffer_end;
42  const uint8_t *buffer = r->buffer;
43  const uint8_t *buffer_start = buffer;
44  BD_VALUE value = r->value;
45  int count = r->count;
46  const size_t bytes_left = buffer_end - buffer;
47  const size_t bits_left = bytes_left * CHAR_BIT;
48  int shift = BD_VALUE_SIZE - CHAR_BIT - (count + CHAR_BIT);
49
50  if (r->decrypt_cb) {
51    size_t n = MIN(sizeof(r->clear_buffer), bytes_left);
52    r->decrypt_cb(r->decrypt_state, buffer, r->clear_buffer, (int)n);
53    buffer = r->clear_buffer;
54    buffer_start = r->clear_buffer;
55  }
56  if (bits_left > BD_VALUE_SIZE) {
57      const int bits = (shift & 0xfffffff8) + CHAR_BIT;
58      BD_VALUE nv;
59      BD_VALUE big_endian_values;
60      memcpy(&big_endian_values, buffer, sizeof(BD_VALUE));
61#if SIZE_MAX == 0xffffffffffffffffULL
62        big_endian_values = HToBE64(big_endian_values);
63#else
64        big_endian_values = HToBE32(big_endian_values);
65#endif
66      nv = big_endian_values >> (BD_VALUE_SIZE - bits);
67      count += bits;
68      buffer += (bits >> 3);
69      value = r->value | (nv << (shift & 0x7));
70  } else {
71    const int bits_over = (int)(shift + CHAR_BIT - bits_left);
72    int loop_end = 0;
73    if (bits_over >= 0) {
74      count += LOTS_OF_BITS;
75      loop_end = bits_over;
76    }
77
78    if (bits_over < 0 || bits_left) {
79      while (shift >= loop_end) {
80        count += CHAR_BIT;
81        value |= (BD_VALUE)*buffer++ << shift;
82        shift -= CHAR_BIT;
83      }
84    }
85  }
86
87  // NOTE: Variable 'buffer' may not relate to 'r->buffer' after decryption,
88  // so we increase 'r->buffer' by the amount that 'buffer' moved, rather than
89  // assign 'buffer' to 'r->buffer'.
90  r->buffer += buffer - buffer_start;
91  r->value = value;
92  r->count = count;
93}
94
95const uint8_t *vpx_reader_find_end(vpx_reader *r) {
96  // Find the end of the coded buffer
97  while (r->count > CHAR_BIT && r->count < BD_VALUE_SIZE) {
98    r->count -= CHAR_BIT;
99    r->buffer--;
100  }
101  return r->buffer;
102}
103