📄 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)
*************************************************************************************
*/
#include "global.h"
#include "refbuf.h"
#include "image.h"
#include "errdo.h"
#include "errdo_mc_prediction.h"
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, 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
* 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)
{
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]), &(image->mb_pred[0][j][0]), image->mb_size[0][0] * sizeof(imgpel));
}
}
else
{
get_predicted_mb(enc_pic, image, decoder, currMB);
add_residue(enc_pic, decoder, PLANE_Y, 0, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
}
}
/*!
**************************************************************************************
* \brief
* Finds predicted macroblock values
* and copies them to img->mb_pred[0][][]
* Requires img->all_mv, enc_picture->motion.ref_idx to be correct for current
* macroblock.
**************************************************************************************
*/
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;
int list_offset = 0; //For now
int curr_mb_field = 0; //For now
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 (!currMB->mb_type)
{
block_size_x = MB_BLOCK_SIZE;
block_size_y = MB_BLOCK_SIZE;
pred_dir = LIST_0;
perform_mc(decoder, PLANE_Y, enc_pic, image, pred_dir, 0, 0, 0, 0, list_offset, block_size_x, block_size_y, curr_mb_field);
}
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, pred_dir, 1, 0, 0, 0, list_offset, block_size_x, block_size_y, curr_mb_field);
}
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, pred_dir, 2, 0, 0, block8x8, list_offset, block_size_x, block_size_y, curr_mb_field);
}
}
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];
assert (pred_dir<=2);
perform_mc(decoder, PLANE_Y, enc_pic, image, pred_dir, 3, 0, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
}
}
else //Need to change to support B slices.
{
for (block8x8 = 0; block8x8 < 4; block8x8++)
{
mv_mode = currMB->b8mode[block8x8];
pred_dir = currMB->b8pdir[block8x8];
if ( mv_mode != 0 )
{
k_start = (block8x8 << 2);
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, pred_dir, mv_mode, 0, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
}
}
}
}
}
/*!
**************************************************************************************
* \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, int decoder, int mbmode, int block8x8, short mv_mode, short b8ref) //b8ref may not be necessary any more.
{
int i,j,k;
int block_size_x, block_size_y;
int i0 = (block8x8 & 0x01)<<3;
int j0 = (block8x8 >> 1)<<3, j1 = j0+8;
int list_offset = 0;
int curr_mb_field = 0;
imgpel **curComp;
imgpel **oldComp;
int pred_dir;
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
{
pred_dir = 0;
k_start = (block8x8 << 2);
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, pred_dir, mv_mode, 0, i, j, list_offset, block_size_x, block_size_y, curr_mb_field);
}
add_residue(enc_pic, decoder, PLANE_Y, block8x8, 8, 8);
}
}
/*!
**************************************************************************************
* \brief
* Add residual to motion predicted block
**************************************************************************************
*/
static void add_residue (StorablePicture *enc_pic, 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][img->pix_y];
int (*res_img)[16] = decs->res_img[0];
imgpel (*mpr)[16] = img->mb_pred[pl];
for (j = j0; j < j1; j++)
{
for (i = i0; i < i1; i++)
{
p_dec_img[j][img->pix_x+i] = iClip3(0, img->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 copies the decoded images to the reference frame buffers of the decoders
*
*************************************************************************************
*/
void UpdateDecoders(InputParameters *params, ImageParameters *image, StorablePicture *enc_pic)
{
int k;
for (k = 0; k < params->NoOfDecoders; k++)
{
Build_Status_Map(enc_pic->mb_error_map[k]); // simulates the packet losses
error_conceal_picture(image, enc_pic, k);
DeblockFrame (image, enc_pic->p_dec_img[0][k], NULL);
}
}
/*!
*************************************************************************************
* \brief
* Initialize error concealment function
* (Currently only copy concealment is implemented. Can extend to other concealment
* types when available.)
*
*************************************************************************************
*/
void init_error_conceal(int concealment_type)
{
error_conceal_picture = copy_conceal_picture;
}
/*!
**************************************************************************************
* \brief
* Finds predicted macroblock values for error concealment
* and copies them to img->mb_pred[0][][]
* Requires enc_picture->motion.mv and enc_picture->motion.ref_idx to be correct for
* current picture.
**************************************************************************************
*/
static void get_predicted_concealment_mb(StorablePicture* enc_pic, ImageParameters* image, int decoder, Macroblock* currMB)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -