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 
11 #ifndef VPX_VPX_DSP_BITWRITER_H_
12 #define VPX_VPX_DSP_BITWRITER_H_
13 
14 #include <stdio.h>
15 
16 #include "vpx_ports/mem.h"
17 
18 #include "vpx_dsp/prob.h"
19 #if CONFIG_BITSTREAM_DEBUG
20 #include "vpx_util/vpx_debug_util.h"
21 #endif  // CONFIG_BITSTREAM_DEBUG
22 
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 typedef struct vpx_writer {
28   unsigned int lowvalue;
29   unsigned int range;
30   int count;
31   unsigned int pos;
32   uint8_t *buffer;
33 } vpx_writer;
34 
35 void vpx_start_encode(vpx_writer *br, uint8_t *source);
36 void vpx_stop_encode(vpx_writer *br);
37 
vpx_write(vpx_writer * br,int bit,int probability)38 static INLINE void vpx_write(vpx_writer *br, int bit, int probability) {
39   unsigned int split;
40   int count = br->count;
41   unsigned int range = br->range;
42   unsigned int lowvalue = br->lowvalue;
43   int shift;
44 
45 #if CONFIG_BITSTREAM_DEBUG
46   /*
47   int queue_r = 0;
48   int frame_idx_r = 0;
49   int queue_w = bitstream_queue_get_write();
50   int frame_idx_w = bitstream_queue_get_frame_write();
51   if (frame_idx_w == frame_idx_r && queue_w == queue_r) {
52     fprintf(stderr, "\n *** bitstream queue at frame_idx_w %d queue_w %d\n",
53             frame_idx_w, queue_w);
54     assert(0);
55   }
56   */
57   bitstream_queue_push(bit, probability);
58 #endif
59 
60   split = 1 + (((range - 1) * probability) >> 8);
61 
62   range = split;
63 
64   if (bit) {
65     lowvalue += split;
66     range = br->range - split;
67   }
68 
69   shift = vpx_norm[range];
70 
71   range <<= shift;
72   count += shift;
73 
74   if (count >= 0) {
75     int offset = shift - count;
76 
77     if ((lowvalue << (offset - 1)) & 0x80000000) {
78       int x = br->pos - 1;
79 
80       while (x >= 0 && br->buffer[x] == 0xff) {
81         br->buffer[x] = 0;
82         x--;
83       }
84 
85       br->buffer[x] += 1;
86     }
87 
88     br->buffer[br->pos++] = (lowvalue >> (24 - offset)) & 0xff;
89     lowvalue <<= offset;
90     shift = count;
91     lowvalue &= 0xffffff;
92     count -= 8;
93   }
94 
95   lowvalue <<= shift;
96   br->count = count;
97   br->lowvalue = lowvalue;
98   br->range = range;
99 }
100 
vpx_write_bit(vpx_writer * w,int bit)101 static INLINE void vpx_write_bit(vpx_writer *w, int bit) {
102   vpx_write(w, bit, 128);  // vpx_prob_half
103 }
104 
vpx_write_literal(vpx_writer * w,int data,int bits)105 static INLINE void vpx_write_literal(vpx_writer *w, int data, int bits) {
106   int bit;
107 
108   for (bit = bits - 1; bit >= 0; bit--) vpx_write_bit(w, 1 & (data >> bit));
109 }
110 
111 #define vpx_write_prob(w, v) vpx_write_literal((w), (v), 8)
112 
113 #ifdef __cplusplus
114 }  // extern "C"
115 #endif
116 
117 #endif  // VPX_VPX_DSP_BITWRITER_H_
118