⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macroblock.c

📁 Mobile IP VCEG的信道模拟程序
💻 C
📖 第 1 页 / 共 4 页
字号:
// *************************************************************************************
// *************************************************************************************
// 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 + -