📄 errdo.c
字号:
/*!
*************************************************************************************
* \file errdo.c
*
* \brief
* Contains functions that implement the "decoders in the encoder" concept for the
* rate-distortion optimization with losses.
* \date
* October 22nd, 2001
*
* \author
* Main contributors (see contributors.h for copyright, address and
* affiliation details)
* - Dimitrios Kontopodis <dkonto@eikon.tum.de>
* Code revamped July 2008 by:
* - Peshala Pahalawatta (ppaha@dolby.com)
* - Alexis Tourapis (atour@dolby.com)
*************************************************************************************
*/
#include "global.h"
#include "memalloc.h"
#include "refbuf.h"
#include "image.h"
#include "errdo.h"
#include "errdo_mc_prediction.h"
Decoders *decs = NULL;
static StorablePicture* find_nearest_ref_picture(int poc);
static void copy_conceal_mb (StorablePicture *enc_pic, ImageParameters* image, int decoder, int mb_error, Macroblock* currMB, StorablePicture* refPic);
static void get_predicted_mb(StorablePicture *enc_pic, ImageParameters* image, int decoder, Macroblock* currMB);
static void add_residue (StorablePicture *enc_pic, ImageParameters* image, int decoder, int pl, int block8x8, int x_size, int y_size);
static void Build_Status_Map(byte **s_map);
extern void DeblockFrame(ImageParameters *img, imgpel **, imgpel ***);
/*!
**************************************************************************************
* \brief
* Allocate memory for error resilient RDO.
**************************************************************************************
*/
int allocate_errdo_mem(InputParameters *pparams)
{
int memory_size = 0;
decs = (Decoders *) malloc(sizeof(Decoders));
decs->dec_mb_pred = NULL;
decs->dec_mbY_best = NULL;
decs->dec_mb_pred_best8x8 = NULL;
decs->dec_mbY_best8x8 = NULL;
decs->res_img = NULL;
memory_size += get_mem3Dpel(&decs->dec_mb_pred, pparams->NoOfDecoders, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
memory_size += get_mem3Dpel(&decs->dec_mbY_best, pparams->NoOfDecoders, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
memory_size += get_mem4Dpel(&decs->dec_mbY_best8x8, 2, pparams->NoOfDecoders, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
memory_size += get_mem4Dpel(&decs->dec_mb_pred_best8x8, 2, pparams->NoOfDecoders, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
memory_size += get_mem3Dint(&decs->res_img, MAX_PLANE, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
return memory_size;
}
/*!
**************************************************************************************
* \brief
* free memory of error resilient RDO.
**************************************************************************************
*/
void free_errdo_mem(void)
{
if (decs->res_img)
{
free_mem3Dint(decs->res_img);
}
if (decs->dec_mb_pred)
{
free_mem3Dpel(decs->dec_mb_pred);
}
if (decs->dec_mbY_best)
{
free_mem3Dpel(decs->dec_mbY_best);
}
if (decs->dec_mbY_best8x8)
{
free_mem4Dpel(decs->dec_mbY_best8x8);
}
if (decs->dec_mb_pred_best8x8)
{
free_mem4Dpel(decs->dec_mb_pred_best8x8);
}
if ( decs != NULL )
free( decs );
}
/*!
**************************************************************************************
* \brief
* Decodes one macroblock for error resilient RDO.
* Currently does not support:
* 1) B coded pictures
* 2) Chroma components
* 3) Potential error propagation due to intra prediction
* 4) Field coding
**************************************************************************************
*/
void decode_one_mb (ImageParameters *image, StorablePicture *enc_pic, int decoder, Macroblock* currMB)
{
int i0, j;
static imgpel** curComp;
static imgpel** oldComp;
if (currMB->mb_type > P8x8) //Intra MB
{
curComp = &enc_pic->p_dec_img[0][decoder][image->pix_y];
oldComp = &enc_pic->p_curr_img[image->pix_y];
i0 = image->pix_x;
for (j = 0; j < MB_BLOCK_SIZE; j++)
{
memcpy(&(curComp[j][i0]), &(oldComp[j][i0]), MB_BLOCK_SIZE*sizeof(imgpel));
}
}
else if ((currMB->mb_type == 0) && (img->type != B_SLICE))
{
get_predicted_mb(enc_pic, image, decoder, currMB);
curComp = &enc_pic->p_dec_img[0][decoder][image->pix_y];
for(j = 0; j < image->mb_size[0][1]; j++)
{
memcpy(&(curComp[j][image->pix_x]), &(decs->dec_mb_pred[decoder][j][0]), image->mb_size[0][0] * sizeof(imgpel));
}
}
else
{
get_predicted_mb(enc_pic, image, decoder, currMB);
add_residue(enc_pic, image, decoder, PLANE_Y, 0, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
}
}
/*!
**************************************************************************************
* \brief
* Finds predicted macroblock values
* and copies them to img->mb_pred[0][][]
**************************************************************************************
*/
static void get_predicted_mb(StorablePicture *enc_pic, ImageParameters* image, int decoder, Macroblock* currMB)
{
int i,j,k;
int block_size_x, block_size_y;
int mv_mode, pred_dir;
static const byte decode_block_scan[16] = {0,1,4,5,2,3,6,7,8,9,12,13,10,11,14,15};
int block8x8;
int k_start, k_end, k_inc;
if (img->type == P_SLICE && !currMB->mb_type)
{
block_size_x = MB_BLOCK_SIZE;
block_size_y = MB_BLOCK_SIZE;
perform_mc(decoder, PLANE_Y, enc_pic, image, currMB, LIST_0, 0, 0, enc_pic->motion.ref_idx, 0, 0, block_size_x, block_size_y, 0);
}
else if (currMB->mb_type == 1)
{
block_size_x = MB_BLOCK_SIZE;
block_size_y = MB_BLOCK_SIZE;
pred_dir = currMB->b8pdir[0];
perform_mc(decoder, PLANE_Y, enc_pic, image, currMB, pred_dir, 1, 1, enc_pic->motion.ref_idx, 0, 0, block_size_x, block_size_y, currMB->bipred_me[0]);
}
else if (currMB->mb_type == 2)
{
block_size_x = MB_BLOCK_SIZE;
block_size_y = 8;
for (block8x8 = 0; block8x8 < 4; block8x8 += 2)
{
pred_dir = currMB->b8pdir[block8x8];
perform_mc(decoder, PLANE_Y, enc_pic, image, currMB, pred_dir, 2, 2, enc_pic->motion.ref_idx, 0, block8x8, block_size_x, block_size_y, currMB->bipred_me[block8x8]);
}
}
else if (currMB->mb_type == 3)
{
block_size_x = 8;
block_size_y = 16;
for (block8x8 = 0; block8x8 < 2; block8x8++)
{
i = block8x8<<1;
j = 0;
pred_dir = currMB->b8pdir[block8x8];
perform_mc(decoder, PLANE_Y, enc_pic, image, currMB, pred_dir, 3, 3, enc_pic->motion.ref_idx, i, j, block_size_x, block_size_y, currMB->bipred_me[block8x8]);
}
}
else
{
for (block8x8 = 0; block8x8 < 4; block8x8++)
{
mv_mode = currMB->b8mode[block8x8];
pred_dir = currMB->b8pdir[block8x8];
k_start = (block8x8 << 2);
k_inc = (mv_mode == 5) ? 2 : 1;
if (mv_mode == 0)
{
k_end = k_start + 1;
block_size_x = 8;
block_size_y = 8;
}
else
{
k_end = (mv_mode == 4) ? k_start + 1 : ((mv_mode == 7) ? k_start + 4 : k_start + k_inc + 1);
block_size_x = ( mv_mode == 5 || mv_mode == 4 ) ? 8 : 4;
block_size_y = ( mv_mode == 6 || mv_mode == 4 ) ? 8 : 4;
}
for (k = k_start; k < k_end; k += k_inc)
{
i = (decode_block_scan[k] & 3);
j = ((decode_block_scan[k] >> 2) & 3);
perform_mc(decoder, PLANE_Y, enc_pic, image, currMB, pred_dir, mv_mode, mv_mode, enc_pic->motion.ref_idx, i, j, block_size_x, block_size_y, currMB->bipred_me[block8x8]);
}
}
}
}
/*!
**************************************************************************************
* \brief
* Decodes one 8x8 partition for error resilient RDO.
* Currently does not support:
* 1) B coded pictures
* 2) Chroma components
* 3) Potential error propagation due to intra prediction
* 4) Field coding
**************************************************************************************
*/
void decode_one_b8block (ImageParameters *image, StorablePicture *enc_pic, Macroblock* currMB, int decoder, int block8x8, short mv_mode, int pred_dir)
{
int i,j,k;
int block_size_x, block_size_y;
int i0 = (block8x8 & 0x01)<<3;
int j0 = (block8x8 >> 1)<<3, j1 = j0+8;
char*** ref_idx_buf = enc_pic->motion.ref_idx;
imgpel **curComp;
imgpel **oldComp;
int k_start, k_end, k_inc;
static const byte decode_block_scan[16] = {0,1,4,5,2,3,6,7,8,9,12,13,10,11,14,15};
if (mv_mode > 8) //Intra
{
for(j = j0; j < j1; j++)
{
curComp = &enc_pic->p_dec_img[0][decoder][image->pix_y];
oldComp = &enc_pic->p_curr_img[image->pix_y];
memcpy(&(curComp[j][i0]), &(oldComp[j][i0]), sizeof(imgpel)*8);
}
}
else
{
k_start = (block8x8 << 2);
if (mv_mode == 0) //Direct
{
k_inc = 1;
k_end = k_start+1;
block_size_x = 8;
block_size_y = 8;
ref_idx_buf = direct_ref_idx;
}
else
{
k_inc = (mv_mode == 5) ? 2 : 1;
k_end = (mv_mode == 4) ? k_start + 1 : ((mv_mode == 7) ? k_start + 4 : k_start + k_inc + 1);
block_size_x = ( mv_mode == 5 || mv_mode == 4 ) ? 8 : 4;
block_size_y = ( mv_mode == 6 || mv_mode == 4 ) ? 8 : 4;
}
for (k = k_start; k < k_end; k += k_inc)
{
i = (decode_block_scan[k] & 3);
j = ((decode_block_scan[k] >> 2) & 3);
perform_mc(decoder, PLANE_Y, enc_pic, image, currMB, pred_dir, mv_mode, mv_mode, ref_idx_buf, i, j, block_size_x, block_size_y, currMB->bipred_me[block8x8]);
}
add_residue(enc_pic, image, decoder, PLANE_Y, block8x8, 8, 8);
}
}
/*!
**************************************************************************************
* \brief
* Add residual to motion predicted block
**************************************************************************************
*/
static void add_residue (StorablePicture *enc_pic, ImageParameters* image, int decoder, int pl, int block8x8, int x_size, int y_size)
{
int i,j;
int i0 = (block8x8 & 0x01)<<3, i1 = i0 + x_size;
int j0 = (block8x8 >> 1)<<3, j1 = j0 + y_size;
imgpel **p_dec_img = &enc_pic->p_dec_img[pl][decoder][image->pix_y];
int **res_img = decs->res_img[0];
imgpel** mpr = decs->dec_mb_pred[decoder];
for (j = j0; j < j1; j++)
{
for (i = i0; i < i1; i++)
{
p_dec_img[j][image->pix_x+i] = iClip3(0, image->max_imgpel_value_comp[pl], (mpr[j][i] + res_img[j][i]));
}
}
}
/*!
*************************************************************************************
* \brief
* Performs the simulation of the packet losses, calls the error concealment funcs
* and deblocks the error concealed pictures
*
*************************************************************************************
*/
void UpdateDecoders(InputParameters *params, ImageParameters *image, StorablePicture *enc_pic)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -