?? macroblock.c
字號:
// *************************************************************************************
// *************************************************************************************
// Macroblock.c Process one macroblock
//
// Main contributors (see contributors.h for copyright, address and affiliation details)
//
// Inge Lille-Lang鴜 <inge.lille-langoy@telenor.com>
// Rickard Sjoberg <rickard.sjoberg@era.ericsson.se>
// Jani Lainema <jani.lainema@nokia.com>
// Sebastian Purreiter <sebastian.purreiter@mch.siemens.de>
// Detlev Marpe <marpe@hhi.de>
// Thomas Wedi <wedi@tnt.uni-hannover.de>
// *************************************************************************************
// *************************************************************************************
#include "contributors.h"
#include <math.h>
#include <stdlib.h>
#include "global.h"
#include "elements.h"
#include "macroblock.h"
#include "refbuf.h"
#include <stdio.h>
/************************************************************************
*
* Name : proceed2nextMacroblock()
*
* Description: updates the coordinates and statistics parameter for the
* next macroblock
*
************************************************************************/
void proceed2nextMacroblock()
{
#if TRACE
int use_bitstream_backing = (input->slice_mode == FIXED_RATE || input->slice_mode == CALLBACK);
#endif
const int number_mb_per_row = img->width / MB_BLOCK_SIZE ;
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
#if TRACE
int i;
if(use_bitstream_backing)
fprintf(p_trace, "\n*********** Pic: %i (I/P) MB: %i Slice: %i **********\n\n", frame_no, img->current_mb_nr, img->current_slice_nr);
/* Write out the tracestring for each symbol */
for (i=0; i<currMB->currSEnr; i++)
trace2out(&(img->MB_SyntaxElements[i]));
#endif
/* Update the statistics */
stat->bit_use_head_mode[img->type] += currMB->bitcounter[BITS_HEADER_MB];
stat->bit_use_coeffY[img->type] += currMB->bitcounter[BITS_COEFF_Y_MB] ;
stat->bit_use_mode_inter[img->mb_mode]+= currMB->bitcounter[BITS_INTER_MB];
stat->tmp_bit_use_cbp[img->type] += currMB->bitcounter[BITS_CBP_MB];
stat->bit_use_coeffC[img->type] += currMB->bitcounter[BITS_COEFF_UV_MB];
if (input->symbol_mode == UVLC)
stat->bit_ctr += currMB->bitcounter[BITS_TOTAL_MB];
if (img->type==INTRA_IMG)
++stat->mode_use_intra[img->mb_mode];
else
if (img->type != B_IMG)
++stat->mode_use_inter[img->mb_mode];
else
++stat->mode_use_Bframe[img->mb_mode];
/* Update coordinates of macroblock */
img->mb_x++;
if (img->mb_x == number_mb_per_row) /* next row of MBs */
{
img->mb_x = 0; /* start processing of next row */
img->mb_y++;
}
img->current_mb_nr++;
/* Define vertical positions */
img->block_y = img->mb_y * BLOCK_SIZE; /* vertical luma block position */
img->pix_y = img->mb_y * MB_BLOCK_SIZE; /* vertical luma macroblock position */
img->pix_c_y = img->mb_y * MB_BLOCK_SIZE/2; /* vertical chroma macroblock position */
if (img->type != B_IMG)
{
if (input->intra_upd > 0 && img->mb_y <= img->mb_y_intra)
img->height_err=(img->mb_y_intra*16)+15; /* for extra intra MB */
else
img->height_err=img->height-1;
}
/* Define horizontal positions */
img->block_x = img->mb_x * BLOCK_SIZE; /* luma block */
img->pix_x = img->mb_x * MB_BLOCK_SIZE; /* luma pixel */
img->block_c_x = img->mb_x * BLOCK_SIZE/2; /* chroma block */
img->pix_c_x = img->mb_x * MB_BLOCK_SIZE/2; /* chroma pixel */
/* Statistics */
if (img->type == INTER_IMG)
{
++stat->quant0;
stat->quant1 += img->qp; /* to find average quant for inter frames */
}
}
/************************************************************************
*
* Name : start_macroblock()
*
* Description: initializes the current macroblock
*
************************************************************************/
void start_macroblock()
{
int i,j,k,l;
int x,y;
int use_bitstream_backing = (input->slice_mode == FIXED_RATE || input->slice_mode == CALLBACK);
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
Slice *curr_slice = img->currentSlice;
DataPartition *dataPart;
Bitstream *currStream;
if(use_bitstream_backing)
{
/* Save loopb and loopc in the case of recoding this macroblock */
for(x = 0 ; x<6 ; x++)
for(y = 0 ; y<6 ; y++)
img->tmp_loop_Y[x][y] = loopb[img->block_x+x][img->block_y+y];
for(x=0 ; x<4 ; x++)
for(y=0 ; y<4 ; y++)
img->tmp_loop_UV[x][y] = loopc[img->block_x/2+x][img->block_y/2+y];
/* Keep the current state of the bitstreams */
for (i=0; i<curr_slice->max_part_nr; i++)
{
dataPart = &(curr_slice->partArr[i]);
currStream = dataPart->bitstream;
currStream->stored_bits_to_go = currStream->bits_to_go;
currStream->stored_byte_pos = currStream->byte_pos;
currStream->stored_byte_buf = currStream->byte_buf;
}
}
/* Save the slice number of this macroblock. When the macroblock below */
/* is coded it will use this to decide if prediction for above is possible */
img->slice_numbers[img->current_mb_nr] = img->current_slice_nr;
/* Save the slice and macroblock number of the current MB */
currMB->slice_nr = img->current_slice_nr;
/* Initialize counter for MB symbols */
currMB->currSEnr=0;
/* If MB is next to a slice boundary, mark neighboring blocks unavailable for prediction */
CheckAvailabilityOfNeighbors(img);
/* Reset vectors before doing motion search in motion_search(). */
if (img->type != B_IMG)
{
for (k=0; k < 2; k++)
{
for (j=0; j < BLOCK_MULTIPLE; j++)
for (i=0; i < BLOCK_MULTIPLE; i++)
tmp_mv[k][img->block_y+j][img->block_x+i+4]=0;
}
}
/* Reset syntax element entries in MB struct */
currMB->mb_type = 0;
currMB->ref_frame = 0;
currMB->cbp = 0;
for (l=0; l < 2; l++)
for (j=0; j < BLOCK_MULTIPLE; j++)
for (i=0; i < BLOCK_MULTIPLE; i++)
for (k=0; k < 2; k++)
currMB->mvd[l][j][i][k] = 0;
for (i=0; i < (BLOCK_MULTIPLE*BLOCK_MULTIPLE); i++)
currMB->intra_pred_modes[i] = 0;
/* Initialize bitcounters for this macroblock */
if(img->current_mb_nr == 0) /* No slice header to account for */
{
currMB->bitcounter[BITS_HEADER_MB] = 0;
}
else
if (img->slice_numbers[img->current_mb_nr] == img->slice_numbers[img->current_mb_nr-1]) /* current MB belongs to the */
/* same slice as the last MB */
{
currMB->bitcounter[BITS_HEADER_MB] = 0;
}
currMB->bitcounter[BITS_COEFF_Y_MB] = 0;
currMB->bitcounter[BITS_INTER_MB] = 0;
currMB->bitcounter[BITS_CBP_MB] = 0;
currMB->bitcounter[BITS_COEFF_UV_MB] = 0;
#ifdef _FAST_FULL_ME_
ResetFastFullIntegerSearch ();
#endif
}
/************************************************************************
*
* Name : terminate_macroblock()
*
* Description: terminates processing of the current macroblock depending
* on the chosen slice mode
*
************************************************************************/
void terminate_macroblock(Boolean *end_of_slice, Boolean *recode_macroblock)
{
int i,x,y;
int mb_nr = img->current_mb_nr;
Slice *curr_slice = img->currentSlice;
DataPartition *dataPart;
Bitstream *currStream;
EncodingEnvironmentPtr eep;
static unsigned int ElowS, EhighS;
static unsigned int EbufferS;
static unsigned int Ebits_to_goS;
static unsigned int Ebits_to_followS;
static byte *EcodestrmS;
static int *Ecodestrm_lenS;
static int save_eep=0;
switch(input->slice_mode)
{
case NO_SLICES:
*recode_macroblock = FALSE;
if ((mb_nr+1) == img->total_number_mb) /* maximum number of MBs */
*end_of_slice = TRUE;
break;
case FIXED_MB:
/* For slice mode one, check if a new slice boundary follows */
*recode_macroblock = FALSE;
if ( ((mb_nr+1) % input->slice_argument == 0) || ((mb_nr+1) == img->total_number_mb) )
{
*end_of_slice = TRUE;
}
break;
/* For slice modes two and three, check if coding of this macroblock */
/* resulted in too many bits for this slice. If so, indicate slice */
/* boundary before this macroblock and code the macroblock again */
case FIXED_RATE:
if (input->symbol_mode ==CABAC)
{
dataPart= &(curr_slice->partArr[0]);
eep = &(dataPart->ee_cabac);
stat->bit_slice = arienco_bits_written(eep);
}
if (mb_nr > 0 && img->mb_data[mb_nr-1].slice_nr == img->current_slice_nr)
{
if (stat->bit_slice > input->slice_argument*8)
{
//printf("MB: %d\tBits: %d\n",mb_nr,stat->bit_slice);
//TO get status of the eep at the last mb in this slice
if (input->symbol_mode ==CABAC)
{
eep->Elow = ElowS;
eep->Ehigh = EhighS;
eep->Ebuffer = EbufferS;
eep->Ebits_to_go = Ebits_to_goS;
eep->Ebits_to_follow = Ebits_to_followS;
eep->Ecodestrm = EcodestrmS;
eep->Ecodestrm_len = Ecodestrm_lenS;
}
*recode_macroblock = TRUE;
*end_of_slice = TRUE;
}
}
if ( (*recode_macroblock == FALSE) && ((mb_nr+1) == img->total_number_mb) ) /* maximum number of MBs */
*end_of_slice = TRUE;
if (input->symbol_mode == CABAC) //TO: save current status of the eep
{
ElowS = eep->Elow;
EhighS = eep->Ehigh;
EbufferS = eep->Ebuffer;
Ebits_to_goS = eep->Ebits_to_go;
Ebits_to_followS = eep->Ebits_to_follow;
EcodestrmS = eep->Ecodestrm;
Ecodestrm_lenS = eep->Ecodestrm_len;
}
break;
case CALLBACK:
if (mb_nr > 0 && img->mb_data[mb_nr-1].slice_nr == img->current_slice_nr)
{
if (curr_slice->slice_too_big(stat->bit_slice))
{
*recode_macroblock = TRUE;
*end_of_slice = TRUE;
}
}
if ( (*recode_macroblock == FALSE) && ((mb_nr+1) == img->total_number_mb) ) /* maximum number of MBs */
*end_of_slice = TRUE;
break;
default:
fprintf(stderr, "Slice Mode %d not supported", input->slice_mode);
exit(1);
}
if(*recode_macroblock == TRUE)
{
/* Restore the state of the bitstreams */
for (i=0; i<curr_slice->max_part_nr; i++)
{
dataPart = &(curr_slice->partArr[i]);
currStream = dataPart->bitstream;
currStream->bits_to_go = currStream->stored_bits_to_go;
currStream->byte_pos = currStream->stored_byte_pos;
currStream->byte_buf = currStream->stored_byte_buf;
}
/* Restore loopb and loopc before coding the MB again*/
for(x = 0 ; x<6 ; x++) for(y = 0 ; y<6 ; y++)
loopb[img->block_x+x][img->block_y+y] = img->tmp_loop_Y[x][y];
for(x=0 ; x<4 ; x++) for(y=0 ; y<4 ; y++)
loopc[img->block_x/2+x][img->block_y/2+y] = img->tmp_loop_UV[x][y];
}
}
/************************************************************************
*
* Name : CheckAvailabilityOfNeighbors(struct img_par *img)
*
* Description: Checks the availability of neighboring macroblocks of
* the current macroblock for prediction and context determination;
* marks the unavailable MBs for intra prediction in the
* ipredmode-array by -1. Only neighboring MBs in the causal
* past of the current MB are checked.
*
************************************************************************/
void CheckAvailabilityOfNeighbors()
{
int i,j;
const int mb_width = img->width/MB_BLOCK_SIZE;
const int mb_nr = img->current_mb_nr;
Macroblock *currMB = &img->mb_data[mb_nr];
/* mark all neighbors as unavailable */
for (i=0; i<3; i++)
for (j=0; j<3; j++)
img->mb_data[mb_nr].mb_available[i][j]=NULL;
img->mb_data[mb_nr].mb_available[1][1]=currMB; /* current MB */
/* Check MB to the left */
if(img->pix_x >= MB_BLOCK_SIZE)
{
if(currMB->slice_nr != img->mb_data[mb_nr-1].slice_nr)
{
img->ipredmode[img->block_x][img->block_y+1] = -1;
img->ipredmode[img->block_x][img->block_y+2] = -1;
img->ipredmode[img->block_x][img->block_y+3] = -1;
img->ipredmode[img->block_x][img->block_y+4] = -1;
} else
currMB->mb_available[1][0]=&(img->mb_data[mb_nr-1]);
}
/* Check MB above */
if(img->pix_y >= MB_BLOCK_SIZE)
{
if(currMB->slice_nr != img->mb_data[mb_nr-mb_width].slice_nr)
{
img->ipredmode[img->block_x+1][img->block_y] = -1;
img->ipredmode[img->block_x+2][img->block_y] = -1;
img->ipredmode[img->block_x+3][img->block_y] = -1;
img->ipredmode[img->block_x+4][img->block_y] = -1;
} else
currMB->mb_available[0][1]=&(img->mb_data[mb_nr-mb_width]);
}
/* Check MB left above */
if(img->pix_x >= MB_BLOCK_SIZE && img->pix_y >= MB_BLOCK_SIZE )
{
if(currMB->slice_nr == img->mb_data[mb_nr-mb_width-1].slice_nr)
img->mb_data[mb_nr].mb_available[0][0]=&(img->mb_data[mb_nr-mb_width-1]);
}
/* Check MB right above */
if(img->pix_y >= MB_BLOCK_SIZE && img->pix_x < (img->width-MB_BLOCK_SIZE ))
{
if(currMB->slice_nr == img->mb_data[mb_nr-mb_width+1].slice_nr)
// currMB->mb_available[0][1]=&(img->mb_data[mb_nr-mb_width+1]);
currMB->mb_available[0][2]=&(img->mb_data[mb_nr-mb_width+1]);
}
}
/************************************************************************
*
* Name : MakeIntraPrediction()
*
* Description: Performs 4x4 and 16x16 intra prediction and transform coding
* of the prediction residue. The routine returns the best cost;
* current cbp (for LUMA only) and intra pred modes are affected
*
************************************************************************/
int MakeIntraPrediction(int *intra_pred_mode_2)
{
int i,j;
int block_x, block_y;
int best_ipmode=0;
int tot_intra_sad, tot_intra_sad2, best_intra_sad, current_intra_sad;
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 ipmode; /* intra pred mode */
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;
tot_intra_sad=QP2QUANT[img->qp]*24;/* sum of intra sad values, start with a 'handicap'*/
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);
best_intra_sad=MAX_VALUE; /* initial value, will be modified below */
img->imod = INTRA_MB_OLD; /* for now mode set to intra, may be changed in motion_search() */
/* DM: has to be removed */
for (ipmode=0; ipmode < NO_INTRA_PMODE; ipmode++) /* all intra prediction modes */
{
/* 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*/
{
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]; /* find diff */
}
current_intra_sad=QP2QUANT[img->qp]*PRED_IPRED[img->ipredmode[pic_block_x+1][pic_block_y]+1][img->ipredmode[pic_block_x][pic_block_y+1]+1][ipmode]*2;
current_intra_sad += find_sad(input->hadamard, img->m7); /* add the start 'handicap' and the computed SAD */
if (current_intra_sad < best_intra_sad)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -