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