xref: /rockchip-linux_mpp/mpp/base/mpp_bitwrite.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1*437bfbebSnyanmisaka /*
2*437bfbebSnyanmisaka  * Copyright 2015 - 2017 Rockchip Electronics Co. LTD
3*437bfbebSnyanmisaka  *
4*437bfbebSnyanmisaka  * Licensed under the Apache License, Version 2.0 (the "License");
5*437bfbebSnyanmisaka  * you may not use this file except in compliance with the License.
6*437bfbebSnyanmisaka  * You may obtain a copy of the License at
7*437bfbebSnyanmisaka  *
8*437bfbebSnyanmisaka  *      http://www.apache.org/licenses/LICENSE-2.0
9*437bfbebSnyanmisaka  *
10*437bfbebSnyanmisaka  * Unless required by applicable law or agreed to in writing, software
11*437bfbebSnyanmisaka  * distributed under the License is distributed on an "AS IS" BASIS,
12*437bfbebSnyanmisaka  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*437bfbebSnyanmisaka  * See the License for the specific language governing permissions and
14*437bfbebSnyanmisaka  * limitations under the License.
15*437bfbebSnyanmisaka  */
16*437bfbebSnyanmisaka 
17*437bfbebSnyanmisaka #include "mpp_mem.h"
18*437bfbebSnyanmisaka #include "mpp_debug.h"
19*437bfbebSnyanmisaka 
20*437bfbebSnyanmisaka #include "mpp_bitwrite.h"
21*437bfbebSnyanmisaka 
mpp_writer_status(MppWriteCtx * ctx)22*437bfbebSnyanmisaka MPP_RET mpp_writer_status(MppWriteCtx *ctx)
23*437bfbebSnyanmisaka {
24*437bfbebSnyanmisaka     if (ctx->byte_cnt > ctx->size) {
25*437bfbebSnyanmisaka         ctx->overflow = 1;
26*437bfbebSnyanmisaka         return MPP_NOK;
27*437bfbebSnyanmisaka     }
28*437bfbebSnyanmisaka 
29*437bfbebSnyanmisaka     return MPP_OK;
30*437bfbebSnyanmisaka }
31*437bfbebSnyanmisaka 
mpp_writer_reset(MppWriteCtx * ctx)32*437bfbebSnyanmisaka MPP_RET mpp_writer_reset(MppWriteCtx *ctx)
33*437bfbebSnyanmisaka {
34*437bfbebSnyanmisaka     ctx->stream = ctx->buffer;
35*437bfbebSnyanmisaka     ctx->byte_cnt = 0;
36*437bfbebSnyanmisaka     ctx->byte_buffer = 0;
37*437bfbebSnyanmisaka     ctx->buffered_bits = 0;
38*437bfbebSnyanmisaka     ctx->zero_bytes = 0;
39*437bfbebSnyanmisaka     ctx->overflow = 0;
40*437bfbebSnyanmisaka     ctx->emul_cnt = 0;
41*437bfbebSnyanmisaka 
42*437bfbebSnyanmisaka     return MPP_OK;
43*437bfbebSnyanmisaka }
44*437bfbebSnyanmisaka 
mpp_writer_init(MppWriteCtx * ctx,void * p,RK_S32 size)45*437bfbebSnyanmisaka MPP_RET mpp_writer_init(MppWriteCtx *ctx, void *p, RK_S32 size)
46*437bfbebSnyanmisaka {
47*437bfbebSnyanmisaka     MPP_RET ret;
48*437bfbebSnyanmisaka 
49*437bfbebSnyanmisaka     ctx->buffer = p;
50*437bfbebSnyanmisaka     ctx->stream = p;
51*437bfbebSnyanmisaka     ctx->size = size;
52*437bfbebSnyanmisaka     ctx->byte_cnt = 0;
53*437bfbebSnyanmisaka     ctx->overflow = 0;
54*437bfbebSnyanmisaka     ctx->byte_buffer = 0;
55*437bfbebSnyanmisaka     ctx->buffered_bits = 0;
56*437bfbebSnyanmisaka     ctx->zero_bytes = 0;
57*437bfbebSnyanmisaka     ctx->emul_cnt = 0;
58*437bfbebSnyanmisaka 
59*437bfbebSnyanmisaka     ret = mpp_writer_status(ctx);
60*437bfbebSnyanmisaka     if (ret)
61*437bfbebSnyanmisaka         mpp_err_f("failed to init with overflow config\n");
62*437bfbebSnyanmisaka 
63*437bfbebSnyanmisaka     return ret;
64*437bfbebSnyanmisaka }
65*437bfbebSnyanmisaka 
mpp_writer_put_raw_bits(MppWriteCtx * ctx,RK_S32 val,RK_S32 len)66*437bfbebSnyanmisaka void mpp_writer_put_raw_bits(MppWriteCtx *ctx, RK_S32 val, RK_S32 len)
67*437bfbebSnyanmisaka {
68*437bfbebSnyanmisaka     RK_S32 bits;
69*437bfbebSnyanmisaka     RK_U32 byte_buffer = ctx->byte_buffer;
70*437bfbebSnyanmisaka     RK_U8*stream = ctx->stream;
71*437bfbebSnyanmisaka 
72*437bfbebSnyanmisaka     if (mpp_writer_status(ctx))
73*437bfbebSnyanmisaka         return;
74*437bfbebSnyanmisaka 
75*437bfbebSnyanmisaka     mpp_assert(val < (1 << len));
76*437bfbebSnyanmisaka     mpp_assert(len < 25);
77*437bfbebSnyanmisaka 
78*437bfbebSnyanmisaka     bits = len + ctx->buffered_bits;
79*437bfbebSnyanmisaka     val <<= (32 - bits);
80*437bfbebSnyanmisaka     byte_buffer = byte_buffer | val;
81*437bfbebSnyanmisaka 
82*437bfbebSnyanmisaka     while (bits > 7) {
83*437bfbebSnyanmisaka         *stream = (RK_U8)(byte_buffer >> 24);
84*437bfbebSnyanmisaka 
85*437bfbebSnyanmisaka         bits -= 8;
86*437bfbebSnyanmisaka         byte_buffer <<= 8;
87*437bfbebSnyanmisaka         stream++;
88*437bfbebSnyanmisaka         ctx->byte_cnt++;
89*437bfbebSnyanmisaka     }
90*437bfbebSnyanmisaka 
91*437bfbebSnyanmisaka     ctx->byte_buffer = byte_buffer;
92*437bfbebSnyanmisaka     ctx->buffered_bits = (RK_U8)bits;
93*437bfbebSnyanmisaka     ctx->stream = stream;
94*437bfbebSnyanmisaka 
95*437bfbebSnyanmisaka     return;
96*437bfbebSnyanmisaka }
97*437bfbebSnyanmisaka 
mpp_writer_flush(MppWriteCtx * ctx)98*437bfbebSnyanmisaka void mpp_writer_flush(MppWriteCtx *ctx)
99*437bfbebSnyanmisaka {
100*437bfbebSnyanmisaka     RK_U32 byte_buffer = ctx->byte_buffer;
101*437bfbebSnyanmisaka     RK_U8*stream = ctx->stream;
102*437bfbebSnyanmisaka 
103*437bfbebSnyanmisaka     if (mpp_writer_status(ctx))
104*437bfbebSnyanmisaka         return;
105*437bfbebSnyanmisaka 
106*437bfbebSnyanmisaka     if (ctx->buffered_bits)
107*437bfbebSnyanmisaka         *stream = (RK_U8)(byte_buffer >> 24);
108*437bfbebSnyanmisaka 
109*437bfbebSnyanmisaka     return;
110*437bfbebSnyanmisaka }
111*437bfbebSnyanmisaka 
mpp_writer_put_bits(MppWriteCtx * ctx,RK_S32 val,RK_S32 len)112*437bfbebSnyanmisaka void mpp_writer_put_bits(MppWriteCtx * ctx, RK_S32 val, RK_S32 len)
113*437bfbebSnyanmisaka {
114*437bfbebSnyanmisaka     RK_S32 bits;
115*437bfbebSnyanmisaka     RK_U8 *stream = ctx->stream;
116*437bfbebSnyanmisaka     RK_U32 byte_buffer = ctx->byte_buffer;
117*437bfbebSnyanmisaka 
118*437bfbebSnyanmisaka     if (val) {
119*437bfbebSnyanmisaka         mpp_assert(val < (1 << len));
120*437bfbebSnyanmisaka         mpp_assert(len < 25);
121*437bfbebSnyanmisaka     }
122*437bfbebSnyanmisaka     bits = len + ctx->buffered_bits;
123*437bfbebSnyanmisaka 
124*437bfbebSnyanmisaka     byte_buffer = byte_buffer | ((RK_U32) val << (32 - bits));
125*437bfbebSnyanmisaka 
126*437bfbebSnyanmisaka     while (bits > 7) {
127*437bfbebSnyanmisaka         RK_S32 zeroBytes = ctx->zero_bytes;
128*437bfbebSnyanmisaka         RK_S32 byteCnt = ctx->byte_cnt;
129*437bfbebSnyanmisaka 
130*437bfbebSnyanmisaka         if (mpp_writer_status(ctx))
131*437bfbebSnyanmisaka             return;
132*437bfbebSnyanmisaka 
133*437bfbebSnyanmisaka         *stream = (RK_U8) (byte_buffer >> 24);
134*437bfbebSnyanmisaka 
135*437bfbebSnyanmisaka         byteCnt++;
136*437bfbebSnyanmisaka         if ((zeroBytes == 2) && (*stream < 4)) {
137*437bfbebSnyanmisaka             *stream++ = 3;
138*437bfbebSnyanmisaka             *stream = (RK_U8) (byte_buffer >> 24);
139*437bfbebSnyanmisaka             byteCnt++;
140*437bfbebSnyanmisaka             zeroBytes = 0;
141*437bfbebSnyanmisaka             ctx->emul_cnt++;
142*437bfbebSnyanmisaka         }
143*437bfbebSnyanmisaka 
144*437bfbebSnyanmisaka         if (*stream == 0)
145*437bfbebSnyanmisaka             zeroBytes++;
146*437bfbebSnyanmisaka         else
147*437bfbebSnyanmisaka             zeroBytes = 0;
148*437bfbebSnyanmisaka 
149*437bfbebSnyanmisaka         bits -= 8;
150*437bfbebSnyanmisaka         byte_buffer <<= 8;
151*437bfbebSnyanmisaka         stream++;
152*437bfbebSnyanmisaka         ctx->zero_bytes = zeroBytes;
153*437bfbebSnyanmisaka         ctx->byte_cnt = byteCnt;
154*437bfbebSnyanmisaka         ctx->stream = stream;
155*437bfbebSnyanmisaka     }
156*437bfbebSnyanmisaka 
157*437bfbebSnyanmisaka     ctx->buffered_bits = (RK_U8) bits;
158*437bfbebSnyanmisaka     ctx->byte_buffer = byte_buffer;
159*437bfbebSnyanmisaka }
160*437bfbebSnyanmisaka 
mpp_writer_align_zero(MppWriteCtx * ctx)161*437bfbebSnyanmisaka void mpp_writer_align_zero(MppWriteCtx *ctx)
162*437bfbebSnyanmisaka {
163*437bfbebSnyanmisaka     if (ctx->buffered_bits)
164*437bfbebSnyanmisaka         mpp_writer_put_raw_bits(ctx, 0, 8 - ctx->buffered_bits);
165*437bfbebSnyanmisaka }
166*437bfbebSnyanmisaka 
mpp_writer_align_one(MppWriteCtx * ctx)167*437bfbebSnyanmisaka void mpp_writer_align_one(MppWriteCtx *ctx)
168*437bfbebSnyanmisaka {
169*437bfbebSnyanmisaka     if (ctx->buffered_bits) {
170*437bfbebSnyanmisaka         RK_S32 len = 8 - ctx->buffered_bits;
171*437bfbebSnyanmisaka 
172*437bfbebSnyanmisaka         mpp_writer_put_raw_bits(ctx, (1 << len) - 1, len);
173*437bfbebSnyanmisaka     }
174*437bfbebSnyanmisaka }
175*437bfbebSnyanmisaka 
mpp_writer_trailing(MppWriteCtx * ctx)176*437bfbebSnyanmisaka void mpp_writer_trailing(MppWriteCtx *ctx)
177*437bfbebSnyanmisaka {
178*437bfbebSnyanmisaka     mpp_writer_put_bits(ctx, 1, 1);
179*437bfbebSnyanmisaka     if (ctx->buffered_bits)
180*437bfbebSnyanmisaka         mpp_writer_put_bits(ctx, 0, 8 - ctx->buffered_bits);
181*437bfbebSnyanmisaka }
182*437bfbebSnyanmisaka 
mpp_writer_put_ue(MppWriteCtx * ctx,RK_U32 val)183*437bfbebSnyanmisaka void mpp_writer_put_ue(MppWriteCtx *ctx, RK_U32 val)
184*437bfbebSnyanmisaka {
185*437bfbebSnyanmisaka     RK_U32 num_bits = 0;
186*437bfbebSnyanmisaka 
187*437bfbebSnyanmisaka     val++;
188*437bfbebSnyanmisaka     while (val >> ++num_bits);
189*437bfbebSnyanmisaka 
190*437bfbebSnyanmisaka     if (num_bits > 12) {
191*437bfbebSnyanmisaka         RK_U32 tmp;
192*437bfbebSnyanmisaka 
193*437bfbebSnyanmisaka         tmp = num_bits - 1;
194*437bfbebSnyanmisaka 
195*437bfbebSnyanmisaka         if (tmp > 24) {
196*437bfbebSnyanmisaka             tmp -= 24;
197*437bfbebSnyanmisaka             mpp_writer_put_bits(ctx, 0, 24);
198*437bfbebSnyanmisaka         }
199*437bfbebSnyanmisaka 
200*437bfbebSnyanmisaka         mpp_writer_put_bits(ctx, 0, tmp);
201*437bfbebSnyanmisaka 
202*437bfbebSnyanmisaka         if (num_bits > 24) {
203*437bfbebSnyanmisaka             num_bits -= 24;
204*437bfbebSnyanmisaka             mpp_writer_put_bits(ctx, val >> num_bits, 24);
205*437bfbebSnyanmisaka             val = val >> num_bits;
206*437bfbebSnyanmisaka         }
207*437bfbebSnyanmisaka 
208*437bfbebSnyanmisaka         mpp_writer_put_bits(ctx, val, num_bits);
209*437bfbebSnyanmisaka     } else {
210*437bfbebSnyanmisaka         mpp_writer_put_bits(ctx, val, 2 * num_bits - 1);
211*437bfbebSnyanmisaka     }
212*437bfbebSnyanmisaka }
213*437bfbebSnyanmisaka 
mpp_writer_put_se(MppWriteCtx * ctx,RK_S32 val)214*437bfbebSnyanmisaka void mpp_writer_put_se(MppWriteCtx *ctx, RK_S32 val)
215*437bfbebSnyanmisaka {
216*437bfbebSnyanmisaka     RK_U32 tmp;
217*437bfbebSnyanmisaka 
218*437bfbebSnyanmisaka     if (val > 0)
219*437bfbebSnyanmisaka         tmp = (RK_U32)(2 * val - 1);
220*437bfbebSnyanmisaka     else
221*437bfbebSnyanmisaka         tmp = (RK_U32)(-2 * val);
222*437bfbebSnyanmisaka 
223*437bfbebSnyanmisaka     mpp_writer_put_ue(ctx, tmp);
224*437bfbebSnyanmisaka }
225*437bfbebSnyanmisaka 
mpp_writer_bytes(MppWriteCtx * ctx)226*437bfbebSnyanmisaka RK_S32 mpp_writer_bytes(MppWriteCtx *ctx)
227*437bfbebSnyanmisaka {
228*437bfbebSnyanmisaka     return ctx->byte_cnt + (ctx->buffered_bits > 0);
229*437bfbebSnyanmisaka }
230*437bfbebSnyanmisaka 
mpp_writer_bits(MppWriteCtx * ctx)231*437bfbebSnyanmisaka RK_S32 mpp_writer_bits(MppWriteCtx *ctx)
232*437bfbebSnyanmisaka {
233*437bfbebSnyanmisaka     return ctx->byte_cnt * 8 + ctx->buffered_bits;
234*437bfbebSnyanmisaka }
235*437bfbebSnyanmisaka 
mpp_exp_golomb_signed(RK_S32 val)236*437bfbebSnyanmisaka RK_S32 mpp_exp_golomb_signed(RK_S32 val)
237*437bfbebSnyanmisaka {
238*437bfbebSnyanmisaka     RK_S32 tmp = 0;
239*437bfbebSnyanmisaka 
240*437bfbebSnyanmisaka     if (val > 0)
241*437bfbebSnyanmisaka         val = 2 * val;
242*437bfbebSnyanmisaka     else
243*437bfbebSnyanmisaka         val = -2 * val + 1;
244*437bfbebSnyanmisaka 
245*437bfbebSnyanmisaka     while (val >> ++tmp)
246*437bfbebSnyanmisaka         ;
247*437bfbebSnyanmisaka 
248*437bfbebSnyanmisaka     return tmp * 2 - 1;
249*437bfbebSnyanmisaka }
250