📄 rdopt.c
字号:
/*!
***************************************************************************
* \file rdopt.c
*
* \brief
* Rate-Distortion optimized mode decision
*
* \author
* - Heiko Schwarz <hschwarz@hhi.de>
* - Valeri George <george@hhi.de>
* - Lowell Winger <lwinger@lsil.com>
* - Alexis Michael Tourapis <alexismt@ieee.org>
* \date
* 12. April 2001
**************************************************************************
*/
#include <math.h>
#include <limits.h>
#include "global.h"
#include "rdopt.h"
#include "q_around.h"
#include "rdopt_coding_state.h"
#include "memalloc.h"
#include "mb_access.h"
#include "elements.h"
#include "intrarefresh.h"
#include "image.h"
#include "transform8x8.h"
#include "cabac.h"
#include "vlc.h"
#include "me_umhex.h"
#include "ratectl.h" // head file for rate control
#include "mode_decision.h"
#include "rd_intra_jm.h"
#include "fmo.h"
#include "macroblock.h"
#include "symbol.h"
#include "q_offsets.h"
#include "conformance.h"
#include "errdo.h"
imgpel pred[16][16];
#define FASTMODE 1
//#define RESET_STATE
imgpel rec_mbY[16][16], rec_mb_cr[2][16][16]; // reconstruction values
int lrec_rec[MB_BLOCK_SIZE][MB_BLOCK_SIZE],lrec_rec_uv[2][MB_BLOCK_SIZE][MB_BLOCK_SIZE]; // store the transf. and quantized coefficients for SP frames
static int diff[16];
static int diff4x4[64];
static int diff8x8[64];
RD_8x8DATA tr4x4, tr8x8;
int ****cofAC=NULL, ****cofAC8x8=NULL; // [8x8block][4x4block][level/run][scan_pos]
int ***cofDC=NULL; // [yuv][level/run][scan_pos]
int **cofAC4x4=NULL, ****cofAC4x4intern=NULL; // [level/run][scan_pos]
int cbp, cbp8x8, cnt_nonz_8x8;
int cbp_blk8x8;
char l0_refframe[4][4], l1_refframe[4][4];
short b8mode[4], b8pdir[4], b8bipred_me[4];
CSptr cs_mb=NULL, cs_b8=NULL, cs_cm=NULL, cs_ib8=NULL, cs_ib4=NULL;
int best_c_imode;
int best_i16offset;
short best_mode;
//mixed transform sizes definitions
int luma_transform_size_8x8_flag;
short all_mv8x8[2][2][4][4][2]; //[8x8_data/temp_data][LIST][block_x][block_y][MVx/MVy]
short pred_mv8x8[2][2][4][4][2];
int ****cofAC8x8ts[3] = {NULL, NULL, NULL}; // [plane][8x8block][4x4block][level/run][scan_pos]
int ****cofAC8x8CbCr[2];
int **cofAC4x4CbCr[2];
int ****cofAC4x4CbCrintern[2];
int64 cbp_blk8_8x8ts;
int cbp8_8x8ts;
int cost8_8x8ts;
int cnt_nonz8_8x8ts;
// adaptive langrangian parameters
double mb16x16_cost;
double lambda_mf_factor;
void StoreMV8x8(int dir);
void RestoreMV8x8(int dir);
// end of mixed transform sizes definitions
char b4_ipredmode[16], b4_intra_pred_modes[16];
/*!
************************************************************************
* \brief
* delete structure for RD-optimized mode decision
************************************************************************
*/
void clear_rdopt (InputParameters *params)
{
free_mem_DCcoeff (cofDC);
free_mem_ACcoeff (cofAC);
free_mem_ACcoeff (cofAC8x8);
free_mem_ACcoeff (cofAC4x4intern);
if (params->Transform8x8Mode)
{
free_mem_ACcoeff (cofAC8x8ts[0]);
//if (img->P444_joined)
{
free_mem_ACcoeff (cofAC8x8ts[1]);
free_mem_ACcoeff (cofAC8x8ts[2]);
}
}
//if (img->P444_joined)
{
free_mem_ACcoeff (cofAC8x8CbCr[0]);
free_mem_ACcoeff (cofAC8x8CbCr[1]);
free_mem_ACcoeff (cofAC4x4CbCrintern[0]);
free_mem_ACcoeff (cofAC4x4CbCrintern[1]);
}
if (params->AdaptiveRounding)
{
clear_adaptive_rounding (params);
}
// structure for saving the coding state
delete_coding_state (cs_mb);
delete_coding_state (cs_b8);
delete_coding_state (cs_cm);
delete_coding_state (cs_ib8);
delete_coding_state (cs_ib4);
}
/*!
************************************************************************
* \brief
* create structure for RD-optimized mode decision
************************************************************************
*/
void init_rdopt (InputParameters *params)
{
rdopt = NULL;
get_mem_DCcoeff (&cofDC);
get_mem_ACcoeff (&cofAC);
get_mem_ACcoeff (&cofAC8x8);
get_mem_ACcoeff (&cofAC4x4intern);
cofAC4x4 = cofAC4x4intern[0][0];
if (params->Transform8x8Mode)
{
get_mem_ACcoeff (&cofAC8x8ts[0]);
//if (img->P444_joined)
{
get_mem_ACcoeff (&cofAC8x8ts[1]);
get_mem_ACcoeff (&cofAC8x8ts[2]);
}
}
//if (img->P444_joined)
{
get_mem_ACcoeff (&cofAC8x8CbCr[0]);
get_mem_ACcoeff (&cofAC8x8CbCr[1]);
get_mem_ACcoeff (&cofAC4x4CbCrintern[0]);
get_mem_ACcoeff (&cofAC4x4CbCrintern[1]);
cofAC4x4CbCr[0] = cofAC4x4CbCrintern[0][0][0];
cofAC4x4CbCr[1] = cofAC4x4CbCrintern[1][0][0];
}
SetLagrangianMultipliers = params->rdopt == 0 ? SetLagrangianMultipliersOff : SetLagrangianMultipliersOn;
switch (params->rdopt)
{
case 0:
encode_one_macroblock = encode_one_macroblock_low;
break;
case 1:
default:
encode_one_macroblock = encode_one_macroblock_high;
break;
case 2:
encode_one_macroblock = encode_one_macroblock_highfast;
break;
case 3:
encode_one_macroblock = encode_one_macroblock_highloss;
break;
}
if (params->AdaptiveRounding)
{
setup_adaptive_rounding (params);
}
// structure for saving the coding state
cs_mb = create_coding_state ();
cs_b8 = create_coding_state ();
cs_cm = create_coding_state ();
cs_ib8 = create_coding_state ();
cs_ib4 = create_coding_state ();
if (params->CtxAdptLagrangeMult == 1)
{
mb16x16_cost = CALM_MF_FACTOR_THRESHOLD;
lambda_mf_factor = 1.0;
}
getDistortion = distortionSSE;
}
/*!
*************************************************************************************
* \brief
* Updates the pixel map that shows, which reference frames are reliable for
* each MB-area of the picture.
*
* \note
* The new values of the pixel_map are taken from the temporary buffer refresh_map
*
*************************************************************************************
*/
void UpdatePixelMap()
{
int mx,my,y,x,i,j;
if (img->type==I_SLICE)
{
memset(pixel_map, 1, img->height * img->width * sizeof(byte));
}
else
{
for (my=0; my<img->height >> 3; my++)
for (mx=0; mx<img->width >> 3; mx++)
{
j = my*8 + 8;
i = mx*8 + 8;
if (refresh_map[my][mx])
{
for (y=my*8; y<j; y++)
memset(&pixel_map[y][mx*8], 1, 8 * sizeof(byte));
}
else
{
for (y=my*8; y<j; y++)
for (x=mx*8; x<i; x++)
{
pixel_map[y][x] = imin(pixel_map[y][x] + 1, params->num_ref_frames+1);
}
}
}
}
}
/*!
*************************************************************************************
* \brief
* Checks if a given reference frame is reliable for the current
* macroblock, given the motion vectors that the motion search has
* returned.
*
* \return
* If the return value is 1, the reference frame is reliable. If it
* is 0, then it is not reliable.
*
* \note
* A specific area in each reference frame is assumed to be unreliable
* if the same area has been intra-refreshed in a subsequent frame.
* The information about intra-refreshed areas is kept in the pixel_map.
*
*************************************************************************************
*/
int CheckReliabilityOfRef (int block, int list_idx, int ref, int mode)
{
int y,x, block_y, block_x, dy, dx, y_pos, x_pos, yy, xx, pres_x, pres_y;
int maxold_x = img->width-1;
int maxold_y = img->height-1;
int ref_frame = ref + 1;
int by0 = (mode>=4?2*(block >> 1):mode==2?2*block:0);
int by1 = by0 + (mode>=4||mode==2?2:4);
int bx0 = (mode>=4?2*(block & 0x01):mode==3?2*block:0);
int bx1 = bx0 + (mode>=4||mode==3?2:4);
for (block_y=by0; block_y<by1; block_y++)
{
for (block_x=bx0; block_x<bx1; block_x++)
{
y_pos = img->all_mv[list_idx][ref][mode][block_y][block_x][1];
y_pos += (img->block_y + block_y) * BLOCK_SIZE * 4;
x_pos = img->all_mv[list_idx][ref][mode][block_y][block_x][0];
x_pos += (img->block_x + block_x) * BLOCK_SIZE * 4;
/* Here we specify which pixels of the reference frame influence
the reference values and check their reliability. This is
based on the function Get_Reference_Pixel */
dy = y_pos & 3;
dx = x_pos & 3;
y_pos = (y_pos - dy) >> 2;
x_pos = (x_pos - dx) >> 2;
if (dy==0 && dx==0) //full-pel
{
for (y=y_pos ; y < y_pos + BLOCK_SIZE ; y++)
for (x=x_pos ; x < x_pos + BLOCK_SIZE ; x++)
if (pixel_map[iClip3(0,maxold_y,y)][iClip3(0,maxold_x,x)] < ref_frame)
return 0;
}
else /* other positions */
{
if (dy == 0)
{
for (y = y_pos ; y < y_pos + BLOCK_SIZE ; y++)
{
pres_y = iClip3(0, maxold_y, y);
for (x = x_pos ; x < x_pos + BLOCK_SIZE ; x++)
{
for(xx = -2 ; xx < 4 ; xx++)
{
pres_x = iClip3(0, maxold_x, x + xx);
if (pixel_map[pres_y][pres_x] < ref_frame)
return 0;
}
}
}
}
else if (dx == 0)
{
for (y = y_pos ; y < y_pos + BLOCK_SIZE ; y++)
for (x=x_pos ; x < x_pos + BLOCK_SIZE ; x++)
{
pres_x = iClip3(0,maxold_x,x);
for(yy=-2;yy<4;yy++)
{
pres_y = iClip3(0,maxold_y, yy + y);
if (pixel_map[pres_y][pres_x] < ref_frame)
return 0;
}
}
}
else if (dx == 2)
{
for (y = y_pos ; y < y_pos + BLOCK_SIZE ; y++)
for (x = x_pos ; x < x_pos + BLOCK_SIZE ; x++)
{
for(yy=-2;yy<4;yy++)
{
pres_y = iClip3(0,maxold_y, yy + y);
for(xx=-2;xx<4;xx++)
{
pres_x = iClip3(0,maxold_x, xx + x);
if (pixel_map[pres_y][pres_x] < ref_frame)
return 0;
}
}
}
}
else if (dy == 2)
{
for (y = y_pos ; y < y_pos + BLOCK_SIZE ; y++)
for (x = x_pos ; x < x_pos + BLOCK_SIZE ; x++)
{
for(xx=-2;xx<4;xx++)
{
pres_x = iClip3(0,maxold_x, xx + x);
for(yy=-2;yy<4;yy++)
{
pres_y = iClip3(0,maxold_y, yy + y);
if (pixel_map[pres_y][pres_x] < ref_frame)
return 0;
}
}
}
}
else
{
for (y = y_pos ; y < y_pos + BLOCK_SIZE ; y++)
{
for (x = x_pos ; x < x_pos + BLOCK_SIZE ; x++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -