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

📄 mot_est_comp.c

📁 MPEG4编解码系统代码
💻 C
📖 第 1 页 / 共 2 页
字号:
//运动信息编码(运动补偿)
#include "vm_common_defs.h"
#include "mom_util.h"
#include "mot_util.h"
#include "mot_est_mb.h"

extern FILE *ftrace;

/* For correct rounding of chrominance vectors */
static Int roundtab16[] = {0,0,0,1,1,1,1,1,1,1,1,1,1,1,2,2};

Void  	MotionEstCompPicture (	
			SInt *curr,
			SInt *prev,
			SInt *prev_ipol_y,
			SInt *prev_ipol_u,
			SInt *prev_ipol_v,
			Int prev_x,
			Int prev_y,
			Int vop_width,
			Int vop_height,
			Int enable_8x8_mv,
			Int edge,
			Int sr_for,
			Int f_code,
			Int rounding_type,
			Int br_x,
			Int br_y,
			Int br_width,
			Int br_height,
			SInt *curr_comp_y,
			SInt *curr_comp_u,
			SInt *curr_comp_v,
			Float *mad,
			Float *mv16_w,
			Float *mv16_h,
			Float *mv8_w,
			Float *mv8_h,
			SInt *mode16
	);
Void GetPred_Chroma (
			Int x_curr,
			Int y_curr,
			Int dx,
			Int dy,
			SInt *prev_u,
			SInt *prev_v,
			SInt *comp_u,
			SInt *comp_v,
			Int width,
			Int width_prev,
			Int prev_x_min,
			Int prev_y_min,
			Int prev_x_max,
			Int prev_y_max,
			Int rounding_control
	);

/***********************************************************CommentBegin******
函数功能:
估计运动向量并进行运动补偿运算。在高级模式下估计运动向量,函数输出为:四个包含运动向量(宏块大小为8×8)横纵坐标的图像,处理模式(每个宏块一个值)。那么运动补偿也是同样的处理方式。
函数描述:
1)对于函数运算和输出所用到的图像均分配了存储空间;
2)对于每一个宏块而言,mot_x/mot_y均有4个相同的向量;
3)对于帧内编码宏块,mot_x/mot_y有4个相同的零向量;
4)如果使用了_NO_ESTIMATION_,函数输出为:
mot_x               所有运动向量为0.0
mot_y               所有运动向量为0.0
mode                所有的模式为MB_INTRA (IGNORING THE SHAPE)
***********************************************************CommentEnd********/

Void MotionEstimationCompensation (
Vop *curr_vop,					/*当前视频对象平面(亮度信息)*/
Vop *prev_rec_vop,				/*重建的参考视频对象平面*/
Int enable_8x8_mv,				/*8×8运动向量(=1)或者16×16运动向量(=0)*/
In edge,					/*如果限制(=0),不限制为边界*/
Int f_code,					/*运动向量搜索范围*/
Vop *curr_comp_vop,				/*进行运动补偿的当前视频对象平面*/
Float *mad,					/*ME/MC结果的容忍值*/
Image **mot_x,					/*运动向量水平坐标*/
Image **mot_y,					/*运动向量竖直坐标*/
Image **mode					/*每一个宏块的模式*/
)
{
	Image *pr_rec_y;				/*参考图像(重建后)*/
	Image *pi_y;				

	Image   *mode16;
	Image   *mv16_w;
	Image   *mv16_h;
	Image   *mv8_w;
	Image   *mv8_h;

	SInt    *prev_ipol_y,			
			*prev_orig_y;		/*有边界的参考原始图像*/

	Int     vop_width, vop_height;

	Int     br_x;
	Int     br_y;
	Int     br_height;
	Int     br_width;
	Int     mv_h, mv_w;
	/*得到数据传输比特率*/
	br_y=curr_vop->ver_spat_ref;
	br_x=curr_vop->hor_spat_ref;
	br_height=curr_vop->height;
	br_width=curr_vop->width;
	mv_h=br_height/MB_SIZE;
	mv_w=br_width/MB_SIZE;
	/*我们假设prev_rec_vop和prev_vop的值相等并且都是非负数*/
	vop_width=prev_rec_vop->width;
	vop_height=prev_rec_vop->height;
	/*得到图像并将它们插入*/
	pr_rec_y = prev_rec_vop->y_chan;
	prev_orig_y = (SInt*)GetImageData(pr_rec_y);
	pi_y = AllocImage (2*vop_width, 2*vop_height, SHORT_TYPE);
	InterpolateImage(pr_rec_y, pi_y, GetVopRoundingType(curr_vop));
	prev_ipol_y = (SInt*)GetImageData(pi_y);
	/*给所有的运动向量和模式数据分配存储空间*/
	mode16=AllocImage (mv_w,mv_h,SHORT_TYPE);
	SetConstantImage (mode16,(Float)MBM_INTRA);
	/*mv16有2×2个重复的运动向量值来共享运动向量预测函数,预测是在函数CodeVopVotion和MotionEstimation之间*/
	mv16_w=AllocImage (mv_w*2,mv_h*2,FLOAT_TYPE);
	mv16_h=AllocImage (mv_w*2,mv_h*2,FLOAT_TYPE);
	mv8_w =AllocImage (mv_w*2,mv_h*2,FLOAT_TYPE);
	mv8_h =AllocImage (mv_w*2,mv_h*2,FLOAT_TYPE);
	SetConstantImage (mv16_h,+0.0);
	SetConstantImage (mv16_w,+0.0);
	SetConstantImage (mv8_h,+0.0);
	SetConstantImage (mv8_w,+0.0);

	SetConstantImage (curr_comp_vop->u_chan, 0);
	SetConstantImage (curr_comp_vop->v_chan, 0);

	/*计算运动向量和每一个宏块的模式*/
	MotionEstCompPicture(
		(SInt *)GetImageData(GetVopY(curr_vop)), //curr_vop,
		prev_orig_y,							/*Y用边界来填充*/
		prev_ipol_y,							/*修改Y值(从pi_y)*/
		(SInt*)GetImageData(prev_rec_vop->u_chan) + (vop_width/2) * (16/2) + (16/2),
		(SInt*)GetImageData(prev_rec_vop->v_chan) + (vop_width/2) * (16/2) + (16/2),
		prev_rec_vop->hor_spat_ref,
		prev_rec_vop->ver_spat_ref,
		vop_width,vop_height,
		enable_8x8_mv,
		edge,
		GetVopSearchRangeFor(curr_vop), 
		f_code,
		GetVopRoundingType(curr_vop),
		br_x,br_y,								  /*边界矩形的空间位置*/
		br_width,br_height,						  /*边界矩形的大小*/
		(SInt*)GetImageData(curr_comp_vop->y_chan),
		(SInt*)GetImageData(curr_comp_vop->u_chan),
		(SInt*)GetImageData(curr_comp_vop->v_chan),
		mad,
		(Float*)GetImageData(mv16_w),
		(Float*)GetImageData(mv16_h),
		(Float*)GetImageData(mv8_w),
		(Float*)GetImageData(mv8_h),
		(SInt*) GetImageData(mode16)
		);

	/*将函数结果转换成MOMUSYS中定义的格式*/
	GetMotionImages(mv16_w, mv16_h, mv8_w, mv8_h, mode16, mot_x, mot_y, mode);

	/* Deallocate dynamic memory */
	FreeImage(mv16_w); FreeImage(mv16_h);
	FreeImage(mv8_w);  FreeImage(mv8_h);
	FreeImage(mode16);
	FreeImage(pi_y);
}


/***********************************************************CommentBegin******
 *
 * -- MotionEstCompPicture -- Computes MV's and predictor errors and 
 *										do motion compensation
 *
 * Purpose :
 *      Computes MV's (8x8 and 16x16) and predictor errors for the whole
 *      vop. Perform motion compensation for the whole vop.
 *
 ***********************************************************CommentEnd********/

Void
MotionEstCompPicture(
SInt* curr,		//当前视频对象平面,是short int型;
SInt* prev,		//用边界填充的原始的Y向量;
SInt* prev_ipol,	//亮度Y的修改值;
SInt* prev_u,		//用边界填充的原始U分量;
SInt* prev_v,		//用边界填充的原始V分量;
int prev_x,		//前一个视频对象平面的水平位置的绝对值,是int型;
int prev_y,		//前一个视频对象平面的竖直位置的绝对值;
int vop_width,		//前一个视频对象平面的水平方向大小,即宽度;
int vop_height,		//前一个视频对象平面的竖直方向大小,即高度;
int enable_8x8_mv, 	//如果运动向量是8×8,则为1;或者仅仅是16×16,则为0
int edge,		//围绕参考视频对象平面的边界;
int sr_for,		//前向搜索范围;
int f_code,		//运动向量的搜索范围;
int rounding_type,	//当前视频对象平面环绕的类型;
int br_x,		//当前视频对象平面水平空间位置的绝对值;
int bt_y,		//当前视频对象平面竖直空间位置的绝对值;
int br_width,		//当前视频对象平面边界矩形的宽度;
int br_height,		//当前视频对象平面边界矩形的高度;
SInt* curr_comp_y,	//运动补偿的当前Y值;
SInt* curr_comp_u,	//运动补偿的当前U值;
SInt* curr_comp_v,	//运动补偿的当前V值;
float* mad,		//当前ME(运动估计)/MC(运动补偿)结果的容忍值,即最大的误差容忍;
float* mv16_w, 		//16×16运动向量的水平预测;
float* mv16_h,		//16×16运动向量的竖直预测;
float* mv8_w,		//8×8运动向量的水平预测;
float* mv8_h,		//8×8运动向量的竖直预测;
SInt* model16,		//预测运动向量的模式。
)
{
	Int		i, j, k;
	SInt	curr_mb[MB_SIZE][MB_SIZE];
	SInt	curr_comp_mb_16[MB_SIZE][MB_SIZE];
	SInt	curr_comp_mb_8[MB_SIZE][MB_SIZE];
	Int		sad8 = MV_MAX_ERROR, sad16, sad;
	Int		imas_w, imas_h,	Mode;
	Int		posmode, pos16,	pos8;
	Int		min_error16,
			min_error8_0, min_error8_1, min_error8_2, min_error8_3;

	/***************************************************************************
	xm:如果向下(或逐低)搜索(x轴方向)完成(没有1/2的搜索可以进行了),那么其值为1;
	如果完成了1/2向下边界搜索(x轴方向),则为0。
	xM:如果向上(或逐高)搜索(x轴方向)完成(没有1/2的搜索可以进行了),那么其值为1;
	如果完成了1/2向上边界搜索(x轴方向),则为0。
	ym:如果向下(或逐低)搜索(y轴方向)完成(没有1/2的搜索可以进行了),那么其值为1;	
	如果完成了1/2向下边界搜索(y轴方向),则为0。
	yM:如果向上(或逐高)搜索(y轴方向)完成(没有1/2的搜索可以进行了),那么其值为1;
	如果完成了1/2向上边界搜索(y轴方向),则为0。

	***************************************************************************/
	SInt	*halfpelflags;
	Float	hint_mv_w, hint_mv_h;
	Int		xsum,ysum,dx,dy;
	Int		prev_x_min,prev_x_max,prev_y_min,prev_y_max;

	prev_x_min = 2 * prev_x + 2 * 16;
	prev_y_min = 2 * prev_y + 2 * 16;
	prev_x_max = prev_x_min + 2 * vop_width - 4 * 16;
	prev_y_max = prev_y_min + 2 * vop_height - 4 * 16; 

	imas_w=br_width/MB_SIZE;
	imas_h=br_height/MB_SIZE;

	/*进行运动预测并将结果存放到数组中*/

	halfpelflags=(SInt*)malloc(5*4*sizeof(SInt));
	/*	halfpelflags=(SInt*)malloc(9*4*sizeof(SInt)); */
	sad = 0;

	for ( j=0; j< (br_height/MB_SIZE); j++)
	{
		hint_mv_w = hint_mv_h = 0.f;
		for ( i=0; i< (br_width/MB_SIZE); i++)
		{
			/* Integer pel search */
			Int min_error;

			posmode =          j * imas_w +   i;
			pos16   = pos8 = 2*j*2*imas_w + 2*i;

			MBMotionEstimation(curr,
				prev, br_x, br_y,
				br_width, i, j, prev_x, prev_y,
				vop_width, vop_height, enable_8x8_mv, edge,
				f_code, sr_for, 
				hint_mv_w, hint_mv_h, // the hint seeds
				mv16_w, mv16_h,
				mv8_w, mv8_h, &min_error, halfpelflags);

			/*帧间/帧内判定*/
			Mode = ChooseMode(curr, 
				i*MB_SIZE,j*MB_SIZE, min_error, br_width);

			hint_mv_w = mv16_w[pos16];
			hint_mv_h = mv16_h[pos16];

			LoadArea(curr, i*MB_SIZE, j*MB_SIZE, 16, 16, br_width, (SInt *)curr_mb);

			/* 0==MBM_INTRA,1==MBM_INTER16||MBM_INTER8 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -