Instead of using hard coded address offsets, defined structures to access MB Header for each MB type This improves readability of the code Also helps in maintaining required alignment for MV MV elements need to be aligned to 2 byte boundary Unaligned accesses result in undefined behavior Bug: 33073518 Test: Tested with -fsanitize=alignment enabled on avcenc Change-Id: I51c009b7deded76315a4bf2880444d21ae7d517f
1803 lines
60 KiB
C
1803 lines
60 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2015 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
|
|
* ih264e_cavlc.c
|
|
*
|
|
* @brief
|
|
* Contains all the routines to code syntax elements and residuals when entropy
|
|
* coding chosen is CAVLC
|
|
*
|
|
* @author
|
|
* ittiam
|
|
*
|
|
* @par List of Functions:
|
|
* - ih264e_compute_zeroruns_and_trailingones()
|
|
* - ih264e_write_coeff4x4_cavlc()
|
|
* - ih264e_write_coeff8x8_cavlc()
|
|
* - ih264e_encode_residue()
|
|
* - ih264e_write_islice_mb_cavlc()
|
|
* - ih264e_write_pslice_mb_cavlc()
|
|
*
|
|
* @remarks
|
|
* None
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
|
|
/*****************************************************************************/
|
|
/* File Includes */
|
|
/*****************************************************************************/
|
|
|
|
/* System include files */
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <limits.h>
|
|
|
|
/* User include files */
|
|
#include "ih264e_config.h"
|
|
#include "ih264_typedefs.h"
|
|
#include "iv2.h"
|
|
#include "ive2.h"
|
|
#include "ih264_debug.h"
|
|
#include "ih264_macros.h"
|
|
#include "ih264_defs.h"
|
|
#include "ih264e_defs.h"
|
|
#include "ih264e_error.h"
|
|
#include "ih264e_bitstream.h"
|
|
#include "ime_distortion_metrics.h"
|
|
#include "ime_defs.h"
|
|
#include "ime_structs.h"
|
|
#include "ih264_error.h"
|
|
#include "ih264_structs.h"
|
|
#include "ih264_trans_quant_itrans_iquant.h"
|
|
#include "ih264_inter_pred_filters.h"
|
|
#include "ih264_mem_fns.h"
|
|
#include "ih264_padding.h"
|
|
#include "ih264_intra_pred_filters.h"
|
|
#include "ih264_deblk_edge_filters.h"
|
|
#include "ih264_cabac_tables.h"
|
|
#include "irc_cntrl_param.h"
|
|
#include "irc_frame_info_collector.h"
|
|
#include "ih264e_rate_control.h"
|
|
#include "ih264e_cabac_structs.h"
|
|
#include "ih264e_structs.h"
|
|
#include "ih264e_encode_header.h"
|
|
#include "ih264_cavlc_tables.h"
|
|
#include "ih264e_cavlc.h"
|
|
#include "ih264e_statistics.h"
|
|
#include "ih264e_trace.h"
|
|
|
|
/*****************************************************************************/
|
|
/* Function Definitions */
|
|
/*****************************************************************************/
|
|
|
|
/**
|
|
*******************************************************************************
|
|
*
|
|
* @brief
|
|
* This function computes run of zero, number of trailing ones and sign of
|
|
* trailing ones basing on the significant coeff map, residual block and
|
|
* total nnz.
|
|
*
|
|
* @param[in] pi2_res_block
|
|
* Pointer to residual block containing levels in scan order
|
|
*
|
|
* @param[in] u4_total_coeff
|
|
* Total non-zero coefficients in that sub block
|
|
*
|
|
* @param[in] pu1_zero_run
|
|
* Pointer to array to store run of zeros
|
|
*
|
|
* @param[in] u4_sig_coeff_map
|
|
* significant coefficient map
|
|
*
|
|
* @returns u4_totzero_sign_trailone
|
|
* Bits 0-8 contains number of trailing ones.
|
|
* Bits 8-16 contains bitwise sign information of trailing one
|
|
* Bits 16-24 contains total number of zeros.
|
|
*
|
|
* @remarks
|
|
* None
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
static UWORD32 ih264e_compute_zeroruns_and_trailingones(WORD16 *pi2_res_block,
|
|
UWORD32 u4_total_coeff,
|
|
UWORD8 *pu1_zero_run,
|
|
UWORD32 u4_sig_coeff_map)
|
|
{
|
|
UWORD32 i = 0;
|
|
UWORD32 u4_nnz_coeff = 0;
|
|
WORD32 i4_run = -1;
|
|
UWORD32 u4_sign = 0;
|
|
UWORD32 u4_tot_zero = 0;
|
|
UWORD32 u4_trailing1 = 0;
|
|
WORD32 i4_val;
|
|
UWORD32 u4_totzero_sign_trailone;
|
|
UWORD32 *pu4_zero_run;
|
|
|
|
pu4_zero_run = (void *)pu1_zero_run;
|
|
pu4_zero_run[0] = 0;
|
|
pu4_zero_run[1] = 0;
|
|
pu4_zero_run[2] = 0;
|
|
pu4_zero_run[3] = 0;
|
|
|
|
/* Compute Runs of zeros for all nnz coefficients except the last 3 */
|
|
if (u4_total_coeff > 3)
|
|
{
|
|
for (i = 0; u4_nnz_coeff < (u4_total_coeff-3); i++)
|
|
{
|
|
i4_run++;
|
|
|
|
i4_val = (u4_sig_coeff_map & 0x1);
|
|
u4_sig_coeff_map >>= 1;
|
|
|
|
if (i4_val != 0)
|
|
{
|
|
pu1_zero_run[u4_nnz_coeff++] = i4_run;
|
|
i4_run = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Compute T1's, Signof(T1's) and Runs of zeros for the last 3 */
|
|
while (u4_nnz_coeff != u4_total_coeff)
|
|
{
|
|
i4_run++;
|
|
|
|
i4_val = (u4_sig_coeff_map & 0x1);
|
|
u4_sig_coeff_map >>= 1;
|
|
|
|
if (i4_val != 0)
|
|
{
|
|
if (pi2_res_block[u4_nnz_coeff] == 1)
|
|
{
|
|
pu1_zero_run[u4_nnz_coeff] = i4_run;
|
|
u4_trailing1++;
|
|
}
|
|
else
|
|
{
|
|
if (pi2_res_block[u4_nnz_coeff] == -1)
|
|
{
|
|
pu1_zero_run[u4_nnz_coeff] = i4_run;
|
|
u4_sign |= 1 << u4_trailing1;
|
|
u4_trailing1++;
|
|
}
|
|
else
|
|
{
|
|
pu1_zero_run[u4_nnz_coeff] = i4_run;
|
|
u4_trailing1 = 0;
|
|
u4_sign = 0;
|
|
}
|
|
}
|
|
i4_run = -1;
|
|
u4_nnz_coeff++;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
u4_tot_zero = i - u4_total_coeff;
|
|
u4_totzero_sign_trailone = (u4_tot_zero << 16)|(u4_sign << 8)|u4_trailing1;
|
|
|
|
return (u4_totzero_sign_trailone);
|
|
}
|
|
|
|
/**
|
|
*******************************************************************************
|
|
*
|
|
* @brief
|
|
* This function generates CAVLC coded bit stream for the given residual block
|
|
*
|
|
* @param[in] pi2_res_block
|
|
* Pointer to residual block containing levels in scan order
|
|
*
|
|
* @param[in] u4_total_coeff
|
|
* Total non-zero coefficients in the sub block
|
|
*
|
|
* @param[in] u4_block_type
|
|
* block type
|
|
*
|
|
* @param[in] pu1_zero_run
|
|
* Pointer to array to store run of zeros
|
|
*
|
|
* @param[in] u4_nc
|
|
* average of non zero coeff from top and left blocks (when available)
|
|
*
|
|
* @param[in, out] ps_bit_stream
|
|
* structure pointing to a buffer holding output bit stream
|
|
*
|
|
* @param[in] u4_sig_coeff_map
|
|
* significant coefficient map of the residual block
|
|
*
|
|
* @returns
|
|
* error code
|
|
*
|
|
* @remarks
|
|
* If the block type is CAVLC_CHROMA_4x4_DC, then u4_nc is non-significant
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
static IH264E_ERROR_T ih264e_write_coeff4x4_cavlc(WORD16 *pi2_res_block,
|
|
UWORD32 u4_total_coeff,
|
|
ENTROPY_BLK_TYPE u4_block_type,
|
|
UWORD8 *pu1_zero_run,
|
|
UWORD32 u4_nc,
|
|
bitstrm_t *ps_bit_stream,
|
|
UWORD32 u4_sig_coeff_map)
|
|
{
|
|
IH264E_ERROR_T error_status = IH264E_SUCCESS;
|
|
UWORD32 u4_totzero_sign_trailone = 0;
|
|
UWORD32 u4_trailing_ones = 0;
|
|
UWORD32 u4_tot_zeros = 0;
|
|
UWORD32 u4_remaining_coeff = 0;
|
|
UWORD32 u4_sign1 = 0;
|
|
UWORD32 u4_max_num_coeff = 0;
|
|
const UWORD32 au4_max_num_nnz_coeff[] = {16, 15, 16, 4, 15};
|
|
|
|
/* validate inputs */
|
|
ASSERT(u4_block_type <= CAVLC_CHROMA_4x4_AC);
|
|
|
|
u4_max_num_coeff = au4_max_num_nnz_coeff[u4_block_type];
|
|
|
|
ASSERT(u4_total_coeff <= u4_max_num_coeff);
|
|
|
|
if (!u4_total_coeff)
|
|
{
|
|
UWORD32 u4_codeword = 15;
|
|
UWORD32 u4_codesize = 1;
|
|
if (u4_block_type == CAVLC_CHROMA_4x4_DC)
|
|
{
|
|
u4_codeword = 1;
|
|
u4_codesize = 2;
|
|
DEBUG("\n[%d numcoeff, %d numtrailing ones]",u4_total_coeff, 0);
|
|
ENTROPY_TRACE("\tnumber of non zero coeffs ",u4_total_coeff);
|
|
ENTROPY_TRACE("\tnumber of trailing ones ",0);
|
|
}
|
|
else
|
|
{
|
|
UWORD32 u4_vlcnum = u4_nc >> 1;
|
|
|
|
/* write coeff_token */
|
|
if (u4_vlcnum > 3)
|
|
{
|
|
/* Num-FLC */
|
|
u4_codeword = 3;
|
|
u4_codesize = 6;
|
|
}
|
|
else
|
|
{
|
|
/* Num-VLC 0, 1, 2 */
|
|
if (u4_vlcnum > 1)
|
|
{
|
|
u4_vlcnum = 2;
|
|
}
|
|
u4_codesize <<= u4_vlcnum;
|
|
u4_codeword >>= (4 - u4_codesize);
|
|
}
|
|
|
|
DEBUG("\n[%d numcoeff, %d numtrailing ones, %d nnz]",u4_total_coeff, 0, u4_nc);
|
|
ENTROPY_TRACE("\tnumber of non zero coeffs ",u4_total_coeff);
|
|
ENTROPY_TRACE("\tnC ",u4_nc);
|
|
}
|
|
|
|
|
|
DEBUG("\nCOEFF TOKEN 0: %d u4_codeword, %d u4_codesize",u4_codeword, u4_codesize);
|
|
ENTROPY_TRACE("\tcodeword ",u4_codeword);
|
|
ENTROPY_TRACE("\tcodesize ",u4_codesize);
|
|
|
|
error_status = ih264e_put_bits(ps_bit_stream, u4_codeword, u4_codesize);
|
|
|
|
return error_status;
|
|
}
|
|
else
|
|
{
|
|
/* Compute zero run, number of trailing ones and their sign. */
|
|
u4_totzero_sign_trailone =
|
|
ih264e_compute_zeroruns_and_trailingones(pi2_res_block,
|
|
u4_total_coeff,
|
|
pu1_zero_run,
|
|
u4_sig_coeff_map);
|
|
u4_trailing_ones = u4_totzero_sign_trailone & 0xFF;
|
|
u4_sign1 = (u4_totzero_sign_trailone >> 8)& 0xFF;
|
|
u4_tot_zeros = (u4_totzero_sign_trailone >> 16) & 0xFF;
|
|
u4_remaining_coeff = u4_total_coeff - u4_trailing_ones;
|
|
|
|
/* write coeff_token */
|
|
{
|
|
UWORD32 u4_codeword;
|
|
UWORD32 u4_codesize;
|
|
if (u4_block_type == CAVLC_CHROMA_4x4_DC)
|
|
{
|
|
u4_codeword = gu1_code_coeff_token_table_chroma[u4_trailing_ones][u4_total_coeff-1];
|
|
u4_codesize = gu1_size_coeff_token_table_chroma[u4_trailing_ones][u4_total_coeff-1];
|
|
|
|
DEBUG("\n[%d numcoeff, %d numtrailing ones]",u4_total_coeff, u4_trailing_ones);
|
|
ENTROPY_TRACE("\tnumber of non zero coeffs ",u4_total_coeff);
|
|
ENTROPY_TRACE("\tnumber of trailing ones ",u4_trailing_ones);
|
|
}
|
|
else
|
|
{
|
|
UWORD32 u4_vlcnum = u4_nc >> 1;
|
|
|
|
if (u4_vlcnum > 3)
|
|
{
|
|
/* Num-FLC */
|
|
u4_codeword = ((u4_total_coeff-1) << 2 ) + u4_trailing_ones;
|
|
u4_codesize = 6;
|
|
}
|
|
else
|
|
{
|
|
/* Num-VLC 0, 1, 2 */
|
|
if (u4_vlcnum > 1)
|
|
{
|
|
u4_vlcnum = 2;
|
|
}
|
|
u4_codeword = gu1_code_coeff_token_table[u4_vlcnum][u4_trailing_ones][u4_total_coeff-1];
|
|
u4_codesize = gu1_size_coeff_token_table[u4_vlcnum][u4_trailing_ones][u4_total_coeff-1];
|
|
}
|
|
|
|
DEBUG("\n[%d numcoeff, %d numtrailing ones, %d nnz]",u4_total_coeff, u4_trailing_ones, u4_nc);
|
|
ENTROPY_TRACE("\tnumber of non zero coeffs ",u4_total_coeff);
|
|
ENTROPY_TRACE("\tnumber of trailing ones ",u4_trailing_ones);
|
|
ENTROPY_TRACE("\tnC ",u4_nc);
|
|
}
|
|
|
|
DEBUG("\nCOEFF TOKEN 0: %d u4_codeword, %d u4_codesize",u4_codeword, u4_codesize);
|
|
ENTROPY_TRACE("\tcodeword ",u4_codeword);
|
|
ENTROPY_TRACE("\tcodesize ",u4_codesize);
|
|
|
|
error_status = ih264e_put_bits(ps_bit_stream, u4_codeword, u4_codesize);
|
|
}
|
|
|
|
/* write sign of trailing ones */
|
|
if (u4_trailing_ones)
|
|
{
|
|
DEBUG("\nT1's: %d u4_codeword, %d u4_codesize",u4_sign1, u4_trailing_ones);
|
|
error_status = ih264e_put_bits(ps_bit_stream, u4_sign1, u4_trailing_ones);
|
|
ENTROPY_TRACE("\tnumber of trailing ones ",u4_trailing_ones);
|
|
ENTROPY_TRACE("\tsign of trailing ones ",u4_sign1);
|
|
}
|
|
|
|
/* write level codes */
|
|
if (u4_remaining_coeff)
|
|
{
|
|
WORD32 i4_level = pi2_res_block[u4_remaining_coeff-1];
|
|
UWORD32 u4_escape;
|
|
UWORD32 u4_suffix_length = 0; // Level-VLC[N]
|
|
UWORD32 u4_abs_level, u4_abs_level_actual = 0;
|
|
WORD32 i4_sign;
|
|
const UWORD32 u4_rndfactor[] = {0, 0, 1, 3, 7, 15, 31};
|
|
|
|
DEBUG("\n \t%d coeff,",i4_level);
|
|
ENTROPY_TRACE("\tcoeff ",i4_level);
|
|
|
|
if (u4_trailing_ones < 3)
|
|
{
|
|
/* If there are less than 3 T1s, then the first non-T1 level is incremented if negative (decremented if positive)*/
|
|
if (i4_level < 0)
|
|
{
|
|
i4_level += 1;
|
|
}
|
|
else
|
|
{
|
|
i4_level -= 1;
|
|
}
|
|
|
|
u4_abs_level_actual = 1;
|
|
|
|
/* Initialize VLC table (Suffix Length) to encode the level */
|
|
if (u4_total_coeff > 10)
|
|
{
|
|
u4_suffix_length = 1;
|
|
}
|
|
}
|
|
|
|
i4_sign = (i4_level >> (sizeof(WORD32) * CHAR_BIT - 1));
|
|
u4_abs_level = ((i4_level + i4_sign) ^ i4_sign);
|
|
|
|
u4_abs_level_actual += u4_abs_level;
|
|
|
|
u4_escape = (u4_abs_level + u4_rndfactor[u4_suffix_length]) >> u4_suffix_length;
|
|
|
|
while (1)
|
|
{
|
|
UWORD32 u4_codesize;
|
|
UWORD32 u4_codeword;
|
|
UWORD32 u4_codeval;
|
|
|
|
u4_remaining_coeff--;
|
|
|
|
GATHER_CAVLC_STATS1();
|
|
|
|
{
|
|
u4_codeval = u4_abs_level << 1;
|
|
u4_codeval = u4_codeval - 2 - i4_sign;
|
|
|
|
if ((!u4_suffix_length) && (u4_escape > 7) && (u4_abs_level < 16))
|
|
{
|
|
u4_codeword = (1 << 4) + (u4_codeval - 14);
|
|
u4_codesize = 19;
|
|
}
|
|
else if (u4_escape > 7)
|
|
{
|
|
u4_codeword = (1 << 12) + (u4_codeval - (15 << u4_suffix_length));
|
|
u4_codesize = 28;
|
|
if (!u4_suffix_length)
|
|
{
|
|
u4_codeword -= 15;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
u4_codeword = (1 << u4_suffix_length) + (u4_codeval & ((1 << u4_suffix_length)-1));
|
|
u4_codesize = (u4_codeval >> u4_suffix_length) + 1 + u4_suffix_length;
|
|
}
|
|
}
|
|
|
|
/*put the level code in bitstream*/
|
|
DEBUG("\nLEVEL: %d u4_codeword, %d u4_codesize",u4_codeword, u4_codesize);
|
|
ENTROPY_TRACE("\tcodeword ",u4_codeword);
|
|
ENTROPY_TRACE("\tcodesize ",u4_codesize);
|
|
error_status = ih264e_put_bits(ps_bit_stream, u4_codeword, u4_codesize);
|
|
|
|
if (u4_remaining_coeff == 0) break;
|
|
|
|
/*update suffix length for next level*/
|
|
if (u4_suffix_length == 0)
|
|
{
|
|
u4_suffix_length++;
|
|
}
|
|
if (u4_suffix_length < 6)
|
|
{
|
|
if (u4_abs_level_actual > gu1_threshold_vlc_level[u4_suffix_length])
|
|
{
|
|
u4_suffix_length++;
|
|
}
|
|
}
|
|
|
|
/* next level */
|
|
i4_level = pi2_res_block[u4_remaining_coeff-1];
|
|
|
|
DEBUG("\n \t%d coeff,",i4_level);
|
|
ENTROPY_TRACE("\tcoeff ",i4_level);
|
|
|
|
i4_sign = (i4_level >> (sizeof(WORD32) * CHAR_BIT - 1));
|
|
u4_abs_level = ((i4_level + i4_sign) ^ i4_sign);
|
|
|
|
u4_abs_level_actual = u4_abs_level;
|
|
|
|
u4_escape = (u4_abs_level + u4_rndfactor[u4_suffix_length]) >> u4_suffix_length;
|
|
}
|
|
}
|
|
|
|
DEBUG("\n \t %d totalzeros",u4_tot_zeros);
|
|
ENTROPY_TRACE("\ttotal zeros ",u4_tot_zeros);
|
|
|
|
/* Write Total Zeros */
|
|
if (u4_total_coeff < u4_max_num_coeff)
|
|
{
|
|
WORD32 index;
|
|
UWORD32 u4_codeword;
|
|
UWORD32 u4_codesize;
|
|
|
|
if (u4_block_type == CAVLC_CHROMA_4x4_DC)
|
|
{
|
|
UWORD8 gu1_index_zero_table_chroma[] = {0, 4, 7};
|
|
index = gu1_index_zero_table_chroma[u4_total_coeff-1] + u4_tot_zeros;
|
|
u4_codesize = gu1_size_zero_table_chroma[index];
|
|
u4_codeword = gu1_code_zero_table_chroma[index];
|
|
}
|
|
else
|
|
{
|
|
index = gu1_index_zero_table[u4_total_coeff-1] + u4_tot_zeros;
|
|
u4_codesize = gu1_size_zero_table[index];
|
|
u4_codeword = gu1_code_zero_table[index];
|
|
}
|
|
|
|
DEBUG("\nTOTAL ZEROS: %d u4_codeword, %d u4_codesize",u4_codeword, u4_codesize);
|
|
ENTROPY_TRACE("\tcodeword ",u4_codeword);
|
|
ENTROPY_TRACE("\tcodesize ",u4_codesize);
|
|
error_status = ih264e_put_bits(ps_bit_stream, u4_codeword, u4_codesize);
|
|
}
|
|
|
|
/* Write Run Before */
|
|
if (u4_tot_zeros)
|
|
{
|
|
UWORD32 u4_max_num_coef = u4_total_coeff-1;
|
|
UWORD32 u4_codeword;
|
|
UWORD32 u4_codesize;
|
|
UWORD32 u4_zeros_left = u4_tot_zeros;
|
|
|
|
while (u4_max_num_coef)
|
|
{
|
|
UWORD32 u4_run_before = pu1_zero_run[u4_max_num_coef];
|
|
UWORD32 u4_index;
|
|
|
|
if (u4_zeros_left > MAX_ZERO_LEFT)
|
|
{
|
|
u4_index = gu1_index_run_table[MAX_ZERO_LEFT];
|
|
}
|
|
else
|
|
{
|
|
u4_index = gu1_index_run_table[u4_zeros_left - 1];
|
|
}
|
|
|
|
u4_codesize = gu1_size_run_table[u4_index + u4_run_before];
|
|
u4_codeword = gu1_code_run_table[u4_index + u4_run_before];
|
|
|
|
DEBUG("\nRUN BEFORE ZEROS: %d u4_codeword, %d u4_codesize",u4_codeword, u4_codesize);
|
|
ENTROPY_TRACE("\tcodeword ",u4_codeword);
|
|
ENTROPY_TRACE("\tcodesize ",u4_codesize);
|
|
error_status = ih264e_put_bits(ps_bit_stream, u4_codeword, u4_codesize);
|
|
|
|
u4_zeros_left -= u4_run_before;
|
|
if (!u4_zeros_left)
|
|
{
|
|
break;
|
|
}
|
|
u4_max_num_coef--;
|
|
}
|
|
}
|
|
}
|
|
|
|
return error_status;
|
|
}
|
|
|
|
/**
|
|
*******************************************************************************
|
|
*
|
|
* @brief
|
|
* This function generates CAVLC coded bit stream for the given subblock
|
|
*
|
|
* @param[in] ps_ent_ctxt
|
|
* Pointer to entropy context
|
|
*
|
|
* @param[in] pi2_res_block
|
|
* Pointers to residual blocks of all the partitions for the current subblk
|
|
* (containing levels in scan order)
|
|
*
|
|
* @param[in] pu1_nnz
|
|
* Total non-zero coefficients of all the partitions for the current subblk
|
|
*
|
|
* @param[in] pu2_sig_coeff_map
|
|
* Significant coefficient map of all the partitions for the current subblk
|
|
*
|
|
* @param[in] u4_block_type
|
|
* entropy coding block type
|
|
*
|
|
* @param[in] u4_ngbr_avbl
|
|
* top and left availability of all the partitions for the current subblk
|
|
* (packed)
|
|
*
|
|
* @param[in] pu1_top_nnz
|
|
* pointer to the buffer containing nnz of all the subblks to the top
|
|
*
|
|
* @param[in] pu1_left_nnz
|
|
* pointer to the buffer containing nnz of all the subblks to the left
|
|
*
|
|
* @returns error status
|
|
*
|
|
* @remarks none
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
static IH264E_ERROR_T ih264e_write_coeff8x8_cavlc(entropy_ctxt_t *ps_ent_ctxt,
|
|
WORD16 **pi2_res_block,
|
|
UWORD8 *pu1_nnz,
|
|
UWORD16 *pu2_sig_coeff_map,
|
|
ENTROPY_BLK_TYPE u4_block_type,
|
|
UWORD32 u4_ngbr_avlb,
|
|
UWORD8 *pu1_top_nnz,
|
|
UWORD8 *pu1_left_nnz)
|
|
{
|
|
IH264E_ERROR_T error_status = IH264E_SUCCESS;
|
|
bitstrm_t *ps_bitstream = ps_ent_ctxt->ps_bitstrm;
|
|
UWORD8 *pu1_zero_run = ps_ent_ctxt->au1_zero_run, *pu1_ngbr_avbl;
|
|
UWORD32 u4_nC;
|
|
UWORD8 u1_mb_a, u1_mb_b;
|
|
|
|
pu1_ngbr_avbl = (void *)(&u4_ngbr_avlb);
|
|
|
|
/* encode ac block index 4x4 = 0*/
|
|
u1_mb_a = pu1_ngbr_avbl[0] & 0x0F;
|
|
u1_mb_b = pu1_ngbr_avbl[0] & 0xF0;
|
|
u4_nC = 0;
|
|
if (u1_mb_a)
|
|
u4_nC += pu1_left_nnz[0];
|
|
if (u1_mb_b)
|
|
u4_nC += pu1_top_nnz[0];
|
|
if (u1_mb_a && u1_mb_b)
|
|
u4_nC = (u4_nC + 1) >> 1;
|
|
pu1_left_nnz[0] = pu1_top_nnz[0] = pu1_nnz[0];
|
|
error_status = ih264e_write_coeff4x4_cavlc(pi2_res_block[0], pu1_nnz[0], u4_block_type, pu1_zero_run, u4_nC, ps_bitstream, pu2_sig_coeff_map[0]);
|
|
|
|
/* encode ac block index 4x4 = 1*/
|
|
u1_mb_a = pu1_ngbr_avbl[1] & 0x0F;
|
|
u1_mb_b = pu1_ngbr_avbl[1] & 0xF0;
|
|
u4_nC = 0;
|
|
if (u1_mb_a)
|
|
u4_nC += pu1_left_nnz[0];
|
|
if (u1_mb_b)
|
|
u4_nC += pu1_top_nnz[1];
|
|
if (u1_mb_a && u1_mb_b)
|
|
u4_nC = (u4_nC + 1) >> 1;
|
|
pu1_left_nnz[0] = pu1_top_nnz[1] = pu1_nnz[1];
|
|
error_status = ih264e_write_coeff4x4_cavlc(pi2_res_block[1], pu1_nnz[1], u4_block_type, pu1_zero_run, u4_nC, ps_bitstream, pu2_sig_coeff_map[1]);
|
|
|
|
/* encode ac block index 4x4 = 2*/
|
|
u1_mb_a = pu1_ngbr_avbl[2] & 0x0F;
|
|
u1_mb_b = pu1_ngbr_avbl[2] & 0xF0;
|
|
u4_nC = 0;
|
|
if (u1_mb_a)
|
|
u4_nC += pu1_left_nnz[1];
|
|
if (u1_mb_b)
|
|
u4_nC += pu1_top_nnz[0];
|
|
if (u1_mb_a && u1_mb_b)
|
|
u4_nC = (u4_nC + 1) >> 1;
|
|
pu1_left_nnz[1] = pu1_top_nnz[0] = pu1_nnz[2];
|
|
error_status = ih264e_write_coeff4x4_cavlc(pi2_res_block[2], pu1_nnz[2], u4_block_type, pu1_zero_run, u4_nC, ps_bitstream, pu2_sig_coeff_map[2]);
|
|
|
|
/* encode ac block index 4x4 = 0*/
|
|
u1_mb_a = pu1_ngbr_avbl[3] & 0x0F;
|
|
u1_mb_b = pu1_ngbr_avbl[3] & 0xF0;
|
|
u4_nC = 0;
|
|
if (u1_mb_a)
|
|
u4_nC += pu1_left_nnz[1];
|
|
if (u1_mb_b)
|
|
u4_nC += pu1_top_nnz[1];
|
|
if (u1_mb_a && u1_mb_b)
|
|
u4_nC = (u4_nC + 1) >> 1;
|
|
pu1_left_nnz[1] = pu1_top_nnz[1] = pu1_nnz[3];
|
|
error_status = ih264e_write_coeff4x4_cavlc(pi2_res_block[3], pu1_nnz[3], u4_block_type, pu1_zero_run, u4_nC, ps_bitstream, pu2_sig_coeff_map[3]);
|
|
|
|
return error_status;
|
|
}
|
|
|
|
/**
|
|
*******************************************************************************
|
|
*
|
|
* @brief
|
|
* This function encodes luma and chroma residues of a macro block when
|
|
* the entropy coding mode chosen is cavlc.
|
|
*
|
|
* @param[in] ps_ent_ctxt
|
|
* Pointer to entropy context
|
|
*
|
|
* @param[in] u4_mb_type
|
|
* current mb type
|
|
*
|
|
* @param[in] u4_cbp
|
|
* coded block pattern for the current mb
|
|
*
|
|
* @returns error code
|
|
*
|
|
* @remarks none
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
static IH264E_ERROR_T ih264e_encode_residue(entropy_ctxt_t *ps_ent_ctxt,
|
|
UWORD32 u4_mb_type,
|
|
UWORD32 u4_cbp)
|
|
{
|
|
/* error status */
|
|
IH264E_ERROR_T error_status = IH264E_SUCCESS;
|
|
|
|
/* packed residue */
|
|
void *pv_mb_coeff_data = ps_ent_ctxt->pv_mb_coeff_data;
|
|
|
|
/* bit stream buffer */
|
|
bitstrm_t *ps_bitstream = ps_ent_ctxt->ps_bitstrm;
|
|
|
|
/* zero run */
|
|
UWORD8 *pu1_zero_run = ps_ent_ctxt->au1_zero_run;
|
|
|
|
/* temp var */
|
|
UWORD32 u4_nC, u4_ngbr_avlb;
|
|
UWORD8 au1_nnz[4], *pu1_ngbr_avlb, *pu1_top_nnz, *pu1_left_nnz;
|
|
UWORD16 au2_sig_coeff_map[4] = {0};
|
|
WORD16 *pi2_res_block[4] = {NULL};
|
|
UWORD8 *pu1_slice_idx = ps_ent_ctxt->pu1_slice_idx;
|
|
tu_sblk_coeff_data_t *ps_mb_coeff_data;
|
|
ENTROPY_BLK_TYPE e_entropy_blk_type = CAVLC_LUMA_4x4;
|
|
|
|
/* ngbr availability */
|
|
UWORD8 u1_mb_a, u1_mb_b;
|
|
|
|
/* cbp */
|
|
UWORD32 u4_cbp_luma = u4_cbp & 0xF, u4_cbp_chroma = u4_cbp >> 4;
|
|
|
|
/* mb indices */
|
|
WORD32 i4_mb_x, i4_mb_y;
|
|
|
|
/* derive neighbor availability */
|
|
i4_mb_x = ps_ent_ctxt->i4_mb_x;
|
|
i4_mb_y = ps_ent_ctxt->i4_mb_y;
|
|
pu1_slice_idx += (i4_mb_y * ps_ent_ctxt->i4_wd_mbs);
|
|
/* left macroblock availability */
|
|
u1_mb_a = (i4_mb_x == 0 ||
|
|
(pu1_slice_idx[i4_mb_x - 1 ] != pu1_slice_idx[i4_mb_x]))? 0 : 1;
|
|
/* top macroblock availability */
|
|
u1_mb_b = (i4_mb_y == 0 ||
|
|
(pu1_slice_idx[i4_mb_x-ps_ent_ctxt->i4_wd_mbs] != pu1_slice_idx[i4_mb_x]))? 0 : 1;
|
|
|
|
pu1_ngbr_avlb = (void *)(&u4_ngbr_avlb);
|
|
pu1_top_nnz = ps_ent_ctxt->pu1_top_nnz_luma[ps_ent_ctxt->i4_mb_x];
|
|
pu1_left_nnz = (UWORD8 *)&ps_ent_ctxt->u4_left_nnz_luma;
|
|
|
|
/* encode luma residue */
|
|
|
|
/* mb type intra 16x16 */
|
|
if (u4_mb_type == I16x16)
|
|
{
|
|
/* parse packed coeff data structure for residual data */
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]);
|
|
/* estimate nnz for the current mb */
|
|
u4_nC = 0;
|
|
if (u1_mb_a)
|
|
u4_nC += pu1_left_nnz[0];
|
|
if (u1_mb_b)
|
|
u4_nC += pu1_top_nnz[0];
|
|
if (u1_mb_a && u1_mb_b)
|
|
u4_nC = (u4_nC + 1) >> 1;
|
|
|
|
/* encode dc block */
|
|
ENTROPY_TRACE("Luma DC blk idx %d",0);
|
|
error_status = ih264e_write_coeff4x4_cavlc(pi2_res_block[0], au1_nnz[0], CAVLC_LUMA_4x4_DC, pu1_zero_run, u4_nC, ps_bitstream, au2_sig_coeff_map[0]);
|
|
|
|
e_entropy_blk_type = CAVLC_LUMA_4x4_AC;
|
|
}
|
|
|
|
if (u4_cbp_luma & 1)
|
|
{
|
|
/* encode ac block index 8x8 = 0*/
|
|
/* parse packed coeff data structure for residual data */
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[2], au2_sig_coeff_map[2], pi2_res_block[2]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[3], au2_sig_coeff_map[3], pi2_res_block[3]);
|
|
/* derive sub block neighbor availability */
|
|
|
|
pu1_ngbr_avlb[0] = (u1_mb_b << 4) | (u1_mb_a);
|
|
pu1_ngbr_avlb[1] = (u1_mb_b << 4) | 1;
|
|
pu1_ngbr_avlb[2] = (1 << 4) | (u1_mb_a);
|
|
pu1_ngbr_avlb[3] = 0x11;
|
|
/* encode sub blk */
|
|
ENTROPY_TRACE("Luma blk idx %d",0);
|
|
error_status = ih264e_write_coeff8x8_cavlc(ps_ent_ctxt, pi2_res_block, au1_nnz, au2_sig_coeff_map, e_entropy_blk_type, u4_ngbr_avlb, pu1_top_nnz, pu1_left_nnz);
|
|
}
|
|
else
|
|
{
|
|
pu1_top_nnz[0] = pu1_top_nnz[1] = 0;
|
|
pu1_left_nnz[0] = pu1_left_nnz[1] = 0;
|
|
}
|
|
|
|
if (u4_cbp_luma & 2)
|
|
{
|
|
/* encode ac block index 8x8 = 1*/
|
|
/* parse packed coeff data structure for residual data */
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[2], au2_sig_coeff_map[2], pi2_res_block[2]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[3], au2_sig_coeff_map[3], pi2_res_block[3]);
|
|
|
|
/* derive sub block neighbor availability */
|
|
pu1_ngbr_avlb[1] = pu1_ngbr_avlb[0] = (u1_mb_b << 4) | 1;
|
|
pu1_ngbr_avlb[3] = pu1_ngbr_avlb[2] = 0x11;
|
|
/* encode sub blk */
|
|
ENTROPY_TRACE("Luma blk idx %d",1);
|
|
error_status = ih264e_write_coeff8x8_cavlc(ps_ent_ctxt, pi2_res_block, au1_nnz, au2_sig_coeff_map, e_entropy_blk_type, u4_ngbr_avlb, pu1_top_nnz+2, pu1_left_nnz);
|
|
}
|
|
else
|
|
{
|
|
(pu1_top_nnz + 2)[0] = (pu1_top_nnz + 2)[1] = 0;
|
|
pu1_left_nnz[0] = pu1_left_nnz[1] = 0;
|
|
}
|
|
|
|
if (u4_cbp_luma & 0x4)
|
|
{
|
|
/* encode ac block index 8x8 = 2*/
|
|
/* parse packed coeff data structure for residual data */
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[2], au2_sig_coeff_map[2], pi2_res_block[2]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[3], au2_sig_coeff_map[3], pi2_res_block[3]);
|
|
|
|
/* derive sub block neighbor availability */
|
|
pu1_ngbr_avlb[2] = pu1_ngbr_avlb[0] = (1 << 4) | u1_mb_a;
|
|
pu1_ngbr_avlb[1] = pu1_ngbr_avlb[3] = 0x11;
|
|
/* encode sub blk */
|
|
ENTROPY_TRACE("Luma blk idx %d",2);
|
|
error_status = ih264e_write_coeff8x8_cavlc(ps_ent_ctxt, pi2_res_block, au1_nnz, au2_sig_coeff_map, e_entropy_blk_type, u4_ngbr_avlb, pu1_top_nnz, (pu1_left_nnz+2));
|
|
}
|
|
else
|
|
{
|
|
pu1_top_nnz[0] = pu1_top_nnz[1] = 0;
|
|
(pu1_left_nnz + 2)[0] = (pu1_left_nnz + 2)[1] = 0;
|
|
}
|
|
|
|
if (u4_cbp_luma & 0x8)
|
|
{
|
|
/* encode ac block index 8x8 = 3*/
|
|
/* parse packed coeff data structure for residual data */
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[2], au2_sig_coeff_map[2], pi2_res_block[2]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[3], au2_sig_coeff_map[3], pi2_res_block[3]);
|
|
|
|
/* derive sub block neighbor availability */
|
|
u4_ngbr_avlb = 0x11111111;
|
|
/* encode sub blk */
|
|
ENTROPY_TRACE("Luma blk idx %d",3);
|
|
error_status = ih264e_write_coeff8x8_cavlc(ps_ent_ctxt, pi2_res_block, au1_nnz, au2_sig_coeff_map, e_entropy_blk_type, u4_ngbr_avlb, pu1_top_nnz+2, pu1_left_nnz+2);
|
|
}
|
|
else
|
|
{
|
|
(pu1_top_nnz + 2)[0] = (pu1_top_nnz + 2)[1] = 0;
|
|
(pu1_left_nnz + 2)[0] = (pu1_left_nnz + 2)[1] = 0;
|
|
}
|
|
|
|
/* encode chroma residue */
|
|
if (u4_cbp_chroma & 3)
|
|
{
|
|
/* parse packed coeff data structure for residual data */
|
|
/* cb, cr */
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]);
|
|
|
|
/* encode dc block */
|
|
/* cb, cr */
|
|
ENTROPY_TRACE("Chroma DC blk idx %d",0);
|
|
error_status = ih264e_write_coeff4x4_cavlc(pi2_res_block[0], au1_nnz[0], CAVLC_CHROMA_4x4_DC, pu1_zero_run, 0, ps_bitstream, au2_sig_coeff_map[0]);
|
|
ENTROPY_TRACE("Chroma DC blk idx %d",1);
|
|
error_status = ih264e_write_coeff4x4_cavlc(pi2_res_block[1], au1_nnz[1], CAVLC_CHROMA_4x4_DC, pu1_zero_run, 0, ps_bitstream, au2_sig_coeff_map[1]);
|
|
}
|
|
|
|
pu1_top_nnz = ps_ent_ctxt->pu1_top_nnz_cbcr[ps_ent_ctxt->i4_mb_x];
|
|
pu1_left_nnz = (UWORD8 *) &ps_ent_ctxt->u4_left_nnz_cbcr;
|
|
|
|
/* encode sub blk */
|
|
if (u4_cbp_chroma & 0x2)
|
|
{
|
|
/* encode ac block index 8x8 = 0*/
|
|
/* derive sub block neighbor availability */
|
|
pu1_ngbr_avlb[0] = (u1_mb_b << 4) | (u1_mb_a);
|
|
pu1_ngbr_avlb[1] = (u1_mb_b << 4) | 1;
|
|
pu1_ngbr_avlb[2] = (1 << 4) | (u1_mb_a);
|
|
pu1_ngbr_avlb[3] = 0x11;
|
|
|
|
/* parse packed coeff data structure for residual data */
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[2], au2_sig_coeff_map[2], pi2_res_block[2]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[3], au2_sig_coeff_map[3], pi2_res_block[3]);
|
|
|
|
ENTROPY_TRACE("Chroma AC blk idx %d",0);
|
|
error_status = ih264e_write_coeff8x8_cavlc(ps_ent_ctxt, pi2_res_block, au1_nnz, au2_sig_coeff_map, CAVLC_CHROMA_4x4_AC, u4_ngbr_avlb, pu1_top_nnz, pu1_left_nnz);
|
|
}
|
|
else
|
|
{
|
|
pu1_top_nnz[0] = pu1_top_nnz[1] = 0;
|
|
pu1_left_nnz[0] = pu1_left_nnz[1] = 0;
|
|
}
|
|
|
|
pu1_top_nnz += 2;
|
|
pu1_left_nnz += 2;
|
|
|
|
/* encode sub blk */
|
|
if (u4_cbp_chroma & 0x2)
|
|
{
|
|
/* parse packed coeff data structure for residual data */
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[2], au2_sig_coeff_map[2], pi2_res_block[2]);
|
|
PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[3], au2_sig_coeff_map[3], pi2_res_block[3]);
|
|
|
|
ENTROPY_TRACE("Chroma AC blk idx %d",1);
|
|
error_status = ih264e_write_coeff8x8_cavlc(ps_ent_ctxt, pi2_res_block, au1_nnz, au2_sig_coeff_map, CAVLC_CHROMA_4x4_AC, u4_ngbr_avlb, pu1_top_nnz, pu1_left_nnz);
|
|
}
|
|
else
|
|
{
|
|
pu1_top_nnz[0] = pu1_top_nnz[1] = 0;
|
|
pu1_left_nnz[0] = pu1_left_nnz[1] = 0;
|
|
}
|
|
|
|
/* store the index of the next mb coeff data */
|
|
ps_ent_ctxt->pv_mb_coeff_data = pv_mb_coeff_data;
|
|
|
|
return error_status;
|
|
}
|
|
|
|
|
|
/**
|
|
*******************************************************************************
|
|
*
|
|
* @brief
|
|
* This function generates CAVLC coded bit stream for an Intra Slice.
|
|
*
|
|
* @description
|
|
* The mb syntax layer for intra slices constitutes luma mb mode, luma sub modes
|
|
* (if present), mb qp delta, coded block pattern, chroma mb mode and
|
|
* luma/chroma residue. These syntax elements are written as directed by table
|
|
* 7.3.5 of h264 specification.
|
|
*
|
|
* @param[in] ps_ent_ctxt
|
|
* pointer to entropy context
|
|
*
|
|
* @returns error code
|
|
*
|
|
* @remarks none
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
IH264E_ERROR_T ih264e_write_islice_mb_cavlc(entropy_ctxt_t *ps_ent_ctxt)
|
|
{
|
|
/* error status */
|
|
IH264E_ERROR_T error_status = IH264E_SUCCESS;
|
|
|
|
/* bit stream ptr */
|
|
bitstrm_t *ps_bitstream = ps_ent_ctxt->ps_bitstrm;
|
|
|
|
/* packed header data */
|
|
UWORD8 *pu1_byte = ps_ent_ctxt->pv_mb_header_data;
|
|
mb_hdr_common_t *ps_mb_hdr = (mb_hdr_common_t *)ps_ent_ctxt->pv_mb_header_data;
|
|
|
|
/* mb header info */
|
|
/*
|
|
* mb_tpm : mb type plus mode
|
|
* mb_type : luma mb type and chroma mb type are packed
|
|
* cbp : coded block pattern
|
|
* mb_qp_delta : mb qp delta
|
|
* chroma_intra_mode : chroma intra mode
|
|
* luma_intra_mode : luma intra mode
|
|
*/
|
|
WORD32 mb_tpm, mb_type, cbp, chroma_intra_mode, luma_intra_mode;
|
|
WORD8 mb_qp_delta;
|
|
|
|
/* temp var */
|
|
WORD32 i, mb_type_stream;
|
|
|
|
WORD32 bitstream_start_offset, bitstream_end_offset;
|
|
|
|
/* Starting bitstream offset for header in bits */
|
|
bitstream_start_offset = GET_NUM_BITS(ps_bitstream);
|
|
|
|
|
|
/********************************************************************/
|
|
/* BEGIN HEADER GENERATION */
|
|
/********************************************************************/
|
|
|
|
/* mb header info */
|
|
mb_tpm = ps_mb_hdr->u1_mb_type_mode;
|
|
cbp = ps_mb_hdr->u1_cbp;
|
|
mb_qp_delta = ps_mb_hdr->u1_mb_qp_delta;
|
|
|
|
/* mb type */
|
|
mb_type = mb_tpm & 0xF;
|
|
/* is intra ? */
|
|
if (mb_type == I16x16)
|
|
{
|
|
UWORD32 u4_cbp_l, u4_cbp_c;
|
|
|
|
u4_cbp_c = (cbp >> 4);
|
|
u4_cbp_l = (cbp & 0xF);
|
|
luma_intra_mode = (mb_tpm >> 4) & 3;
|
|
chroma_intra_mode = (mb_tpm >> 6);
|
|
|
|
mb_type_stream = luma_intra_mode + 1 + (u4_cbp_c << 2) + (u4_cbp_l == 15) * 12;
|
|
|
|
/* write mb type */
|
|
PUT_BITS_UEV(ps_bitstream, mb_type_stream, error_status, "mb type");
|
|
|
|
/* intra_chroma_pred_mode */
|
|
PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode");
|
|
|
|
pu1_byte += sizeof(mb_hdr_i16x16_t);
|
|
}
|
|
else if (mb_type == I4x4)
|
|
{
|
|
mb_hdr_i4x4_t *ps_mb_hdr_i4x4 = (mb_hdr_i4x4_t *)ps_ent_ctxt->pv_mb_header_data;
|
|
|
|
/* mb sub blk modes */
|
|
WORD32 intra_pred_mode_flag, rem_intra_mode;
|
|
WORD32 byte;
|
|
|
|
chroma_intra_mode = (mb_tpm >> 6);
|
|
|
|
/* write mb type */
|
|
PUT_BITS_UEV(ps_bitstream, 0, error_status, "mb type");
|
|
|
|
for (i = 0; i < 16; i += 2)
|
|
{
|
|
/* sub blk idx 1 */
|
|
byte = ps_mb_hdr_i4x4->au1_sub_blk_modes[i >> 1];
|
|
|
|
intra_pred_mode_flag = byte & 0x1;
|
|
|
|
/* prev_intra4x4_pred_mode_flag */
|
|
PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag");
|
|
|
|
/* rem_intra4x4_pred_mode */
|
|
if (!intra_pred_mode_flag)
|
|
{
|
|
rem_intra_mode = (byte & 0xF) >> 1;
|
|
PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode");
|
|
}
|
|
|
|
/* sub blk idx 2 */
|
|
byte >>= 4;
|
|
|
|
intra_pred_mode_flag = byte & 0x1;
|
|
|
|
/* prev_intra4x4_pred_mode_flag */
|
|
PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag");
|
|
|
|
/* rem_intra4x4_pred_mode */
|
|
if (!intra_pred_mode_flag)
|
|
{
|
|
rem_intra_mode = (byte & 0xF) >> 1;
|
|
PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode");
|
|
}
|
|
}
|
|
|
|
/* intra_chroma_pred_mode */
|
|
PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode");
|
|
|
|
pu1_byte += sizeof(mb_hdr_i4x4_t);
|
|
}
|
|
else if (mb_type == I8x8)
|
|
{
|
|
/* transform 8x8 flag */
|
|
UWORD32 u4_transform_size_8x8_flag = ps_ent_ctxt->i1_transform_8x8_mode_flag;
|
|
mb_hdr_i8x8_t *ps_mb_hdr_i8x8 = (mb_hdr_i8x8_t *)ps_ent_ctxt->pv_mb_header_data;
|
|
|
|
/* mb sub blk modes */
|
|
WORD32 intra_pred_mode_flag, rem_intra_mode;
|
|
WORD32 byte;
|
|
|
|
chroma_intra_mode = (mb_tpm >> 6);
|
|
|
|
ASSERT(0);
|
|
|
|
/* write mb type */
|
|
PUT_BITS_UEV(ps_bitstream, 0, error_status, "mb type");
|
|
|
|
/* u4_transform_size_8x8_flag */
|
|
PUT_BITS(ps_bitstream, u4_transform_size_8x8_flag, 1, error_status, "u4_transform_size_8x8_flag");
|
|
|
|
/* write sub block modes */
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
/* sub blk idx 1 */
|
|
byte = ps_mb_hdr_i8x8->au1_sub_blk_modes[i >> 1];
|
|
|
|
intra_pred_mode_flag = byte & 0x1;
|
|
|
|
/* prev_intra4x4_pred_mode_flag */
|
|
PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag");
|
|
|
|
/* rem_intra4x4_pred_mode */
|
|
if (!intra_pred_mode_flag)
|
|
{
|
|
rem_intra_mode = (byte & 0xF) >> 1;
|
|
PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode");
|
|
}
|
|
|
|
/* sub blk idx 2 */
|
|
byte >>= 4;
|
|
|
|
intra_pred_mode_flag = byte & 0x1;
|
|
|
|
/* prev_intra4x4_pred_mode_flag */
|
|
PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag");
|
|
|
|
/* rem_intra4x4_pred_mode */
|
|
if (!intra_pred_mode_flag)
|
|
{
|
|
rem_intra_mode = (byte & 0xF) >> 1;
|
|
PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode");
|
|
}
|
|
}
|
|
|
|
/* intra_chroma_pred_mode */
|
|
PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode");
|
|
|
|
pu1_byte += sizeof(mb_hdr_i8x8_t);
|
|
}
|
|
else
|
|
{
|
|
}
|
|
|
|
/* coded_block_pattern */
|
|
if (mb_type != I16x16)
|
|
{
|
|
PUT_BITS_UEV(ps_bitstream, gu1_cbp_map_tables[cbp][0], error_status, "coded_block_pattern");
|
|
}
|
|
|
|
if (cbp || mb_type == I16x16)
|
|
{
|
|
/* mb_qp_delta */
|
|
PUT_BITS_SEV(ps_bitstream, mb_qp_delta, error_status, "mb_qp_delta");
|
|
}
|
|
|
|
/* Ending bitstream offset for header in bits */
|
|
bitstream_end_offset = GET_NUM_BITS(ps_bitstream);
|
|
|
|
ps_ent_ctxt->u4_header_bits[0] += bitstream_end_offset - bitstream_start_offset;
|
|
|
|
/* Starting bitstream offset for residue */
|
|
bitstream_start_offset = bitstream_end_offset;
|
|
|
|
/* residual */
|
|
error_status = ih264e_encode_residue(ps_ent_ctxt, mb_type, cbp);
|
|
|
|
/* Ending bitstream offset for reside in bits */
|
|
bitstream_end_offset = GET_NUM_BITS(ps_bitstream);
|
|
ps_ent_ctxt->u4_residue_bits[0] += bitstream_end_offset - bitstream_start_offset;
|
|
|
|
/* store the index of the next mb syntax layer */
|
|
ps_ent_ctxt->pv_mb_header_data = pu1_byte;
|
|
|
|
return error_status;
|
|
}
|
|
|
|
/**
|
|
*******************************************************************************
|
|
*
|
|
* @brief
|
|
* This function generates CAVLC coded bit stream for Inter slices
|
|
*
|
|
* @description
|
|
* The mb syntax layer for inter slices constitutes luma mb mode, luma sub modes
|
|
* (if present), mb qp delta, coded block pattern, chroma mb mode and
|
|
* luma/chroma residue. These syntax elements are written as directed by table
|
|
* 7.3.5 of h264 specification
|
|
*
|
|
* @param[in] ps_ent_ctxt
|
|
* pointer to entropy context
|
|
*
|
|
* @returns error code
|
|
*
|
|
* @remarks none
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
IH264E_ERROR_T ih264e_write_pslice_mb_cavlc(entropy_ctxt_t *ps_ent_ctxt)
|
|
{
|
|
/* error status */
|
|
IH264E_ERROR_T error_status = IH264E_SUCCESS;
|
|
|
|
/* bit stream ptr */
|
|
bitstrm_t *ps_bitstream = ps_ent_ctxt->ps_bitstrm;
|
|
|
|
/* packed header data */
|
|
UWORD8 *pu1_byte = ps_ent_ctxt->pv_mb_header_data;
|
|
mb_hdr_common_t *ps_mb_hdr = (mb_hdr_common_t *)ps_ent_ctxt->pv_mb_header_data;
|
|
|
|
/* mb header info */
|
|
/*
|
|
* mb_tpm : mb type plus mode
|
|
* mb_type : luma mb type and chroma mb type are packed
|
|
* cbp : coded block pattern
|
|
* mb_qp_delta : mb qp delta
|
|
* chroma_intra_mode : chroma intra mode
|
|
* luma_intra_mode : luma intra mode
|
|
* ps_pu : Pointer to the array of structures having motion vectors, size
|
|
* and position of sub partitions
|
|
*/
|
|
WORD32 mb_tpm, mb_type, cbp, chroma_intra_mode, luma_intra_mode;
|
|
WORD8 mb_qp_delta;
|
|
|
|
/* temp var */
|
|
WORD32 i, mb_type_stream, cbptable = 1;
|
|
|
|
WORD32 is_inter = 0;
|
|
|
|
WORD32 bitstream_start_offset, bitstream_end_offset;
|
|
|
|
/* Starting bitstream offset for header in bits */
|
|
bitstream_start_offset = GET_NUM_BITS(ps_bitstream);
|
|
|
|
/********************************************************************/
|
|
/* BEGIN HEADER GENERATION */
|
|
/********************************************************************/
|
|
|
|
/* mb header info */
|
|
mb_tpm = ps_mb_hdr->u1_mb_type_mode;
|
|
|
|
/* mb type */
|
|
mb_type = mb_tpm & 0xF;
|
|
|
|
/* check for skip */
|
|
if (mb_type == PSKIP)
|
|
{
|
|
UWORD32 *nnz;
|
|
|
|
is_inter = 1;
|
|
|
|
/* increment skip counter */
|
|
(*ps_ent_ctxt->pi4_mb_skip_run)++;
|
|
|
|
/* store the index of the next mb syntax layer */
|
|
pu1_byte += sizeof(mb_hdr_pskip_t);
|
|
ps_ent_ctxt->pv_mb_header_data = pu1_byte;
|
|
|
|
/* set nnz to zero */
|
|
ps_ent_ctxt->u4_left_nnz_luma = 0;
|
|
nnz = (UWORD32 *)ps_ent_ctxt->pu1_top_nnz_luma[ps_ent_ctxt->i4_mb_x];
|
|
*nnz = 0;
|
|
ps_ent_ctxt->u4_left_nnz_cbcr = 0;
|
|
nnz = (UWORD32 *)ps_ent_ctxt->pu1_top_nnz_cbcr[ps_ent_ctxt->i4_mb_x];
|
|
*nnz = 0;
|
|
|
|
/* residual */
|
|
error_status = ih264e_encode_residue(ps_ent_ctxt, P16x16, 0);
|
|
|
|
bitstream_end_offset = GET_NUM_BITS(ps_bitstream);
|
|
|
|
ps_ent_ctxt->u4_header_bits[is_inter] += bitstream_end_offset - bitstream_start_offset;
|
|
|
|
return error_status;
|
|
}
|
|
|
|
/* remaining mb header info */
|
|
cbp = ps_mb_hdr->u1_cbp;
|
|
mb_qp_delta = ps_mb_hdr->u1_mb_qp_delta;
|
|
|
|
/* mb skip run */
|
|
PUT_BITS_UEV(ps_bitstream, *ps_ent_ctxt->pi4_mb_skip_run, error_status, "mb skip run");
|
|
|
|
/* reset skip counter */
|
|
*ps_ent_ctxt->pi4_mb_skip_run = 0;
|
|
|
|
/* is intra ? */
|
|
if (mb_type == I16x16)
|
|
{
|
|
UWORD32 u4_cbp_l, u4_cbp_c;
|
|
|
|
is_inter = 0;
|
|
|
|
u4_cbp_c = (cbp >> 4);
|
|
u4_cbp_l = (cbp & 0xF);
|
|
luma_intra_mode = (mb_tpm >> 4) & 3;
|
|
chroma_intra_mode = (mb_tpm >> 6);
|
|
|
|
mb_type_stream = luma_intra_mode + 1 + (u4_cbp_c << 2) + (u4_cbp_l == 15) * 12;
|
|
|
|
mb_type_stream += 5;
|
|
|
|
/* write mb type */
|
|
PUT_BITS_UEV(ps_bitstream, mb_type_stream, error_status, "mb type");
|
|
|
|
/* intra_chroma_pred_mode */
|
|
PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode");
|
|
pu1_byte += sizeof(mb_hdr_i16x16_t);
|
|
}
|
|
else if (mb_type == I4x4)
|
|
{
|
|
mb_hdr_i4x4_t *ps_mb_hdr_i4x4 = (mb_hdr_i4x4_t *)ps_ent_ctxt->pv_mb_header_data;
|
|
|
|
/* mb sub blk modes */
|
|
WORD32 intra_pred_mode_flag, rem_intra_mode;
|
|
WORD32 byte;
|
|
|
|
is_inter = 0;
|
|
|
|
chroma_intra_mode = (mb_tpm >> 6);
|
|
cbptable = 0;
|
|
|
|
/* write mb type */
|
|
PUT_BITS_UEV(ps_bitstream, 5, error_status, "mb type");
|
|
|
|
for (i = 0; i < 16; i += 2)
|
|
{
|
|
/* sub blk idx 1 */
|
|
byte = ps_mb_hdr_i4x4->au1_sub_blk_modes[i >> 1];
|
|
|
|
intra_pred_mode_flag = byte & 0x1;
|
|
|
|
/* prev_intra4x4_pred_mode_flag */
|
|
PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag");
|
|
|
|
/* rem_intra4x4_pred_mode */
|
|
if (!intra_pred_mode_flag)
|
|
{
|
|
rem_intra_mode = (byte & 0xF) >> 1;
|
|
PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode");
|
|
}
|
|
|
|
/* sub blk idx 2 */
|
|
byte >>= 4;
|
|
|
|
intra_pred_mode_flag = byte & 0x1;
|
|
|
|
/* prev_intra4x4_pred_mode_flag */
|
|
PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag");
|
|
|
|
/* rem_intra4x4_pred_mode */
|
|
if (!intra_pred_mode_flag)
|
|
{
|
|
rem_intra_mode = (byte & 0xF) >> 1;
|
|
PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode");
|
|
}
|
|
}
|
|
|
|
/* intra_chroma_pred_mode */
|
|
PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode");
|
|
|
|
pu1_byte += sizeof(mb_hdr_i4x4_t);
|
|
}
|
|
else if (mb_type == I8x8)
|
|
{
|
|
mb_hdr_i8x8_t *ps_mb_hdr_i8x8 = (mb_hdr_i8x8_t *)ps_ent_ctxt->pv_mb_header_data;
|
|
|
|
/* transform 8x8 flag */
|
|
UWORD32 u4_transform_size_8x8_flag = ps_ent_ctxt->i1_transform_8x8_mode_flag;
|
|
|
|
/* mb sub blk modes */
|
|
WORD32 intra_pred_mode_flag, rem_intra_mode;
|
|
WORD32 byte;
|
|
|
|
is_inter = 0;
|
|
|
|
chroma_intra_mode = (mb_tpm >> 6);
|
|
cbptable = 0;
|
|
|
|
ASSERT(0);
|
|
|
|
/* write mb type */
|
|
PUT_BITS_UEV(ps_bitstream, 5, error_status, "mb type");
|
|
|
|
/* u4_transform_size_8x8_flag */
|
|
PUT_BITS(ps_bitstream, u4_transform_size_8x8_flag, 1, error_status, "u4_transform_size_8x8_flag");
|
|
|
|
/* write sub block modes */
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
/* sub blk idx 1 */
|
|
byte = ps_mb_hdr_i8x8->au1_sub_blk_modes[i >> 1];
|
|
|
|
intra_pred_mode_flag = byte & 0x1;
|
|
|
|
/* prev_intra4x4_pred_mode_flag */
|
|
PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag");
|
|
|
|
/* rem_intra4x4_pred_mode */
|
|
if (!intra_pred_mode_flag)
|
|
{
|
|
rem_intra_mode = (byte & 0xF) >> 1;
|
|
PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode");
|
|
}
|
|
|
|
/* sub blk idx 2 */
|
|
byte >>= 4;
|
|
|
|
intra_pred_mode_flag = byte & 0x1;
|
|
|
|
/* prev_intra4x4_pred_mode_flag */
|
|
PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag");
|
|
|
|
/* rem_intra4x4_pred_mode */
|
|
if (!intra_pred_mode_flag)
|
|
{
|
|
rem_intra_mode = (byte & 0xF) >> 1;
|
|
PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode");
|
|
}
|
|
}
|
|
|
|
/* intra_chroma_pred_mode */
|
|
PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode");
|
|
|
|
pu1_byte += sizeof(mb_hdr_i8x8_t);
|
|
}
|
|
else
|
|
{
|
|
mb_hdr_p16x16_t *ps_mb_hdr_p16x16 = (mb_hdr_p16x16_t *)ps_ent_ctxt->pv_mb_header_data;
|
|
|
|
/* inter macro block partition cnt */
|
|
const UWORD8 au1_part_cnt[] = { 1, 2, 2, 4 };
|
|
|
|
/* mv ptr */
|
|
WORD16 *pi2_mv_ptr = (WORD16 *)ps_mb_hdr_p16x16->ai2_mv;
|
|
|
|
/* number of partitions for the current mb */
|
|
UWORD32 u4_part_cnt = au1_part_cnt[mb_type - 3];
|
|
|
|
is_inter = 1;
|
|
|
|
/* write mb type */
|
|
PUT_BITS_UEV(ps_bitstream, mb_type - 3, error_status, "mb type");
|
|
|
|
for (i = 0; i < (WORD32)u4_part_cnt; i++)
|
|
{
|
|
PUT_BITS_SEV(ps_bitstream, *pi2_mv_ptr++, error_status, "mv x");
|
|
PUT_BITS_SEV(ps_bitstream, *pi2_mv_ptr++, error_status, "mv y");
|
|
}
|
|
|
|
pu1_byte += sizeof(mb_hdr_p16x16_t);
|
|
|
|
}
|
|
|
|
/* coded_block_pattern */
|
|
if (mb_type != I16x16)
|
|
{
|
|
PUT_BITS_UEV(ps_bitstream, gu1_cbp_map_tables[cbp][cbptable], error_status, "coded_block_pattern");
|
|
}
|
|
|
|
if (cbp || mb_type == I16x16)
|
|
{
|
|
/* mb_qp_delta */
|
|
PUT_BITS_SEV(ps_bitstream, mb_qp_delta, error_status, "mb_qp_delta");
|
|
}
|
|
|
|
/* Ending bitstream offset for header in bits */
|
|
bitstream_end_offset = GET_NUM_BITS(ps_bitstream);
|
|
|
|
ps_ent_ctxt->u4_header_bits[is_inter] += bitstream_end_offset - bitstream_start_offset;
|
|
|
|
/* start bitstream offset for residue in bits */
|
|
bitstream_start_offset = bitstream_end_offset;
|
|
|
|
/* residual */
|
|
error_status = ih264e_encode_residue(ps_ent_ctxt, mb_type, cbp);
|
|
|
|
/* Ending bitstream offset for residue in bits */
|
|
bitstream_end_offset = GET_NUM_BITS(ps_bitstream);
|
|
|
|
ps_ent_ctxt->u4_residue_bits[is_inter] += bitstream_end_offset - bitstream_start_offset;
|
|
|
|
/* store the index of the next mb syntax layer */
|
|
ps_ent_ctxt->pv_mb_header_data = pu1_byte;
|
|
|
|
return error_status;
|
|
}
|
|
|
|
|
|
/**
|
|
*******************************************************************************
|
|
*
|
|
* @brief
|
|
* This function generates CAVLC coded bit stream for B slices
|
|
*
|
|
* @description
|
|
* The mb syntax layer for inter slices constitutes luma mb mode, luma sub modes
|
|
* (if present), mb qp delta, coded block pattern, chroma mb mode and
|
|
* luma/chroma residue. These syntax elements are written as directed by table
|
|
* 7.3.5 of h264 specification
|
|
*
|
|
* @param[in] ps_ent_ctxt
|
|
* pointer to entropy context
|
|
*
|
|
* @returns error code
|
|
*
|
|
* @remarks none
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
IH264E_ERROR_T ih264e_write_bslice_mb_cavlc(entropy_ctxt_t *ps_ent_ctxt)
|
|
{
|
|
/* error status */
|
|
IH264E_ERROR_T error_status = IH264E_SUCCESS;
|
|
|
|
/* bit stream ptr */
|
|
bitstrm_t *ps_bitstream = ps_ent_ctxt->ps_bitstrm;
|
|
|
|
/* packed header data */
|
|
UWORD8 *pu1_byte = ps_ent_ctxt->pv_mb_header_data;
|
|
mb_hdr_common_t *ps_mb_hdr = (mb_hdr_common_t *)ps_ent_ctxt->pv_mb_header_data;
|
|
|
|
/* mb header info */
|
|
/*
|
|
* mb_tpm : mb type plus mode
|
|
* mb_type : luma mb type and chroma mb type are packed
|
|
* cbp : coded block pattern
|
|
* mb_qp_delta : mb qp delta
|
|
* chroma_intra_mode : chroma intra mode
|
|
* luma_intra_mode : luma intra mode
|
|
* ps_pu : Pointer to the array of structures having motion vectors, size
|
|
* and position of sub partitions
|
|
*/
|
|
WORD32 mb_tpm, mb_type, cbp, chroma_intra_mode, luma_intra_mode;
|
|
WORD8 mb_qp_delta;
|
|
|
|
/* temp var */
|
|
WORD32 i, mb_type_stream, cbptable = 1;
|
|
|
|
WORD32 is_inter = 0;
|
|
|
|
WORD32 bitstream_start_offset, bitstream_end_offset;
|
|
|
|
/* Starting bitstream offset for header in bits */
|
|
bitstream_start_offset = GET_NUM_BITS(ps_bitstream);
|
|
|
|
/********************************************************************/
|
|
/* BEGIN HEADER GENERATION */
|
|
/********************************************************************/
|
|
|
|
mb_tpm = ps_mb_hdr->u1_mb_type_mode;
|
|
|
|
/* mb type */
|
|
mb_type = mb_tpm & 0xF;
|
|
|
|
/* check for skip */
|
|
if (mb_type == BSKIP)
|
|
{
|
|
UWORD32 *nnz;
|
|
|
|
is_inter = 1;
|
|
|
|
/* increment skip counter */
|
|
(*ps_ent_ctxt->pi4_mb_skip_run)++;
|
|
|
|
/* store the index of the next mb syntax layer */
|
|
pu1_byte += sizeof(mb_hdr_bskip_t);
|
|
ps_ent_ctxt->pv_mb_header_data = pu1_byte;
|
|
|
|
/* set nnz to zero */
|
|
ps_ent_ctxt->u4_left_nnz_luma = 0;
|
|
nnz = (UWORD32 *)ps_ent_ctxt->pu1_top_nnz_luma[ps_ent_ctxt->i4_mb_x];
|
|
*nnz = 0;
|
|
ps_ent_ctxt->u4_left_nnz_cbcr = 0;
|
|
nnz = (UWORD32 *)ps_ent_ctxt->pu1_top_nnz_cbcr[ps_ent_ctxt->i4_mb_x];
|
|
*nnz = 0;
|
|
|
|
/* residual */
|
|
error_status = ih264e_encode_residue(ps_ent_ctxt, B16x16, 0);
|
|
|
|
bitstream_end_offset = GET_NUM_BITS(ps_bitstream);
|
|
|
|
ps_ent_ctxt->u4_header_bits[is_inter] += bitstream_end_offset
|
|
- bitstream_start_offset;
|
|
|
|
return error_status;
|
|
}
|
|
|
|
|
|
/* remaining mb header info */
|
|
cbp = ps_mb_hdr->u1_cbp;
|
|
mb_qp_delta = ps_mb_hdr->u1_mb_qp_delta;
|
|
|
|
/* mb skip run */
|
|
PUT_BITS_UEV(ps_bitstream, *ps_ent_ctxt->pi4_mb_skip_run, error_status, "mb skip run");
|
|
|
|
/* reset skip counter */
|
|
*ps_ent_ctxt->pi4_mb_skip_run = 0;
|
|
|
|
/* is intra ? */
|
|
if (mb_type == I16x16)
|
|
{
|
|
UWORD32 u4_cbp_l, u4_cbp_c;
|
|
|
|
is_inter = 0;
|
|
|
|
u4_cbp_c = (cbp >> 4);
|
|
u4_cbp_l = (cbp & 0xF);
|
|
luma_intra_mode = (mb_tpm >> 4) & 3;
|
|
chroma_intra_mode = (mb_tpm >> 6);
|
|
|
|
mb_type_stream = luma_intra_mode + 1 + (u4_cbp_c << 2) + (u4_cbp_l == 15) * 12;
|
|
|
|
mb_type_stream += 23;
|
|
|
|
/* write mb type */
|
|
PUT_BITS_UEV(ps_bitstream, mb_type_stream, error_status, "mb type");
|
|
|
|
/* intra_chroma_pred_mode */
|
|
PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode");
|
|
pu1_byte += sizeof(mb_hdr_i16x16_t);
|
|
|
|
}
|
|
else if (mb_type == I4x4)
|
|
{
|
|
mb_hdr_i4x4_t *ps_mb_hdr_i4x4 = (mb_hdr_i4x4_t *)ps_ent_ctxt->pv_mb_header_data;
|
|
|
|
/* mb sub blk modes */
|
|
WORD32 intra_pred_mode_flag, rem_intra_mode;
|
|
WORD32 byte;
|
|
|
|
is_inter = 0;
|
|
|
|
chroma_intra_mode = (mb_tpm >> 6);
|
|
cbptable = 0;
|
|
|
|
/* write mb type */
|
|
PUT_BITS_UEV(ps_bitstream, 23, error_status, "mb type");
|
|
|
|
for (i = 0; i < 16; i += 2)
|
|
{
|
|
/* sub blk idx 1 */
|
|
byte = ps_mb_hdr_i4x4->au1_sub_blk_modes[i >> 1];
|
|
|
|
intra_pred_mode_flag = byte & 0x1;
|
|
|
|
/* prev_intra4x4_pred_mode_flag */
|
|
PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag");
|
|
|
|
/* rem_intra4x4_pred_mode */
|
|
if (!intra_pred_mode_flag)
|
|
{
|
|
rem_intra_mode = (byte & 0xF) >> 1;
|
|
PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode");
|
|
}
|
|
|
|
/* sub blk idx 2 */
|
|
byte >>= 4;
|
|
|
|
intra_pred_mode_flag = byte & 0x1;
|
|
|
|
/* prev_intra4x4_pred_mode_flag */
|
|
PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag");
|
|
|
|
/* rem_intra4x4_pred_mode */
|
|
if (!intra_pred_mode_flag)
|
|
{
|
|
rem_intra_mode = (byte & 0xF) >> 1;
|
|
PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode");
|
|
}
|
|
}
|
|
|
|
/* intra_chroma_pred_mode */
|
|
PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode");
|
|
pu1_byte += sizeof(mb_hdr_i4x4_t);
|
|
|
|
}
|
|
else if (mb_type == I8x8)
|
|
{
|
|
mb_hdr_i8x8_t *ps_mb_hdr_i8x8 = (mb_hdr_i8x8_t *)ps_ent_ctxt->pv_mb_header_data;
|
|
|
|
/* transform 8x8 flag */
|
|
UWORD32 u4_transform_size_8x8_flag = ps_ent_ctxt->i1_transform_8x8_mode_flag;
|
|
|
|
/* mb sub blk modes */
|
|
WORD32 intra_pred_mode_flag, rem_intra_mode;
|
|
WORD32 byte;
|
|
|
|
is_inter = 0;
|
|
|
|
chroma_intra_mode = (mb_tpm >> 6);
|
|
cbptable = 0;
|
|
|
|
ASSERT(0);
|
|
|
|
/* write mb type */
|
|
PUT_BITS_UEV(ps_bitstream, 23, error_status, "mb type");
|
|
|
|
/* u4_transform_size_8x8_flag */
|
|
PUT_BITS(ps_bitstream, u4_transform_size_8x8_flag, 1, error_status, "u4_transform_size_8x8_flag");
|
|
|
|
/* write sub block modes */
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
/* sub blk idx 1 */
|
|
byte = ps_mb_hdr_i8x8->au1_sub_blk_modes[i >> 1];
|
|
|
|
intra_pred_mode_flag = byte & 0x1;
|
|
|
|
/* prev_intra4x4_pred_mode_flag */
|
|
PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag");
|
|
|
|
/* rem_intra4x4_pred_mode */
|
|
if (!intra_pred_mode_flag)
|
|
{
|
|
rem_intra_mode = (byte & 0xF) >> 1;
|
|
PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode");
|
|
}
|
|
|
|
/* sub blk idx 2 */
|
|
byte >>= 4;
|
|
|
|
intra_pred_mode_flag = byte & 0x1;
|
|
|
|
/* prev_intra4x4_pred_mode_flag */
|
|
PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag");
|
|
|
|
/* rem_intra4x4_pred_mode */
|
|
if (!intra_pred_mode_flag)
|
|
{
|
|
rem_intra_mode = (byte & 0xF) >> 1;
|
|
PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode");
|
|
}
|
|
}
|
|
|
|
/* intra_chroma_pred_mode */
|
|
PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode");
|
|
pu1_byte += sizeof(mb_hdr_i8x8_t);
|
|
|
|
}
|
|
else if(mb_type == BDIRECT)
|
|
{
|
|
is_inter = 1;
|
|
/* write mb type */
|
|
PUT_BITS_UEV(ps_bitstream, B_DIRECT_16x16, error_status, "mb type");
|
|
pu1_byte += sizeof(mb_hdr_bdirect_t);
|
|
|
|
}
|
|
else /* if mb_type == B16x16 */
|
|
{
|
|
mb_hdr_b16x16_t *ps_mb_hdr_b16x16 = (mb_hdr_b16x16_t *)ps_ent_ctxt->pv_mb_header_data;
|
|
|
|
/* inter macro block partition cnt for 16x16 16x8 8x16 8x8 */
|
|
const UWORD8 au1_part_cnt[] = { 1, 2, 2, 4 };
|
|
|
|
/* number of partitions for the current mb */
|
|
UWORD32 u4_part_cnt = au1_part_cnt[mb_type - B16x16];
|
|
|
|
/* Get the pred modes */
|
|
WORD32 i4_mb_part_pred_mode = (mb_tpm >> 4);
|
|
|
|
is_inter = 1;
|
|
|
|
mb_type_stream = mb_type - B16x16 + B_L0_16x16 + i4_mb_part_pred_mode;
|
|
|
|
/* write mb type */
|
|
PUT_BITS_UEV(ps_bitstream, mb_type_stream, error_status, "mb type");
|
|
|
|
for (i = 0; i < (WORD32)u4_part_cnt; i++)
|
|
{
|
|
if (i4_mb_part_pred_mode != PRED_L1)/* || PRED_BI */
|
|
{
|
|
PUT_BITS_SEV(ps_bitstream, ps_mb_hdr_b16x16->ai2_mv[0][0], error_status, "mv l0 x");
|
|
PUT_BITS_SEV(ps_bitstream, ps_mb_hdr_b16x16->ai2_mv[0][1], error_status, "mv l0 y");
|
|
}
|
|
if (i4_mb_part_pred_mode != PRED_L0)/* || PRED_BI */
|
|
{
|
|
PUT_BITS_SEV(ps_bitstream, ps_mb_hdr_b16x16->ai2_mv[1][0], error_status, "mv l1 x");
|
|
PUT_BITS_SEV(ps_bitstream, ps_mb_hdr_b16x16->ai2_mv[1][1], error_status, "mv l1 y");
|
|
}
|
|
}
|
|
|
|
pu1_byte += sizeof(mb_hdr_b16x16_t);
|
|
}
|
|
|
|
/* coded_block_pattern */
|
|
if (mb_type != I16x16)
|
|
{
|
|
PUT_BITS_UEV(ps_bitstream, gu1_cbp_map_tables[cbp][cbptable], error_status, "coded_block_pattern");
|
|
}
|
|
|
|
if (cbp || mb_type == I16x16)
|
|
{
|
|
/* mb_qp_delta */
|
|
PUT_BITS_SEV(ps_bitstream, mb_qp_delta, error_status, "mb_qp_delta");
|
|
}
|
|
|
|
/* Ending bitstream offset for header in bits */
|
|
bitstream_end_offset = GET_NUM_BITS(ps_bitstream);
|
|
|
|
ps_ent_ctxt->u4_header_bits[is_inter] += bitstream_end_offset - bitstream_start_offset;
|
|
|
|
/* start bitstream offset for residue in bits */
|
|
bitstream_start_offset = bitstream_end_offset;
|
|
|
|
/* residual */
|
|
error_status = ih264e_encode_residue(ps_ent_ctxt, mb_type, cbp);
|
|
|
|
/* Ending bitstream offset for residue in bits */
|
|
bitstream_end_offset = GET_NUM_BITS(ps_bitstream);
|
|
|
|
ps_ent_ctxt->u4_residue_bits[is_inter] += bitstream_end_offset - bitstream_start_offset;
|
|
|
|
/* store the index of the next mb syntax layer */
|
|
ps_ent_ctxt->pv_mb_header_data = pu1_byte;
|
|
|
|
return error_status;
|
|
}
|