📄 cabac.c
字号:
/*
***********************************************************************
* COPYRIGHT AND WARRANTY INFORMATION
*
* Copyright 2001, International Telecommunications Union, Geneva
*
* DISCLAIMER OF WARRANTY
*
* These software programs are available to the user without any
* license fee or royalty on an "as is" basis. The ITU disclaims
* any and all warranties, whether express, implied, or
* statutory, including any implied warranties of merchantability
* or of fitness for a particular purpose. In no event shall the
* contributor or the ITU be liable for any incidental, punitive, or
* consequential damages of any kind whatsoever arising from the
* use of these programs.
*
* This disclaimer of warranty extends to the user of these programs
* and user's customers, employees, agents, transferees, successors,
* and assigns.
*
* The ITU does not represent or warrant that the programs furnished
* hereunder are free of infringement of any third-party patents.
* Commercial implementations of ITU-T Recommendations, including
* shareware, may be subject to royalty fees to patent holders.
* Information regarding the ITU-T patent policy is available from
* the ITU Web site at http://www.itu.int.
*
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE ITU-T PATENT POLICY.
************************************************************************
*/
/*!
*************************************************************************************
* \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 <math.h>
#include <memory.h>
#include <assert.h> // for debugging
#include <string.h>
#include "cabac.h"
#include "memalloc.h"
#include "header.h"
#include "elements.h"
#include "global.h"
int symbolCount = 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 readFieldModeInfoFromBuffer_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->map_mb_nr];//GB current_mb_nr];
if (currMB->field_available[0] == NULL)
b = 0;
else
b = currMB->field_available[0]->mb_field;
if (currMB->field_available[1] == NULL)
a = 0;
else
a = currMB->field_available[1]->mb_field;
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++;
setMapMB_nr(img);
currMB = &img->mb_data[img->map_mb_nr];
currMB->slice_nr = img->current_slice_nr;
CheckAvailabilityOfNeighborsForAff(img);
CheckAvailabilityOfNeighbors(img);
//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, "Check MB skipflag", TRACESTRING_SIZE);
#endif
readMB_skip_flagInfoFromBuffer_CABAC(se,inp,img,dep_dp);
skip = (bframe)? (se->value1==0 && se->value2==0) : (se->value1==0);
if (!skip)
{
#if TRACE
strncpy(se->tracestring, "Get Field mode", TRACESTRING_SIZE);
#endif
readFieldModeInfoFromBuffer_CABAC( se,inp,img,dep_dp);
field = se->value1;
}
//reset
img->current_mb_nr--;
setMapMB_nr(img);
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) );
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 readBiMVD2Buffer_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 backward = se->value2 & 0x01;
int k = (se->value2>>1); // MVD component
MotionInfoContexts *ctx = img->currentSlice->mot_ctx;
Macroblock *currMB = &img->mb_data[img->map_mb_nr];//GB current_mb_nr];
if (j==0)
{
if (currMB->mb_available[0][1] == NULL)
b = 0;
else
{
b = absm((currMB->mb_available[0][1])->mvd[backward][BLOCK_SIZE-1][i][k]);
if (img->structure==FRAME && img->mb_frame_field_flag && (k==1))
{
if ((currMB->mb_field==0) && (currMB->mb_available[0][1]->mb_field==1))
b *= 2;
else if ((currMB->mb_field==1) && (currMB->mb_available[0][1]->mb_field==0))
b /= 2;
}
}
}
else
b = absm(currMB->mvd[backward][j-1/*step_v*/][i][k]);
if (i==0)
{
if (currMB->mb_available[1][0] == NULL)
a = 0;
else
{
a = absm((currMB->mb_available[1][0])->mvd[backward][j][BLOCK_SIZE-1][k]);
if (img->structure==FRAME && img->mb_frame_field_flag && (k==1))
{
if ((currMB->mb_field==0) && (currMB->mb_available[1][0]->mb_field==1))
a *= 2;
else if ((currMB->mb_field==1) && (currMB->mb_available[1][0]->mb_field==0))
a /= 2;
}
}
}
else
a = absm(currMB->mvd[backward][j][i-1/*step_h*/][k]);
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_typeInfoFromBuffer_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;
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+=1;
}
}
else
{
if (biari_decode_symbol (dep_dp, &ctx->b8_type_contexts[1][3])) act_sym = 1;
else act_sym = 0;
}
act_sym++;
}
else
{
act_sym= 0;
}
}
se->value1 = act_sym;
// if (act_sym == 13) printf(" stop");
}
/*!
************************************************************************
* \brief
* This function is used to arithmetically decode the macroblock
* type info of a given MB.
************************************************************************
*/
void readMB_skip_flagInfoFromBuffer_CABAC( SyntaxElement *se,
struct inp_par *inp,
struct img_par *img,
DecodingEnvironmentPtr dep_dp)
{
int a, b;
int act_ctx;
int bframe=(img->type==B_SLICE);
MotionInfoContexts *ctx = (img->currentSlice)->mot_ctx;
Macroblock *currMB = &img->mb_data[img->map_mb_nr];//GB current_mb_nr];
if (bframe)
{
if (currMB->mb_available[0][1] == NULL)
b = 0;
else
b = (currMB->mb_available[0][1]->mb_type==0 && currMB->mb_available[0][1]->cbp==0 ? 0 : 1);
if (currMB->mb_available[1][0] == NULL)
a = 0;
else
a = (currMB->mb_available[1][0]->mb_type==0 && currMB->mb_available[1][0]->cbp==0 ? 0 : 1);
act_ctx = 7 + a + b;
if (biari_decode_symbol (dep_dp, &ctx->mb_type_contexts[2][act_ctx]) == 1)
se->value1 = se->value2 = 0;
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -