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