📄 rdopt.c
字号:
/***************************************************************************
*
* Modul : rdopt.c
* Author : Heiko Schwarz <hschwarz@hhi.de>
* Date : 12. April 2001
*
* Description : Rate-Distortion optimized mode decision
*
**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <memory.h>
#include "rdopt.h"
#ifdef _RD_OPT_
#ifdef USE_9_INTRA_MODES
extern const byte PRED_IPRED[10][10][9];
#else // !USE_9_INTRA_MODES
extern const byte PRED_IPRED[7][7][6];
#endif
extern int QP2QUANT [32];
/*=== static parameters ===*/
RDOpt *rdopt = NULL;
int *forward_me_done[9];
int *tot_for_sad[9];
/************************************************************************
*
* Name : clear_rdopt()
*
* Description: delete structure for RD-optimized mode decision
*
************************************************************************/
void
clear_rdopt ()
{
int i;
/* rd-optimization structure */
if (rdopt != NULL)
{
free (rdopt);
rdopt = NULL;
for (i=0; i<9; i++)
{
free (forward_me_done[i]);
free (tot_for_sad [i]);
}
}
/* structure for saving the coding state */
clear_coding_state ();
}
/************************************************************************
*
* Name : init_rdopt()
*
* Description: create structure for RD-optimized mode decision
*
************************************************************************/
void
init_rdopt ()
{
int i;
if (!input->rdopt)
return;
clear_rdopt ();
/* rd-optimization structure */
if ((rdopt = (RDOpt*) calloc (1, sizeof(RDOpt))) == NULL)
{
fprintf (stderr, "Memory allocation for RDOpt datastruct failed\n");
exit(1);
}
for (i=0; i<9; i++)
{
if ((forward_me_done[i] = (int*)malloc (img->buf_cycle*sizeof(int))) == NULL) no_mem_exit (1);
if ((tot_for_sad [i] = (int*)malloc (img->buf_cycle*sizeof(int))) == NULL) no_mem_exit (1);
}
/* structure for saving the coding state */
init_coding_state ();
}
/************************************************************************
*
* Name : RDCost_Intra4x4_Block()
*
* Description: set Rate-Distortion cost of 4x4 Intra modes
*
************************************************************************/
void
RDCost_Intra4x4_Block (int block_x,
int block_y,
int ipmode)
{
int dummy, left_ipmode, upper_ipmode, curr_ipmode, x, y;
int i = block_x >> 2;
int j = block_y >> 2;
int pic_block_x = (img->pix_x+block_x) / BLOCK_SIZE;
int pic_block_y = (img->pix_y+block_y) / BLOCK_SIZE;
int even_block = ((i & 1) == 1);
Slice *currSlice = img->currentSlice;
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
SyntaxElement *currSE = &img->MB_SyntaxElements[currMB->currSEnr];
int *partMap = assignSE2partition[input->partition_mode];
DataPartition *dataPart;
/*===== perform DCT, Q, IQ, IDCT =====*/
dct_luma (block_x, block_y, &dummy);
/*===== get distortion (SSD) of 4x4 block =====*/
for (y=0; y < BLOCK_SIZE; y++)
for (x=0; x < BLOCK_SIZE; x++)
{
dummy = imgY_org[img->pix_y+block_y+y][img->pix_x+block_x+x] - img->m7[x][y];
rdopt->distortion_4x4[j][i][ipmode] += img->quad[abs(dummy)];
}
rdopt->rdcost_4x4[j][i][ipmode] = (double)rdopt->distortion_4x4[j][i][ipmode];
if (rdopt->rdcost_4x4[j][i][ipmode] >= rdopt->min_rdcost_4x4[j][i])
return;
/*===== store the coding state =====*/
store_coding_state ();
/*===== get (estimate) rate for intra prediction mode =====*/
/*--- set or estimate the values of syntax element ---*/
if (even_block)
/* EVEN BLOCK: the values the of syntax element can be set correctly */
{
/* value of last block */
upper_ipmode = img->ipredmode [pic_block_x ][pic_block_y ];
left_ipmode = img->ipredmode [pic_block_x-1][pic_block_y+1];
curr_ipmode = img->ipredmode [pic_block_x ][pic_block_y+1];
currSE->value1 = PRED_IPRED [upper_ipmode+1][left_ipmode+1][curr_ipmode];
/* value of this block */
upper_ipmode = img->ipredmode [pic_block_x+1][pic_block_y ];
currSE->value2 = PRED_IPRED [upper_ipmode+1][curr_ipmode+1][ipmode];
}
else
/* ODD BLOCK: the second value of the syntax element cannot be set, since
* it will be known only after the next step. For estimating
* the rate the corresponding prediction mode is set to zero
* (minimum rate). */
{
upper_ipmode = img->ipredmode [pic_block_x+1][pic_block_y ];
left_ipmode = img->ipredmode [pic_block_x ][pic_block_y+1];
currSE->value1 = PRED_IPRED [upper_ipmode+1][left_ipmode+1][ipmode];
currSE->value2 = 0; /* value with maximum probability */
}
/*--- set function pointers for syntax element ---*/
if (input->symbol_mode == UVLC) currSE->mapping = intrapred_linfo;
else currSE->writing = writeIntraPredMode2Buffer_CABAC;
currSE->type = SE_INTRAPREDMODE;
/*--- choose the appropriate data partition ---*/
if (img->type != B_IMG) dataPart = &(currSlice->partArr[partMap[SE_INTRAPREDMODE]]);
else dataPart = &(currSlice->partArr[partMap[SE_BFRAME]]);
/*--- get length of syntax element ---*/
dataPart->writeSyntaxElement (currSE, dataPart);
rdopt->rate_imode_4x4[j][i][ipmode] = currSE->len;
rdopt->rdcost_4x4[j][i][ipmode] += rdopt->lambda_intra*(double)rdopt->rate_imode_4x4[j][i][ipmode];
if (rdopt->rdcost_4x4[j][i][ipmode] >= rdopt->min_rdcost_4x4[j][i])
{
restore_coding_state ();
return;
}
currSE++;
currMB->currSEnr++;
/*===== get rate for luminance coefficients =====*/
rdopt->rate_luma_4x4[j][i][ipmode] = writeMB_bits_for_4x4_luma (i, j, 0);
rdopt->rdcost_4x4[j][i][ipmode] += rdopt->lambda_intra*(double)rdopt->rate_luma_4x4[j][i][ipmode];
/*===== restore the saved coding state =====*/
restore_coding_state ();
/*===== update best mode =====*/
if (rdopt->rdcost_4x4[j][i][ipmode] < rdopt->min_rdcost_4x4[j][i])
{
rdopt->best_mode_4x4 [j][i] = ipmode;
rdopt->min_rdcost_4x4[j][i] = rdopt->rdcost_4x4[j][i][ipmode];
}
}
/************************************************************************
*
* Name : RD_Intra4x4_Mode_Decision()
*
* Description: Get best 4x4 Intra mode by rate-dist-based decision
*
************************************************************************/
int
RD_Intra4x4_Mode_Decision (int block_x,
int block_y)
{
int ipmode, i, j;
int index_y = block_y >> 2;
int index_x = block_x >> 2;
int pic_pix_y = img->pix_y + block_y;
int pic_pix_x = img->pix_x + block_x;
int pic_block_y = pic_pix_y / BLOCK_SIZE;
int pic_block_x = pic_pix_x / BLOCK_SIZE;
typedef int (*WRITE_SE)(SyntaxElement*, struct datapartition*);
WRITE_SE *writeSE=0;
int symbol_mode;
/*=== set symbol mode to UVLC (CABAC does not work correctly -> wrong coding order) ===*
*=== and store the original symbol mode and function pointers ===*/
symbol_mode = input->symbol_mode;
if (input->symbol_mode != UVLC)
{
input->symbol_mode = UVLC;
if ((writeSE = (WRITE_SE*) calloc (img->currentSlice->max_part_nr, sizeof (WRITE_SE))) == NULL)
{
fprintf (stderr, "Memory allocation in RDGet_4x4IntraMode failed!\n");
exit (1);
}
for (i=0; i<img->currentSlice->max_part_nr; i++)
{
writeSE[i] = img->currentSlice->partArr[i].writeSyntaxElement;
img->currentSlice->partArr[i].writeSyntaxElement = writeSyntaxElement_UVLC;
}
}
/*=== LOOP OVER ALL 4x4 INTRA PREDICTION MODES ===*/
rdopt->best_mode_4x4 [index_y][index_x] = -1;
rdopt->min_rdcost_4x4[index_y][index_x] = 1e30;
for (ipmode=0; ipmode < NO_INTRA_PMODE; ipmode++)
{
rdopt->rdcost_4x4 [index_y][index_x][ipmode] = -1;
rdopt->distortion_4x4[index_y][index_x][ipmode] = 0;
rdopt->rate_imode_4x4[index_y][index_x][ipmode] = 0;
rdopt->rate_luma_4x4 [index_y][index_x][ipmode] = 0;
/* Horizontal pred from Y neighbour pix , vertical use X pix, diagonal needs both */
if (ipmode==DC_PRED || ipmode==HOR_PRED || img->ipredmode[pic_block_x+1][pic_block_y] >= 0)
/* DC or vert pred or hor edge*/
{
if (ipmode==DC_PRED || ipmode==VERT_PRED || img->ipredmode[pic_block_x][pic_block_y+1] >= 0)
/* DC or hor pred or vert edge*/
{
/* find diff */
for (j=0; j < BLOCK_SIZE; j++)
for (i=0; i < BLOCK_SIZE; i++)
img->m7[i][j] = imgY_org[pic_pix_y+j][pic_pix_x+i] - img->mprr[ipmode][j][i];
/* copy intra prediction block */
for (j=0; j < BLOCK_SIZE; j++)
for (i=0; i < BLOCK_SIZE; i++)
img->mpr[i+block_x][j+block_y] = img->mprr[ipmode][j][i];
/* get lagrangian cost */
RDCost_Intra4x4_Block (block_x, block_y, ipmode);
}
}
}
/*=== restore the original symbol mode and function pointers ===*/
if (symbol_mode != UVLC)
{
input->symbol_mode = symbol_mode;
for (i=0; i<img->currentSlice->max_part_nr; i++)
{
img->currentSlice->partArr[i].writeSyntaxElement = writeSE[i];
}
free (writeSE);
}
return rdopt->best_mode_4x4[index_y][index_x];
}
/************************************************************************
*
* Name : Intra4x4_Mode_Decision ()
*
* Description: Rate-Distortion opt. mode decision for 4x4 intra blocks
*
************************************************************************/
void
Intra4x4_Mode_Decision ()
{
int i,j;
int block_x, block_y;
int best_ipmode;
int coeff_cost; // not used
int pic_pix_y,pic_pix_x,pic_block_y,pic_block_x;
int last_ipred=0; /* keeps last chosen intra prediction mode for 4x4 intra pred */
int nonzero; /* keep track of nonzero coefficients */
int cbp_mask;
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
/* start making 4x4 intra prediction */
currMB->cbp=0;
img->mb_data[img->current_mb_nr].intraOrInter = INTRA_MB_4x4;
for(block_y = 0 ; block_y < MB_BLOCK_SIZE ; block_y += BLOCK_MULTIPLE)
{
pic_pix_y=img->pix_y+block_y;
pic_block_y=pic_pix_y/BLOCK_SIZE;
for(block_x = 0 ; block_x < MB_BLOCK_SIZE ; block_x += BLOCK_MULTIPLE)
{
cbp_mask=(1<<(2*(block_y/8)+block_x/8));
pic_pix_x=img->pix_x+block_x;
pic_block_x=pic_pix_x/BLOCK_SIZE;
/*
intrapred_luma() makes and returns 4x4 blocks with all 5 intra prediction modes.
Notice that some modes are not possible at frame edges.
*/
intrapred_luma (pic_pix_x,pic_pix_y);
/*=== rate-constrained mode decision ===*/
best_ipmode = RD_Intra4x4_Mode_Decision (block_x, block_y);
img->ipredmode[pic_block_x+1][pic_block_y+1]=best_ipmode;
if ((pic_block_x & 1) == 1) /* just even blocks, two and two predmodes are sent together */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -