C++程序  |  428行  |  14.65 KB

/******************************************************************************
 *
 * 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_ */