📄 cabac.c
字号:
/*!
*************************************************************************************
* \file cabac.c
*
* \brief
* CABAC entropy coding routines
*
* \author
* Main contributors (see contributors.h for copyright, address and affiliation details)
* - Detlev Marpe <marpe@hhi.de>
**************************************************************************************
*/
#include <stdlib.h>
#include <string.h>
#include "global.h"
#include "cabac.h"
#include "memalloc.h"
#include "elements.h"
#include "image.h"
#include "biaridecod.h"
#include "mb_access.h"
int symbolCount = 0;
int last_dquant = 0;
/***********************************************************************
* L O C A L L Y D E F I N E D F U N C T I O N P R O T O T Y P E S
***********************************************************************
*/
unsigned int unary_bin_decode(DecodingEnvironmentPtr dep_dp,
BiContextTypePtr ctx,
int ctx_offset);
unsigned int unary_bin_max_decode(DecodingEnvironmentPtr dep_dp,
BiContextTypePtr ctx,
int ctx_offset,
unsigned int max_symbol);
unsigned int unary_exp_golomb_level_decode( DecodingEnvironmentPtr dep_dp,
BiContextTypePtr ctx);
unsigned int unary_exp_golomb_mv_decode(DecodingEnvironmentPtr dep_dp,
BiContextTypePtr ctx,
unsigned int max_bin);
void CheckAvailabilityOfNeighborsCABAC()
{
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
PixelPos up, left;
getNeighbour(img->current_mb_nr, -1, 0, 1, &left);
getNeighbour(img->current_mb_nr, 0, -1, 1, &up);
if (up.available)
currMB->mb_available_up = &img->mb_data[up.mb_addr];
else
currMB->mb_available_up = NULL;
if (left.available)
currMB->mb_available_left = &img->mb_data[left.mb_addr];
else
currMB->mb_available_left = NULL;
}
void cabac_new_slice()
{
last_dquant=0;
}
/*!
************************************************************************
* \brief
* Allocation of contexts models for the motion info
* used for arithmetic decoding
*
************************************************************************
*/
MotionInfoContexts* create_contexts_MotionInfo(void)
{
MotionInfoContexts *deco_ctx;
deco_ctx = (MotionInfoContexts*) calloc(1, sizeof(MotionInfoContexts) );
if( deco_ctx == NULL )
no_mem_exit("create_contexts_MotionInfo: deco_ctx");
return deco_ctx;
}
/*!
************************************************************************
* \brief
* Allocates of contexts models for the texture info
* used for arithmetic decoding
************************************************************************
*/
TextureInfoContexts* create_contexts_TextureInfo(void)
{
TextureInfoContexts *deco_ctx;
deco_ctx = (TextureInfoContexts*) calloc(1, sizeof(TextureInfoContexts) );
if( deco_ctx == NULL )
no_mem_exit("create_contexts_TextureInfo: deco_ctx");
return deco_ctx;
}
/*!
************************************************************************
* \brief
* Frees the memory of the contexts models
* used for arithmetic decoding of the motion info.
************************************************************************
*/
void delete_contexts_MotionInfo(MotionInfoContexts *deco_ctx)
{
if( deco_ctx == NULL )
return;
free( deco_ctx );
return;
}
/*!
************************************************************************
* \brief
* Frees the memory of the contexts models
* used for arithmetic decoding of the texture info.
************************************************************************
*/
void delete_contexts_TextureInfo(TextureInfoContexts *deco_ctx)
{
if( deco_ctx == NULL )
return;
free( deco_ctx );
return;
}
void readFieldModeInfo_CABAC( SyntaxElement *se,
struct inp_par *inp,
struct img_par *img,
DecodingEnvironmentPtr dep_dp)
{
int a,b,act_ctx;
MotionInfoContexts *ctx = (img->currentSlice)->mot_ctx;
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
if (currMB->mbAvailA)
a = img->mb_data[currMB->mbAddrA].mb_field;
else
a = 0;
if (currMB->mbAvailB)
b = img->mb_data[currMB->mbAddrB].mb_field;
else
b=0;
act_ctx = a + b;
se->value1 = biari_decode_symbol (dep_dp, &ctx->mb_aff_contexts[act_ctx]);
#if TRACE
fprintf(p_trace, "@%d %s\t\t%d\n",symbolCount++, se->tracestring, se->value1);
fflush(p_trace);
#endif
}
int check_next_mb_and_get_field_mode_CABAC( SyntaxElement *se,
struct img_par *img,
struct inp_par *inp,
DataPartition *act_dp)
{
BiContextTypePtr mb_type_ctx_copy[4];
BiContextTypePtr mb_aff_ctx_copy;
DecodingEnvironmentPtr dep_dp_copy;
int length;
DecodingEnvironmentPtr dep_dp = &(act_dp->de_cabac);
int bframe = (img->type==B_SLICE);
int skip = 0;
int field = 0;
int i;
Macroblock *currMB;
//get next MB
img->current_mb_nr++;
currMB = &img->mb_data[img->current_mb_nr];
currMB->slice_nr = img->current_slice_nr;
currMB->mb_field = img->mb_data[img->current_mb_nr-1].mb_field;
CheckAvailabilityOfNeighbors();
CheckAvailabilityOfNeighborsCABAC();
//create
dep_dp_copy = (DecodingEnvironmentPtr) calloc(1, sizeof(DecodingEnvironment) );
for (i=0;i<4;i++)
mb_type_ctx_copy[i] = (BiContextTypePtr) calloc(NUM_MB_TYPE_CTX, sizeof(BiContextType) );
mb_aff_ctx_copy = (BiContextTypePtr) calloc(NUM_MB_AFF_CTX, sizeof(BiContextType) );
//copy
memcpy(dep_dp_copy,dep_dp,sizeof(DecodingEnvironment));
length = *(dep_dp_copy->Dcodestrm_len) = *(dep_dp->Dcodestrm_len);
for (i=0;i<4;i++)
memcpy(mb_type_ctx_copy[i], img->currentSlice->mot_ctx->mb_type_contexts[i],NUM_MB_TYPE_CTX*sizeof(BiContextType) );
memcpy(mb_aff_ctx_copy, img->currentSlice->mot_ctx->mb_aff_contexts,NUM_MB_AFF_CTX*sizeof(BiContextType) );
//check_next_mb
#if TRACE
strncpy(se->tracestring, "mb_skip_flag (of following bottom MB)", TRACESTRING_SIZE);
#endif
last_dquant = 0;
readMB_skip_flagInfo_CABAC(se,inp,img,dep_dp);
skip = (bframe)? (se->value1==0 && se->value2==0) : (se->value1==0);
if (!skip)
{
#if TRACE
strncpy(se->tracestring, "mb_field_decoding_flag (of following bottom MB)", TRACESTRING_SIZE);
#endif
readFieldModeInfo_CABAC( se,inp,img,dep_dp);
field = se->value1;
img->mb_data[img->current_mb_nr-1].mb_field = field;
}
//reset
img->current_mb_nr--;
memcpy(dep_dp,dep_dp_copy,sizeof(DecodingEnvironment));
*(dep_dp->Dcodestrm_len) = length;
for (i=0;i<4;i++)
memcpy(img->currentSlice->mot_ctx->mb_type_contexts[i],mb_type_ctx_copy[i], NUM_MB_TYPE_CTX*sizeof(BiContextType) );
memcpy( img->currentSlice->mot_ctx->mb_aff_contexts,mb_aff_ctx_copy,NUM_MB_AFF_CTX*sizeof(BiContextType) );
CheckAvailabilityOfNeighborsCABAC();
// CheckAvailabilityOfNeighbors(img);
//delete
free(dep_dp_copy);
for (i=0;i<4;i++)
free(mb_type_ctx_copy[i]);
free(mb_aff_ctx_copy);
return skip;
}
/*!
************************************************************************
* \brief
* This function is used to arithmetically decode the motion
* vector data of a B-frame MB.
************************************************************************
*/
void readMVD_CABAC( SyntaxElement *se,
struct inp_par *inp,
struct img_par *img,
DecodingEnvironmentPtr dep_dp)
{
int i = img->subblock_x;
int j = img->subblock_y;
int a, b;
int act_ctx;
int act_sym;
int mv_local_err;
int mv_sign;
int list_idx = se->value2 & 0x01;
int k = (se->value2>>1); // MVD component
PixelPos block_a, block_b;
MotionInfoContexts *ctx = img->currentSlice->mot_ctx;
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
getLuma4x4Neighbour(img->current_mb_nr, i, j, -1, 0, &block_a);
getLuma4x4Neighbour(img->current_mb_nr, i, j, 0, -1, &block_b);
if (block_b.available)
{
b = absm(img->mb_data[block_b.mb_addr].mvd[list_idx][block_b.y][block_b.x][k]);
if (img->MbaffFrameFlag && (k==1))
{
if ((currMB->mb_field==0) && (img->mb_data[block_b.mb_addr].mb_field==1))
b *= 2;
else if ((currMB->mb_field==1) && (img->mb_data[block_b.mb_addr].mb_field==0))
b /= 2;
}
}
else
b=0;
if (block_a.available)
{
a = absm(img->mb_data[block_a.mb_addr].mvd[list_idx][block_a.y][block_a.x][k]);
if (img->MbaffFrameFlag && (k==1))
{
if ((currMB->mb_field==0) && (img->mb_data[block_a.mb_addr].mb_field==1))
a *= 2;
else if ((currMB->mb_field==1) && (img->mb_data[block_a.mb_addr].mb_field==0))
a /= 2;
}
}
else
a = 0;
if ((mv_local_err=a+b)<3)
act_ctx = 5*k;
else
{
if (mv_local_err>32)
act_ctx=5*k+3;
else
act_ctx=5*k+2;
}
se->context = act_ctx;
act_sym = biari_decode_symbol(dep_dp,&ctx->mv_res_contexts[0][act_ctx] );
if (act_sym != 0)
{
act_ctx=5*k;
act_sym = unary_exp_golomb_mv_decode(dep_dp,ctx->mv_res_contexts[1]+act_ctx,3);
act_sym++;
mv_sign = biari_decode_symbol_eq_prob(dep_dp);
if(mv_sign)
act_sym = -act_sym;
}
se->value1 = act_sym;
#if TRACE
fprintf(p_trace, "@%d %s\t\t\t%d \n",symbolCount++, se->tracestring, se->value1);
fflush(p_trace);
#endif
}
/*!
************************************************************************
* \brief
* This function is used to arithmetically decode the 8x8 block type.
************************************************************************
*/
void readB8_typeInfo_CABAC (SyntaxElement *se,
struct inp_par *inp,
struct img_par *img,
DecodingEnvironmentPtr dep_dp)
{
int act_sym = 0;
int bframe = (img->type==B_SLICE);
MotionInfoContexts *ctx = (img->currentSlice)->mot_ctx;
if (!bframe)
{
if (biari_decode_symbol (dep_dp, &ctx->b8_type_contexts[0][1]))
{
act_sym = 0;
}
else
{
if (biari_decode_symbol (dep_dp, &ctx->b8_type_contexts[0][3]))
{
if (biari_decode_symbol (dep_dp, &ctx->b8_type_contexts[0][4])) act_sym = 2;
else act_sym = 3;
}
else
{
act_sym = 1;
}
}
}
else
{
if (biari_decode_symbol (dep_dp, &ctx->b8_type_contexts[1][0]))
{
if (biari_decode_symbol (dep_dp, &ctx->b8_type_contexts[1][1]))
{
if (biari_decode_symbol (dep_dp, &ctx->b8_type_contexts[1][2]))
{
if (biari_decode_symbol (dep_dp, &ctx->b8_type_contexts[1][3]))
{
act_sym = 10;
if (biari_decode_symbol (dep_dp, &ctx->b8_type_contexts[1][3])) act_sym++;
}
else
{
act_sym = 6;
if (biari_decode_symbol (dep_dp, &ctx->b8_type_contexts[1][3])) act_sym+=2;
if (biari_decode_symbol (dep_dp, &ctx->b8_type_contexts[1][3])) act_sym++;
}
}
else
{
act_sym=2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -