📄 rdopt.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 rdopt.c
*
* \brief
* Rate-Distortion optimized mode decision
*
* \author
* Heiko Schwarz <hschwarz@hhi.de>
*
* \date
* 12. April 2001
**************************************************************************
*/
#include <stdlib.h>
#include <math.h>
#include <memory.h>
#include "rdopt.h"
#include "refbuf.h"
extern const byte PRED_IPRED[7][7][6];
extern int QP2QUANT [32];
//=== static parameters ===
RDOpt *rdopt = NULL;
int *forward_me_done[9];
int *tot_for_sad[9];
/*!
************************************************************************
* \brief
* 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 ();
}
/*!
************************************************************************
* \brief
* 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)
{
no_mem_exit ("init_rdopt: rdopt");
}
for (i=0; i<9; i++)
{
if ((forward_me_done[i] = (int*)malloc (img->buf_cycle*sizeof(int))) == NULL) no_mem_exit ("init_rdopt: forward_me_done");
if ((tot_for_sad [i] = (int*)malloc (img->buf_cycle*sizeof(int))) == NULL) no_mem_exit ("init_rdopt: tot_for_sad");
}
// structure for saving the coding state
init_coding_state ();
}
/*!
************************************************************************
* \brief
* 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];
}
}
/*!
************************************************************************
* \brief
* 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)
{
no_mem_exit ("RD_Intra4x4_Mode_Decision: writeSE");
}
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];
}
/*!
************************************************************************
* \brief
* 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
{
currMB->intra_pred_modes[block_x/4+block_y]=PRED_IPRED[img->ipredmode[pic_block_x+1][pic_block_y]+1][img->ipredmode[pic_block_x][pic_block_y+1]+1][best_ipmode];
currMB->intra_pred_modes[block_x/4-1+block_y]=last_ipred;
}
last_ipred=PRED_IPRED[img->ipredmode[pic_block_x+1][pic_block_y]+1][img->ipredmode[pic_block_x][pic_block_y+1]+1][best_ipmode];
// Make difference from prediction to be transformed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -