1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker *
4*fb1b10abSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker */
10*fb1b10abSAndroid Build Coastguard Worker
11*fb1b10abSAndroid Build Coastguard Worker #ifndef VPX_VPX_DSP_BITWRITER_H_
12*fb1b10abSAndroid Build Coastguard Worker #define VPX_VPX_DSP_BITWRITER_H_
13*fb1b10abSAndroid Build Coastguard Worker
14*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
15*fb1b10abSAndroid Build Coastguard Worker
16*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/compiler_attributes.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/mem.h"
18*fb1b10abSAndroid Build Coastguard Worker
19*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/prob.h"
20*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_BITSTREAM_DEBUG
21*fb1b10abSAndroid Build Coastguard Worker #include "vpx_util/vpx_debug_util.h"
22*fb1b10abSAndroid Build Coastguard Worker #endif // CONFIG_BITSTREAM_DEBUG
23*fb1b10abSAndroid Build Coastguard Worker
24*fb1b10abSAndroid Build Coastguard Worker #ifdef __cplusplus
25*fb1b10abSAndroid Build Coastguard Worker extern "C" {
26*fb1b10abSAndroid Build Coastguard Worker #endif
27*fb1b10abSAndroid Build Coastguard Worker
28*fb1b10abSAndroid Build Coastguard Worker typedef struct vpx_writer {
29*fb1b10abSAndroid Build Coastguard Worker unsigned int lowvalue;
30*fb1b10abSAndroid Build Coastguard Worker unsigned int range;
31*fb1b10abSAndroid Build Coastguard Worker int count;
32*fb1b10abSAndroid Build Coastguard Worker // Whether there has been an error.
33*fb1b10abSAndroid Build Coastguard Worker int error;
34*fb1b10abSAndroid Build Coastguard Worker // We maintain the invariant that pos <= size, i.e., we never write beyond
35*fb1b10abSAndroid Build Coastguard Worker // the end of the buffer. If pos would be incremented to be greater than
36*fb1b10abSAndroid Build Coastguard Worker // size, leave pos unchanged and set error to 1.
37*fb1b10abSAndroid Build Coastguard Worker unsigned int pos;
38*fb1b10abSAndroid Build Coastguard Worker unsigned int size;
39*fb1b10abSAndroid Build Coastguard Worker uint8_t *buffer;
40*fb1b10abSAndroid Build Coastguard Worker } vpx_writer;
41*fb1b10abSAndroid Build Coastguard Worker
42*fb1b10abSAndroid Build Coastguard Worker void vpx_start_encode(vpx_writer *br, uint8_t *source, size_t size);
43*fb1b10abSAndroid Build Coastguard Worker // Returns 0 on success and returns -1 in case of error.
44*fb1b10abSAndroid Build Coastguard Worker int vpx_stop_encode(vpx_writer *br);
45*fb1b10abSAndroid Build Coastguard Worker
vpx_write(vpx_writer * br,int bit,int probability)46*fb1b10abSAndroid Build Coastguard Worker static INLINE VPX_NO_UNSIGNED_SHIFT_CHECK void vpx_write(vpx_writer *br,
47*fb1b10abSAndroid Build Coastguard Worker int bit,
48*fb1b10abSAndroid Build Coastguard Worker int probability) {
49*fb1b10abSAndroid Build Coastguard Worker unsigned int split;
50*fb1b10abSAndroid Build Coastguard Worker int count = br->count;
51*fb1b10abSAndroid Build Coastguard Worker unsigned int range = br->range;
52*fb1b10abSAndroid Build Coastguard Worker unsigned int lowvalue = br->lowvalue;
53*fb1b10abSAndroid Build Coastguard Worker int shift;
54*fb1b10abSAndroid Build Coastguard Worker
55*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_BITSTREAM_DEBUG
56*fb1b10abSAndroid Build Coastguard Worker /*
57*fb1b10abSAndroid Build Coastguard Worker int queue_r = 0;
58*fb1b10abSAndroid Build Coastguard Worker int frame_idx_r = 0;
59*fb1b10abSAndroid Build Coastguard Worker int queue_w = bitstream_queue_get_write();
60*fb1b10abSAndroid Build Coastguard Worker int frame_idx_w = bitstream_queue_get_frame_write();
61*fb1b10abSAndroid Build Coastguard Worker if (frame_idx_w == frame_idx_r && queue_w == queue_r) {
62*fb1b10abSAndroid Build Coastguard Worker fprintf(stderr, "\n *** bitstream queue at frame_idx_w %d queue_w %d\n",
63*fb1b10abSAndroid Build Coastguard Worker frame_idx_w, queue_w);
64*fb1b10abSAndroid Build Coastguard Worker assert(0);
65*fb1b10abSAndroid Build Coastguard Worker }
66*fb1b10abSAndroid Build Coastguard Worker */
67*fb1b10abSAndroid Build Coastguard Worker bitstream_queue_push(bit, probability);
68*fb1b10abSAndroid Build Coastguard Worker #endif
69*fb1b10abSAndroid Build Coastguard Worker
70*fb1b10abSAndroid Build Coastguard Worker split = 1 + (((range - 1) * probability) >> 8);
71*fb1b10abSAndroid Build Coastguard Worker
72*fb1b10abSAndroid Build Coastguard Worker range = split;
73*fb1b10abSAndroid Build Coastguard Worker
74*fb1b10abSAndroid Build Coastguard Worker if (bit) {
75*fb1b10abSAndroid Build Coastguard Worker lowvalue += split;
76*fb1b10abSAndroid Build Coastguard Worker range = br->range - split;
77*fb1b10abSAndroid Build Coastguard Worker }
78*fb1b10abSAndroid Build Coastguard Worker
79*fb1b10abSAndroid Build Coastguard Worker shift = vpx_norm[range];
80*fb1b10abSAndroid Build Coastguard Worker
81*fb1b10abSAndroid Build Coastguard Worker range <<= shift;
82*fb1b10abSAndroid Build Coastguard Worker count += shift;
83*fb1b10abSAndroid Build Coastguard Worker
84*fb1b10abSAndroid Build Coastguard Worker if (count >= 0) {
85*fb1b10abSAndroid Build Coastguard Worker int offset = shift - count;
86*fb1b10abSAndroid Build Coastguard Worker
87*fb1b10abSAndroid Build Coastguard Worker if (!br->error) {
88*fb1b10abSAndroid Build Coastguard Worker if ((lowvalue << (offset - 1)) & 0x80000000) {
89*fb1b10abSAndroid Build Coastguard Worker int x = (int)br->pos - 1;
90*fb1b10abSAndroid Build Coastguard Worker
91*fb1b10abSAndroid Build Coastguard Worker while (x >= 0 && br->buffer[x] == 0xff) {
92*fb1b10abSAndroid Build Coastguard Worker br->buffer[x] = 0;
93*fb1b10abSAndroid Build Coastguard Worker x--;
94*fb1b10abSAndroid Build Coastguard Worker }
95*fb1b10abSAndroid Build Coastguard Worker
96*fb1b10abSAndroid Build Coastguard Worker // TODO(wtc): How to prove x >= 0?
97*fb1b10abSAndroid Build Coastguard Worker br->buffer[x] += 1;
98*fb1b10abSAndroid Build Coastguard Worker }
99*fb1b10abSAndroid Build Coastguard Worker
100*fb1b10abSAndroid Build Coastguard Worker if (br->pos < br->size) {
101*fb1b10abSAndroid Build Coastguard Worker br->buffer[br->pos++] = (lowvalue >> (24 - offset)) & 0xff;
102*fb1b10abSAndroid Build Coastguard Worker } else {
103*fb1b10abSAndroid Build Coastguard Worker br->error = 1;
104*fb1b10abSAndroid Build Coastguard Worker }
105*fb1b10abSAndroid Build Coastguard Worker }
106*fb1b10abSAndroid Build Coastguard Worker lowvalue <<= offset;
107*fb1b10abSAndroid Build Coastguard Worker shift = count;
108*fb1b10abSAndroid Build Coastguard Worker lowvalue &= 0xffffff;
109*fb1b10abSAndroid Build Coastguard Worker count -= 8;
110*fb1b10abSAndroid Build Coastguard Worker }
111*fb1b10abSAndroid Build Coastguard Worker
112*fb1b10abSAndroid Build Coastguard Worker lowvalue <<= shift;
113*fb1b10abSAndroid Build Coastguard Worker br->count = count;
114*fb1b10abSAndroid Build Coastguard Worker br->lowvalue = lowvalue;
115*fb1b10abSAndroid Build Coastguard Worker br->range = range;
116*fb1b10abSAndroid Build Coastguard Worker }
117*fb1b10abSAndroid Build Coastguard Worker
vpx_write_bit(vpx_writer * w,int bit)118*fb1b10abSAndroid Build Coastguard Worker static INLINE void vpx_write_bit(vpx_writer *w, int bit) {
119*fb1b10abSAndroid Build Coastguard Worker vpx_write(w, bit, 128); // vpx_prob_half
120*fb1b10abSAndroid Build Coastguard Worker }
121*fb1b10abSAndroid Build Coastguard Worker
vpx_write_literal(vpx_writer * w,int data,int bits)122*fb1b10abSAndroid Build Coastguard Worker static INLINE void vpx_write_literal(vpx_writer *w, int data, int bits) {
123*fb1b10abSAndroid Build Coastguard Worker int bit;
124*fb1b10abSAndroid Build Coastguard Worker
125*fb1b10abSAndroid Build Coastguard Worker for (bit = bits - 1; bit >= 0; bit--) vpx_write_bit(w, 1 & (data >> bit));
126*fb1b10abSAndroid Build Coastguard Worker }
127*fb1b10abSAndroid Build Coastguard Worker
128*fb1b10abSAndroid Build Coastguard Worker #define vpx_write_prob(w, v) vpx_write_literal((w), (v), 8)
129*fb1b10abSAndroid Build Coastguard Worker
130*fb1b10abSAndroid Build Coastguard Worker #ifdef __cplusplus
131*fb1b10abSAndroid Build Coastguard Worker } // extern "C"
132*fb1b10abSAndroid Build Coastguard Worker #endif
133*fb1b10abSAndroid Build Coastguard Worker
134*fb1b10abSAndroid Build Coastguard Worker #endif // VPX_VPX_DSP_BITWRITER_H_
135