You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
428 lines
15 KiB
428 lines
15 KiB
/******************************************************************************
|
|
*
|
|
* 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_ */
|