aboutsummaryrefslogtreecommitdiff
path: root/encoder/ihevce_cabac.h
blob: 2cce81e2051b2c8a7c84b5a38b24f9db0f8db380 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
/******************************************************************************
 *
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *****************************************************************************
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/

/**
******************************************************************************
*
* @file ihevce_cabac.h
*
* @brief
*  This file contains encoder cabac engine related structures and
*  interface prototypes
*
* @author
*  ittiam
*
******************************************************************************
*/

#ifndef _IHEVCE_CABAC_H_
#define _IHEVCE_CABAC_H_

#include "ihevc_debug.h"
#include "ihevc_macros.h"

/*****************************************************************************/
/* Constant Macros                                                           */
/*****************************************************************************/
/**
*******************************************************************************
@brief Bit precision of cabac engine;
*******************************************************************************
 */
#define CABAC_BITS 9

/**
*******************************************************************************
@brief q format to account for the fractional bits encoded in cabac
*******************************************************************************
 */
#define CABAC_FRAC_BITS_Q 12

/**
*******************************************************************************
@brief Enables bit-efficient chroma cbf signalling by peeking into cbfs of
       children nodes
*******************************************************************************
 */
#define CABAC_BIT_EFFICIENT_CHROMA_PARENT_CBF 1

/*****************************************************************************/
/* Function Macros                                                           */
/*****************************************************************************/

/**
*******************************************************************************
@brief converts floating point number to CABAC_FRAC_BITS_Q q format and
       rounds the results to 16 bit integer
*******************************************************************************
 */
#define ROUND_Q12(x) ((UWORD16)(((x) * (1 << CABAC_FRAC_BITS_Q)) + 0.5))

/*****************************************************************************/
/* Enums                                                                     */
/*****************************************************************************/

/**
*******************************************************************************
@brief Enums for controlling the operating mode of cabac engine
*******************************************************************************
 */
typedef enum
{
    /** in this mode, bits are encoded in the bit stream buffer */
    CABAC_MODE_ENCODE_BITS = 0,

    /** in this mode, only num bits gen are computed but not put in the stream */
    CABAC_MODE_COMPUTE_BITS = 1

} CABAC_OP_MODE;

/*****************************************************************************/
/* Structures                                                                */
/*****************************************************************************/

/**
******************************************************************************
 *  @brief      Cabac context for encoder
******************************************************************************
 */
typedef struct cab_ctxt
{
    /**
     * indicates if cabac encode works in put bits mode or bit compute mode
     * In puts bits mode, bitstream and cabac engine fields L,R etc are used
     * In bit compute mode, bitstream and cabac engine fields are not used
     */
    CABAC_OP_MODE e_cabac_op_mode;

    /**
     * total bits estimated (for a cu) when mode is CABAC_MODE_COMPUTE_BITS
     * This is in q12 format to account for the fractional bits as well
     */
    UWORD32 u4_bits_estimated_q12;

    /**
     * total texture bits estimated (for a cu) when mode is CABAC_MODE_COMPUTE_BITS
     * This is in q12 format to account for the fractional bits as well
     */
    UWORD32 u4_texture_bits_estimated_q12;

    /**
     * total header bits estimated (for a cu) when mode is CABAC_MODE_COMPUTE_BITS
     * This is in q12 format to account for the fractional bits as well
     */
    UWORD32 u4_header_bits_estimated_q12;

    UWORD32 u4_cbf_bits_q12;

    UWORD32 u4_true_tu_split_flag_q12;
    /*********************************************************************/
    /*  CABAC ENGINE related fields; not used in CABAC_MODE_COMPUTE_BITS */
    /*********************************************************************/
    /** cabac interval range R  */
    UWORD32 u4_range;

    /** cabac interval start L  */
    UWORD32 u4_low;

    /** bits generated during renormalization
     *  A byte is put to stream/u4_out_standing_bytes from u4_low(L) when
     *  u4_bits_gen exceeds 8
     */
    UWORD32 u4_bits_gen;

    /** bytes_outsanding; number of 0xFF bits that occur during renorm
     *  These  will be accumulated till the carry bit is knwon
     */
    UWORD32 u4_out_standing_bytes;

    /*************************************************************************/
    /*  OUTPUT Bitstream related fields; not used in CABAC_MODE_COMPUTE_BITS */
    /*************************************************************************/
    /** points to start of stream buffer.    */
    UWORD8 *pu1_strm_buffer;

    /**
     *  max bitstream size (in bytes).
     *  Encoded stream shall not exceed this size.
     */
    UWORD32 u4_max_strm_size;

    /**
    `*  byte offset (w.r.t pu1_strm_buffer) where next byte would be written
     *  Bitstream engine makes sure it would not corrupt data beyond
     *  u4_max_strm_size bytes
     */
    UWORD32 u4_strm_buf_offset;

    /**
     *  signifies the number of consecutive zero bytes propogated from previous
     *  word. It is used for emulation prevention byte insertion in the stream
     */
    WORD32 i4_zero_bytes_run;

    /*********************************************************************/
    /*  CABAC context models                                             */
    /*********************************************************************/
    /** All Context models stored in packed form pState[bits6-1] | MPS[bit0] */
    UWORD8 au1_ctxt_models[IHEVC_CAB_CTXT_END];

    /**
     *Cabac context for start of every row which is same as top right ctxt
     */
    UWORD8 au1_ctxt_models_top_right[IHEVC_CAB_CTXT_END];

    /**
     * copy of enable entropy coding sync flag in pps
     */
    WORD8 i1_entropy_coding_sync_enabled_flag;

    /**
     * store the bitstream offset from which first slice data is generated by cabac
     */
    UWORD32 u4_first_slice_start_offset;

} cab_ctxt_t;

/*****************************************************************************/
/* Globals                                                                   */
/*****************************************************************************/
extern UWORD16 gau2_ihevce_cabac_bin_to_bits[64 * 2];

/*****************************************************************************/
/* Extern Function Declarations                                              */
/*****************************************************************************/
WORD32
    ihevce_cabac_reset(cab_ctxt_t *ps_cabac, bitstrm_t *ps_bitstrm, CABAC_OP_MODE e_cabac_op_mode);

WORD32 ihevce_cabac_init(
    cab_ctxt_t *ps_cabac,
    bitstrm_t *ps_bitstrm,
    WORD32 slice_qp,
    WORD32 cabac_init_idc,
    CABAC_OP_MODE e_cabac_op_mode);

WORD32 ihevce_cabac_put_byte(cab_ctxt_t *ps_cabac);

/**
******************************************************************************
*
*  @brief Codes a bin based on probablilty and mps packed context model
*
*  @par   Description
*  1. Apart from encoding bin, context model is updated as per state transition
*  2. Range and Low renormalization is done based on bin and original state
*  3. After renorm bistream is updated (if required)
*
*  @param[inout]   ps_cabac
*  pointer to cabac context (handle)
*
*  @param[in]   bin
*  bin(boolean) to be encoded
*
*  @param[in]   ctxt_index
*  index of cabac context model containing pState[bits6-1] | MPS[bit0]
*
*  @return      success or failure error code
*
******************************************************************************
*/
static INLINE WORD32 ihevce_cabac_encode_bin(cab_ctxt_t *ps_cabac, WORD32 bin, WORD32 ctxt_index)
{
    UWORD32 u4_range = ps_cabac->u4_range;
    UWORD32 u4_low = ps_cabac->u4_low;
    UWORD32 u4_rlps;
    UWORD8 *pu1_ctxt_model = &ps_cabac->au1_ctxt_models[ctxt_index];
    WORD32 state_mps = *pu1_ctxt_model;
    WORD32 shift;

    /* Sanity checks */
    ASSERT((bin == 0) || (bin == 1));
    ASSERT((ctxt_index >= 0) && (ctxt_index < IHEVC_CAB_CTXT_END));
    ASSERT(state_mps < 128);

    if(CABAC_MODE_ENCODE_BITS == ps_cabac->e_cabac_op_mode)
    {
        ASSERT((u4_range >= 256) && (u4_range < 512));

        /* Get the lps range from LUT based on quantized range and state */
        u4_rlps = gau1_ihevc_cabac_rlps[state_mps >> 1][(u4_range >> 6) & 0x3];

        u4_range -= u4_rlps;

        /* check if bin is mps or lps */
        if((state_mps & 0x1) ^ bin)
        {
            /* lps path;  L= L + R; R = RLPS */
            u4_low += u4_range;
            u4_range = u4_rlps;
        }

        /*Compute bit always to populate the trace*/
        /* increment bits generated based on state and bin encoded */
        ps_cabac->u4_bits_estimated_q12 += gau2_ihevce_cabac_bin_to_bits[state_mps ^ bin];

        /* update the context model from state transition LUT */
        *pu1_ctxt_model = gau1_ihevc_next_state[(state_mps << 1) | bin];

        /*****************************************************************/
        /* Renormalization; calculate bits generated based on range(R)   */
        /* Note : 6 <= R < 512; R is 2 only for terminating encode       */
        /*****************************************************************/
        GETRANGE(shift, u4_range);
        shift = 9 - shift;
        u4_low <<= shift;
        u4_range <<= shift;

        /* bits to be inserted in the bitstream */
        ps_cabac->u4_bits_gen += shift;
        ps_cabac->u4_range = u4_range;
        ps_cabac->u4_low = u4_low;

        /* generate stream when a byte is ready */
        if(ps_cabac->u4_bits_gen > CABAC_BITS)
        {
            return (ihevce_cabac_put_byte(ps_cabac));
        }
    }
    else /* (CABAC_MODE_COMPUTE_BITS == e_cabac_op_mode) */
    {
        /* increment bits generated based on state and bin encoded */
        ps_cabac->u4_bits_estimated_q12 += gau2_ihevce_cabac_bin_to_bits[state_mps ^ bin];

        /* update the context model from state transition LUT */
        *pu1_ctxt_model = gau1_ihevc_next_state[(state_mps << 1) | bin];
    }

    return (IHEVCE_SUCCESS);
}

WORD32 ihevce_cabac_encode_bypass_bin(cab_ctxt_t *ps_cabac, WORD32 bin);

WORD32
    ihevce_cabac_encode_terminate(cab_ctxt_t *ps_cabac, WORD32 term_bin, WORD32 i4_end_of_sub_strm);

/**
******************************************************************************
*
*  @brief Encodes a series of bypass bins (FLC bypass bins)
*
*  @par   Description
*  This function is more optimal than calling ihevce_cabac_encode_bypass_bin()
*  in a loop as cabac low, renorm and generating the stream (8bins at a time)
*  can be done in one operation
*
*  @param[inout]ps_cabac
*   pointer to cabac context (handle)
*
*  @param[in]   u4_sym
*   syntax element to be coded (as FLC bins)
*
*  @param[in]   num_bins
*   This is the FLC length for u4_sym
*
*
*  @return      success or failure error code
*
******************************************************************************
*/
static INLINE WORD32
    ihevce_cabac_encode_bypass_bins(cab_ctxt_t *ps_cabac, UWORD32 u4_bins, WORD32 num_bins)
{
    UWORD32 u4_range = ps_cabac->u4_range;
    WORD32 next_byte;
    WORD32 error = IHEVCE_SUCCESS;

    if(CABAC_MODE_ENCODE_BITS == ps_cabac->e_cabac_op_mode)
    {
        /* Sanity checks */
        ASSERT((num_bins < 33) && (num_bins > 0));
        ASSERT((u4_range >= 256) && (u4_range < 512));

        /*Compute bit always to populate the trace*/
        /* increment bits generated by num_bins */
        ps_cabac->u4_bits_estimated_q12 += (num_bins << CABAC_FRAC_BITS_Q);

        /* Encode 8bins at a time and put in the bit-stream */
        while(num_bins > 8)
        {
            num_bins -= 8;

            /* extract the leading 8 bins */
            next_byte = (u4_bins >> num_bins) & 0xff;

            /*  L = (L << 8) +  (R * next_byte) */
            ps_cabac->u4_low <<= 8;
            ps_cabac->u4_low += (next_byte * u4_range);
            ps_cabac->u4_bits_gen += 8;

            if(ps_cabac->u4_bits_gen > CABAC_BITS)
            {
                /*  insert the leading byte of low into stream */
                error |= ihevce_cabac_put_byte(ps_cabac);
            }
        }

        /* Update low with remaining bins and return */
        next_byte = (u4_bins & ((1 << num_bins) - 1));

        ps_cabac->u4_low <<= num_bins;
        ps_cabac->u4_low += (next_byte * u4_range);
        ps_cabac->u4_bits_gen += num_bins;

        if(ps_cabac->u4_bits_gen > CABAC_BITS)
        {
            /*  insert the leading byte of low into stream */
            error |= ihevce_cabac_put_byte(ps_cabac);
        }
    }
    else
    {
        /* increment bits generated by num_bins */
        ps_cabac->u4_bits_estimated_q12 += (num_bins << CABAC_FRAC_BITS_Q);
    }

    return (error);
}

WORD32 ihevce_cabac_encode_tunary(
    cab_ctxt_t *ps_cabac,
    WORD32 sym,
    WORD32 c_max,
    WORD32 ctxt_index,
    WORD32 ctxt_shift,
    WORD32 ctxt_inc_max);

WORD32 ihevce_cabac_encode_tunary_bypass(cab_ctxt_t *ps_cabac, WORD32 sym, WORD32 c_max);

WORD32 ihevce_cabac_encode_egk(cab_ctxt_t *ps_cabac, UWORD32 u4_sym, WORD32 k);

WORD32 ihevce_cabac_encode_trunc_rice(
    cab_ctxt_t *ps_cabac, UWORD32 u4_sym, WORD32 c_rice_param, WORD32 c_rice_max);

WORD32 ihevce_cabac_flush(cab_ctxt_t *ps_cabac, WORD32 i4_end_of_sub_strm);

WORD32 ihevce_cabac_ctxt_backup(cab_ctxt_t *ps_cabac);

WORD32 ihevce_cabac_ctxt_row_init(cab_ctxt_t *ps_cabac);

#endif /* _IHEVCE_CABAC_H_ */