bitwriter_buffer.c (4416B)
1 /* 2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved. 3 * 4 * This source code is subject to the terms of the BSD 2 Clause License and 5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6 * was not distributed with this source code in the LICENSE file, you can 7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8 * Media Patent License 1.0 was not distributed with this source code in the 9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10 */ 11 12 #include <assert.h> 13 #include <limits.h> 14 #include <stdlib.h> 15 16 #include "config/aom_config.h" 17 18 #include "aom_dsp/bitwriter_buffer.h" 19 #include "aom_dsp/recenter.h" 20 #include "aom_ports/bitops.h" 21 22 int aom_wb_is_byte_aligned(const struct aom_write_bit_buffer *wb) { 23 return (wb->bit_offset % CHAR_BIT == 0); 24 } 25 26 uint32_t aom_wb_bytes_written(const struct aom_write_bit_buffer *wb) { 27 return wb->bit_offset / CHAR_BIT + (wb->bit_offset % CHAR_BIT > 0); 28 } 29 30 void aom_wb_write_bit(struct aom_write_bit_buffer *wb, int bit) { 31 const int off = (int)wb->bit_offset; 32 const int p = off / CHAR_BIT; 33 const int q = CHAR_BIT - 1 - off % CHAR_BIT; 34 if (q == CHAR_BIT - 1) { 35 // Zero next char and write bit 36 wb->bit_buffer[p] = bit << q; 37 } else { 38 wb->bit_buffer[p] &= ~(1 << q); 39 wb->bit_buffer[p] |= bit << q; 40 } 41 wb->bit_offset = off + 1; 42 } 43 44 static void overwrite_bit(struct aom_write_bit_buffer *wb, int bit) { 45 // Do not zero bytes but overwrite exisiting values 46 const int off = (int)wb->bit_offset; 47 const int p = off / CHAR_BIT; 48 const int q = CHAR_BIT - 1 - off % CHAR_BIT; 49 wb->bit_buffer[p] &= ~(1 << q); 50 wb->bit_buffer[p] |= bit << q; 51 wb->bit_offset = off + 1; 52 } 53 54 void aom_wb_write_literal(struct aom_write_bit_buffer *wb, int data, int bits) { 55 assert(bits <= 31); 56 int bit; 57 for (bit = bits - 1; bit >= 0; bit--) aom_wb_write_bit(wb, (data >> bit) & 1); 58 } 59 60 void aom_wb_write_unsigned_literal(struct aom_write_bit_buffer *wb, 61 uint32_t data, int bits) { 62 assert(bits <= 32); 63 int bit; 64 for (bit = bits - 1; bit >= 0; bit--) aom_wb_write_bit(wb, (data >> bit) & 1); 65 } 66 67 void aom_wb_overwrite_literal(struct aom_write_bit_buffer *wb, int data, 68 int bits) { 69 int bit; 70 for (bit = bits - 1; bit >= 0; bit--) overwrite_bit(wb, (data >> bit) & 1); 71 } 72 73 void aom_wb_write_inv_signed_literal(struct aom_write_bit_buffer *wb, int data, 74 int bits) { 75 aom_wb_write_literal(wb, data, bits + 1); 76 } 77 78 void aom_wb_write_uvlc(struct aom_write_bit_buffer *wb, uint32_t v) { 79 assert(v != UINT32_MAX); 80 ++v; 81 const int leading_zeroes = get_msb(v); 82 aom_wb_write_literal(wb, 0, leading_zeroes); 83 aom_wb_write_unsigned_literal(wb, v, leading_zeroes + 1); 84 } 85 86 static void wb_write_primitive_quniform(struct aom_write_bit_buffer *wb, 87 uint16_t n, uint16_t v) { 88 if (n <= 1) return; 89 const int l = get_msb(n) + 1; 90 const int m = (1 << l) - n; 91 if (v < m) { 92 aom_wb_write_literal(wb, v, l - 1); 93 } else { 94 aom_wb_write_literal(wb, m + ((v - m) >> 1), l - 1); 95 aom_wb_write_bit(wb, (v - m) & 1); 96 } 97 } 98 99 static void wb_write_primitive_subexpfin(struct aom_write_bit_buffer *wb, 100 uint16_t n, uint16_t k, uint16_t v) { 101 int i = 0; 102 int mk = 0; 103 while (1) { 104 int b = (i ? k + i - 1 : k); 105 int a = (1 << b); 106 if (n <= mk + 3 * a) { 107 wb_write_primitive_quniform(wb, n - mk, v - mk); 108 break; 109 } else { 110 int t = (v >= mk + a); 111 aom_wb_write_bit(wb, t); 112 if (t) { 113 i = i + 1; 114 mk += a; 115 } else { 116 aom_wb_write_literal(wb, v - mk, b); 117 break; 118 } 119 } 120 } 121 } 122 123 static void wb_write_primitive_refsubexpfin(struct aom_write_bit_buffer *wb, 124 uint16_t n, uint16_t k, 125 uint16_t ref, uint16_t v) { 126 wb_write_primitive_subexpfin(wb, n, k, recenter_finite_nonneg(n, ref, v)); 127 } 128 129 void aom_wb_write_signed_primitive_refsubexpfin(struct aom_write_bit_buffer *wb, 130 uint16_t n, uint16_t k, 131 int16_t ref, int16_t v) { 132 ref += n - 1; 133 v += n - 1; 134 const uint16_t scaled_n = (n << 1) - 1; 135 wb_write_primitive_refsubexpfin(wb, scaled_n, k, ref, v); 136 }