www.pudn.com > encore50src.zip > text_code_mb.c


 
/************************************************************************** 
 *                                                                        * 
 * This code is developed by Adam Li.  This software is an                * 
 * implementation of a part of one or more MPEG-4 Video tools as          * 
 * specified in ISO/IEC 14496-2 standard.  Those intending to use this    * 
 * software module in hardware or software products are advised that its  * 
 * use may infringe existing patents or copyrights, and any such use      * 
 * would be at such party's own risk.  The original developer of this     * 
 * software module and his/her company, and subsequent editors and their  * 
 * companies (including Project Mayo), will have no liability for use of  * 
 * this software or modifications or derivatives thereof.                 * 
 *                                                                        * 
 * Project Mayo gives users of the Codec a license to this software       * 
 * module or modifications thereof for use in hardware or software        * 
 * products claiming conformance to the MPEG-4 Video Standard as          * 
 * described in the Open DivX license.                                    * 
 *                                                                        * 
 * The complete Open DivX license can be found at                         * 
 * http://www.projectmayo.com/opendivx/license.php .                      * 
 *                                                                        * 
 **************************************************************************/ 
 
/************************************************************************** 
 * 
 *  text_code_mb.c 
 * 
 *  Copyright (C) 2001  Project Mayo 
 * 
 *  Adam Li 
 *  Juice 
 * 
 *  DivX Advance Research Center  
 * 
 **************************************************************************/ 
 
/* This file contains some functions for text coding of MacroBlocks.      */ 
/* Some codes of this project come from MoMuSys MPEG-4 implementation.    */ 
/* Please see seperate acknowledgement file for a list of contributors.   */ 
 
#include "text_code.h" 
#include "text_dct.h" 
 
#define BLOCK_SIZE 8 
 
Void  	BlockPredict (SInt *curr, /*SInt *rec_curr,*/ 
	Int x_pos, Int y_pos, UInt width, Int fblock[][8]); 
Void  	BlockRebuild (SInt *rec_curr, SInt *comp, Int pred_type, Int max, 
	Int x_pos, Int y_pos, UInt width, UInt edge, Int fblock[][8]); 
Void  	BlockQuantH263 (Int *coeff, Int QP, Int mode, Int type, 
	Int *qcoeff, Int maxDC, Int image_type); 
Void  	BlockDequantH263 (Int *qcoeff, Int QP, Int mode, Int type, 
	Int *rcoeff, Int image_type, Int short_video_header, Int bits_per_pixel); 
 
 
/***********************************************************CommentBegin****** 
 * 
 * -- CodeMB -- Code, decode and reconstruct Macroblock  
 *              combined with substraction and addition operation 
 * 
 * Arguments in : 
 *	Int x_pos	x_position of Macroblock 
 *	Int y_pos	y_position of Macroblock 
 *	UInt width	width of Vop bounding box (unpadded size) 
 *	Int QP		Quantization parameter 
 *	Int Mode	Macroblock coding mode 
 * 
 * Arguments in/out : 
 *	Vop *curr	current Vop, uncoded 
 *	Vop *rec_curr	current Vop, decoded and reconstructed 
 *  Vop *comp   current Vop, motion compensated 
 *  Int *qcoeff coefficient block (384 * sizeof(Int)) 
 * 
 ***********************************************************CommentEnd********/ 
 
Void CodeMB(Vop *curr, Vop *rec_curr, Vop *comp, Int x_pos, Int y_pos, UInt width, 
Int QP, Int Mode, Int *qcoeff) 
{ 
	Int k; 
	Int fblock[6][8][8]; 
	Int coeff[384]; 
	Int *coeff_ind; 
	Int *qcoeff_ind; 
	Int* rcoeff_ind; 
	Int x, y; 
	SInt *current, *recon, *compensated = NULL; 
	UInt xwidth; 
	Int iblock[6][8][8]; 
	Int rcoeff[6*64]; 
	Int i, j; 
	Int type;									  /* luma = 1, chroma = 2 */ 
//	Int *qmat; 
	SInt tmp[64]; 
	Int s; 
 
	int operation = curr->prediction_type; 
	/* This variable is for combined operation. 
	If it is an I_VOP, then MB in curr is reconstruct into rec_curr, 
	and comp is not used at all (i.e., it can be set to NULL). 
	If it is a P_VOP, then MB in curr is reconstructed, and the result 
	added with MB_comp is written into rec_curr.  
	- adamli 11/19/2000 */ 
 
	Int max = GetVopBrightWhite(curr); 
	/* This variable is the max value for the clipping of the reconstructed image. */ 
 
	coeff_ind = coeff; 
	qcoeff_ind = qcoeff; 
	rcoeff_ind = rcoeff; 
 
	for (k = 0; k < 6; k++) 
	{ 
		switch (k) 
		{ 
			case 0: 
				x = x_pos; 
				y = y_pos; 
				xwidth = width; 
				current = (SInt *) GetImageData (GetVopY (curr)); 
				break; 
			case 1: 
				x = x_pos + 8; 
				y = y_pos; 
				xwidth = width; 
				current = (SInt *) GetImageData (GetVopY (curr)); 
				break; 
			case 2: 
				x = x_pos; 
				y = y_pos + 8; 
				xwidth = width; 
				current = (SInt *) GetImageData (GetVopY (curr)); 
				break; 
			case 3: 
				x = x_pos + 8; 
				y = y_pos + 8; 
				xwidth = width; 
				current = (SInt *) GetImageData (GetVopY (curr)); 
				break; 
			case 4: 
				x = x_pos / 2; 
				y = y_pos / 2; 
				xwidth = width / 2; 
				current = (SInt *) GetImageData (GetVopU (curr)); 
				break; 
			case 5: 
				x = x_pos / 2; 
				y = y_pos / 2; 
				xwidth = width / 2; 
				current = (SInt *) GetImageData (GetVopV (curr)); 
				break; 
			default: 
				break; 
		} 
		BlockPredict (current, x, y, xwidth, fblock[k]); 
	} 
 
	for (k = 0; k < 6; k++) 
	{ 
		s = 0; 
		for (i = 0; i < 8; i++) 
			for (j = 0; j < 8; j++) 
				tmp[s++] = (SInt) fblock[k][i][j]; 
#ifndef _MMX_ 
		fdct_enc(tmp); 
#else 
		fdct_mm32(tmp); 
#endif 
		for (s = 0; s < 64; s++) 
			coeff_ind[s] = (Int) tmp[s]; 
 
		if (k < 4) type = 1; 
		else type = 2; 
 
		/* For this release, only H263 quantization is supported. - adamli */ 
		BlockQuantH263(coeff_ind,QP,Mode,type,qcoeff_ind, 
			GetVopBrightWhite(curr),1); 
		BlockDequantH263(qcoeff_ind,QP,Mode,type,rcoeff_ind,1, 0, GetVopBitsPerPixel(curr)); 
 
		for (s = 0; s < 64; s++) 
			tmp[s] = (SInt) rcoeff_ind[s]; 
#ifndef _MMX_ 
		idct_enc(tmp); 
#else 
		Fast_IDCT(tmp); 
#endif 
		s = 0; 
		for (i = 0; i < 8; i++) 
			for (j = 0; j < 8; j++) 
				iblock[k][i][j] = (Int)tmp[s++]; 
 
		coeff_ind += 64; 
		qcoeff_ind += 64; 
		rcoeff_ind += 64; 
 
		if (Mode == MODE_INTRA||Mode==MODE_INTRA_Q) 
			for (i = 0; i < 8; i++) 
				for (j = 0; j < 8; j ++) 
					iblock[k][i][j] = MIN (GetVopBrightWhite(curr), MAX (0, iblock[k][i][j])); 
 
		switch (k) 
		{ 
			case 0: 
			case 1: 
			case 2: 
				continue; 
 
			case 3: 
				recon = (SInt *) GetImageData (GetVopY (rec_curr)); 
				if (operation == P_VOP) compensated = (SInt *) GetImageData (GetVopY (comp)); 
				BlockRebuild (recon, compensated, operation, max, x_pos,     y_pos,     width, 16, iblock[0]); 
				BlockRebuild (recon, compensated, operation, max, x_pos + 8, y_pos,     width, 16, iblock[1]); 
				BlockRebuild (recon, compensated, operation, max, x_pos,     y_pos + 8, width, 16, iblock[2]); 
				BlockRebuild (recon, compensated, operation, max, x_pos + 8, y_pos + 8, width, 16, iblock[3]); 
				continue; 
 
			case 4: 
				recon = (SInt *) GetImageData (GetVopU (rec_curr)); 
				if (operation == P_VOP) compensated = (SInt *) GetImageData (GetVopU (comp)); 
				BlockRebuild (recon, compensated, operation, max, 
					x_pos/2, y_pos/2, width/2, 8, iblock[4]); 
				continue; 
 
			case 5: 
				recon = (SInt *) GetImageData (GetVopV (rec_curr)); 
				if (operation == P_VOP) compensated = (SInt *) GetImageData (GetVopV (comp)); 
				BlockRebuild (recon, compensated, operation, max, 
					x_pos/2, y_pos/2, width/2, 8, iblock[5]); 
				continue; 
		} 
	} 
 
	return; 
} 
 
 
/***********************************************************CommentBegin****** 
 * 
 * -- BlockPredict -- Get prediction for an Intra block 
 * 
 * Purpose : 
 *	Get prediction for an Intra block 
 * 
 * Arguments in : 
 *	Int x_pos	x_position of Macroblock 
 *	Int y_pos	y_position of Macroblock 
 *	UInt width	width of Vop bounding box 
 * 
 * Arguments in/out : 
 *	SInt *curr	current uncoded Vop data 
 *	SInt *rec_curr	reconstructed Vop data area 
 * 
 * Arguments out : 
 *	Int fblock[][8]	the prediction block to be coded for bitstream 
 * 
 ***********************************************************CommentEnd********/ 
Void 
BlockPredict (SInt *curr, /*SInt *rec_curr,*/ Int x_pos, Int y_pos, 
UInt width, Int fblock[][8]) 
{ 
	Int i, j; 
 
	for (i = 0; i < 8; i++) 
	{ 
		for (j = 0; j < 8; j++) 
		{ 
			fblock[i][j] = curr[(y_pos+i)*width + x_pos+j]; 
		} 
	} 
} 
 
 
/***********************************************************CommentBegin****** 
 * 
 * -- BlockRebuild -- Reconstructs a block into data area of Vop 
 * 
 * Purpose : 
 *	Reconstructs a block into data area of Vop 
 * 
 * Arguments in : 
 *	Int x_pos	x_position of Macroblock 
 *	Int y_pos	y_position of Macroblock 
 *	UInt width	width of Vop bounding box 
 * 
 * Arguments in/out : 
 *	SInt *rec_curr	current Vop data area to be reconstructed 
 * 
 * Description : 
 *	Does reconstruction for Intra predicted blocks also 
 * 
 ***********************************************************CommentEnd********/ 
 
Void 
BlockRebuild (SInt *rec_curr, SInt *comp, Int pred_type, Int max, 
Int x_pos, Int y_pos, UInt width, UInt edge, Int fblock[][8]) 
{ 
	/* this function now does rebuild and generating error at the same time */ 
	Int i, j; 
	SInt *rec; 
	Int padded_width; 
	 
	padded_width = width + 2 * edge; 
	rec = rec_curr + edge * padded_width + edge; 
 
	if (pred_type == I_VOP) 
	{ 
		SInt *p; 
		p  = rec + y_pos * padded_width + x_pos; 
 
		for (i = 0; i < 8; i++)  
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				SInt temp = fblock[i][j]; 
				*(p++) = CLIP(temp, 0, max); 
			} 
 
			p += padded_width - 8; 
		} 
	} 
	else if (pred_type == P_VOP) 
	{ 
		SInt *p, *pc;  
		p  = rec + y_pos * padded_width + x_pos; 
		pc = comp     + y_pos * width + x_pos; 
 
		for (i = 0; i < 8; i++) 
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				SInt temp = *(pc++) + fblock[i][j]; 
				*(p++) = CLIP(temp, 0, max); 
			} 
 
			p += padded_width - 8; 
			pc += width - 8; 
		} 
	} 
} 
 
 
 
/***********************************************************CommentBegin****** 
 * 
 * -- BlockQuantH263 -- 8x8 block level quantization 
 * 
 * Purpose : 
 *	8x8 block level quantization 
 * 
 * Arguments in : 
 *	Int *coeff	non-quantized coefficients 
 *	Int QP		quantization parameter 
 *	Int Mode	Macroblock coding mode 
 * 
 * Arguments out : 
 *	Int *qcoeff	quantized coefficients 
 * 
 ***********************************************************CommentEnd********/ 
Void 
BlockQuantH263 (Int *coeff, Int QP, Int mode, Int type, Int *qcoeff, Int maxDC, Int image_type) 
{ 
	Int i; 
	Int level, result; 
	Int step, offset; 
	Int dc_scaler; 
 
	if (!(QP > 0 && (QP < 32*image_type))) return; 
	if (!(type == 1 || type == 2)) return; 
 
	if (mode == MODE_INTRA || mode == MODE_INTRA_Q) 
	{										  /* Intra */ 
		dc_scaler = cal_dc_scaler(QP,type); 
		qcoeff[0] = MAX(1,MIN(maxDC-1, (coeff[0] + dc_scaler/2)/dc_scaler)); 
 
		step = 2 * QP; 
		for (i = 1; i < 64; i++) 
		{ 
			level = (abs(coeff[i]))  / step; 
			result = (coeff[i] >= 0) ? level : -level; 
			qcoeff[i] =  MIN(2047, MAX(-2048, result)); 
		} 
	} 
	else 
	{										  /* non Intra */ 
		step = 2 * QP; 
		offset = QP / 2; 
		for (i = 0; i < 64; i++) 
		{ 
			level = (abs(coeff[i]) - offset)  / step; 
			result = (coeff[i] >= 0) ? level : -level; 
			qcoeff[i] =  MIN(2047, MAX(-2048, result)); 
		} 
	} 
 
	return; 
} 
 
 
/***********************************************************CommentBegin****** 
 * 
 * -- BlockDequantH263 -- 8x8 block dequantization 
 * 
 * Purpose : 
 *	8x8 block dequantization 
 * 
 * Arguments in : 
 *	Int *qcoeff	        quantized coefficients 
 *	Int QP		        quantization parameter 
 *	Int mode	        Macroblock coding mode 
 *      Int short_video_header  Flag to signal short video header bitstreams (H.263) 
 * 
 * Arguments out : 
 *	Int *rcoeff	reconstructed (dequantized) coefficients 
 * 
 ***********************************************************CommentEnd********/ 
Void 
BlockDequantH263 (Int *qcoeff, Int QP, Int mode, Int type, Int *rcoeff, 
Int image_type, Int short_video_header, Int bits_per_pixel) 
{ 
	Int i; 
	Int dc_scaler; 
	Int lim; 
 
	lim = (1 << (bits_per_pixel + 3)); 
 
	if (QP) 
	{ 
		for (i = 0; i < 64; i++) 
		{ 
			if (qcoeff[i]) 
			{ 
				/* 16.11.98 Sven Brandau: "correct saturation" due to N2470, Clause 2.1.6 */ 
				qcoeff[i] =  MIN(2047, MAX(-2048, qcoeff[i] )); 
				if ((QP % 2) == 1) 
					rcoeff[i] = QP * (2*ABS(qcoeff[i]) + 1); 
				else 
					rcoeff[i] = QP * (2*ABS(qcoeff[i]) + 1) - 1; 
				rcoeff[i] = SIGN(qcoeff[i]) * rcoeff[i]; 
			} 
			else 
				rcoeff[i] = 0; 
		} 
		if (mode == MODE_INTRA || mode == MODE_INTRA_Q) 
		{										  /* Intra */ 
 
			MOMCHECK(QP > 0 && (QP < 32*image_type)); 
			MOMCHECK(type == 1 || type == 2); 
 
			if (short_video_header) 
				dc_scaler = 8; 
			else 
				dc_scaler = cal_dc_scaler(QP,type); 
 
			rcoeff[0] = qcoeff[0] * dc_scaler; 
		} 
	} 
	else 
	{ 
		/* No quantizing at all */ 
		for (i = 0; i < 64; i++) 
		{ 
			rcoeff[i] = qcoeff[i]; 
		} 
 
		if (mode == MODE_INTRA || mode == MODE_INTRA_Q) 
		{										  /* Intra */ 
			rcoeff[0] = qcoeff[0]*8; 
		} 
	} 
	for (i=0;i<64;i++) 
		if (rcoeff[i]>(lim-1)) rcoeff[i]=(lim-1); 
		else if (rcoeff[i]<(-lim)) rcoeff[i]=(-lim); 
 
	return; 
}