mot_util.c

来自「实现在linux下的mpeg4编解码」· C语言 代码 · 共 482 行

C
482
字号
/************************************************************************** *                                                                        * * 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 .                      * *                                                                        * **************************************************************************//************************************************************************** * *  mot_util.c * *  Copyright (C) 2001  Project Mayo * *  Adam Li * *  DivX Advance Research Center <darc@projectmayo.com> * **************************************************************************//* This file contains some utility functions to for motion estimation and *//* compensation.                                                          *//* Some codes of this project come from MoMuSys MPEG-4 implementation.    *//* Please see seperate acknowledgement file for a list of contributors.   */#include "mom_structs.h"#include "vm_common_defs.h"#include "mot_util.h"/* ------------------------------------------------------------------------- *//* Macro to compute the MB absolute error difference of the inside the shape *///static Int P_diff;#define DIFF1(v1,v2,idx) (P_diff = (v1[idx]-v2[idx]), ABS(P_diff))/***********************************************************CommentBegin****** * * -- InterpolateImage -- Interpolates a complete  (SInt)image * * Purpose : *      Interpolates a complete  (SInt) image for easier half pel prediction * ***********************************************************CommentEnd********/VoidInterpolateImage(Image   *input_image,							  /* <-- image to interpolate (SInt) */Image   *output_image,							  /* --> interpolated image (SInt)  */Int     rounding_control){	SInt   *ii, *oo;	UInt    i, j;	UInt   width, height;	width = input_image->x;	height = input_image->y;	ii = (SInt*)GetImageData(output_image);	oo = (SInt*)GetImageData(input_image);	/* main image */	for (j = 0; j < height-1; j++)	{		for (i = 0; i  < width-1; i++)		{			*(ii + (i<<1)) = *(oo + i);			*(ii + (i<<1)+1) = (*(oo + i) + *(oo + i + 1) + 1- rounding_control)>>1;			*(ii + (i<<1)+(width<<1)) = (*(oo + i) + *(oo + i + width) + 1-				rounding_control)>>1;			*(ii + (i<<1)+1+(width<<1)) = (*(oo+i) + *(oo+i+1) +				*(oo+i+width) + *(oo+i+1+width) + 2-				rounding_control)>>2;		}		/* last pels on each line */		*(ii+ (width<<1) - 2) = *(oo + width - 1);		*(ii+ (width<<1) - 1) = *(oo + width - 1);		*(ii+ (width<<1)+ (width<<1)-2) = (*(oo+width-1)+*(oo+width+width-1)+1-			rounding_control)>>1;		*(ii+ (width<<1)+ (width<<1)-1) = (*(oo+width-1)+*(oo+width+width-1)+1-			rounding_control)>>1;		ii += (width<<2);		oo += width;	}	/* last lines */	for (i = 0; i < width-1; i++)	{		*(ii+ (i<<1)) = *(oo + i);		*(ii+ (i<<1)+1) = (*(oo + i) + *(oo + i + 1) + 1- rounding_control)>>1;		*(ii+ (width<<1)+ (i<<1)) = *(oo + i);		*(ii+ (width<<1)+ (i<<1)+1) = (*(oo + i) + *(oo + i + 1) + 1-			rounding_control)>>1;	}	/* bottom right corner pels */	*(ii + (width<<1) - 2) = *(oo + width -1);	*(ii + (width<<1) - 1) = *(oo + width -1);	*(ii + (width<<2) - 2) = *(oo + width -1);	*(ii + (width<<2) - 1) = *(oo + width -1);	return;}/***********************************************************CommentBegin****** * * -- GetMotionImages -- * * Purpose : *      Translate the MVs data from the resulting separated four *      (Float) Images (16x16/8x8, X,Y) of the motion estimation process *      into two Images, which contain the 16x16 and 8x8 MVs *      values acording to the modes (MBM_INTRA, MBM_INTER16, *      MBM_INTER8). It also *      makes a copy of imode16 (SInt-Image of modes). * * Return values : *      1 on success, -1 on error * ***********************************************************CommentEnd********/IntGetMotionImages(Image   *imv16_w,								  /* <-- 16x16 horiz. MV Float-Image (MxN) (cuad.)   */Image   *imv16_h,								  /* <-- 16x16 verti. MV Float-Image   (MxN) (cuad.) */Image   *imv8_w,								  /* <-- 8x8  horizontal MV Float-Image  (MxN)       */Image   *imv8_h,								  /* <-- 8x8  vertical MV Float-Image    (MxN)       */Image   *imode16,								  /* <-- SInt-Image of modes            (M/2xN/2)    */Image   **mv_x,									  /* --> horizontal MV Float-Image      (MxN)        */Image   **mv_y,									  /* --> vertical   MV Float-Image      (MxN)        */Image   **mode									  /* --> SInt-Image of modes           (M/2xN/2)     */){	Int     i, j;	Int     width, height, base;	Float   val_x, val_y;	Float   *data_x, *data_y,			*mv16_w, *mv16_h,			*mv8_w,  *mv8_h;	SInt    *mode16, *data_mode;	SInt    modo;	width = imode16->x; height = imode16->y;	(*mode)=AllocImage(width,height,SHORT_TYPE);	(*mv_x)=AllocImage(width*2,height*2,FLOAT_TYPE);	(*mv_y)=AllocImage(width*2,height*2,FLOAT_TYPE);	data_x = (Float*)GetImageData((*mv_x));	data_y = (Float*)GetImageData((*mv_y));	data_mode = (SInt*)GetImageData((*mode));	mode16=(SInt*)GetImageData(imode16);	mv16_w=(Float*)GetImageData(imv16_w);	mv16_h=(Float*)GetImageData(imv16_h);	mv8_w=(Float*)GetImageData(imv8_w);	mv8_h=(Float*)GetImageData(imv8_h);	for(j=0;j<height;j++)	{		for(i=0;i< width;i++)		{			modo=data_mode[j*width+i]=mode16[j*width+i];			if ( modo==MBM_INTRA)				  /*INTRA*/			{				base=2*j*2*width+2*i;				data_x[base]=0.0;  data_x[base+1]=0.0;				data_y[base]=0.0;  data_y[base+1]=0.0;				base+=width*2;				data_x[base]=0.0;  data_x[base+1]=0.0;				data_y[base]=0.0;  data_y[base+1]=0.0;			}			else if(modo==MBM_INTER16)			  /*INTER 16*/			{				base=2*j*2*width+2*i;				val_x=mv16_w[base];val_y=mv16_h[base];				data_x[base]=val_x; data_x[base+1]=val_x;				data_y[base]=val_y; data_y[base+1]=val_y;				base+=width*2;				data_x[base]=val_x; data_x[base+1]=val_x;				data_y[base]=val_y; data_y[base+1]=val_y;			}			else if (modo==MBM_INTER8)			  /*INTER4*8*/			{				base=2*j*2*width+2*i;				data_x[base]   = mv8_w[base];				data_y[base]   = mv8_h[base];				data_x[base+1] = mv8_w[base+1];				data_y[base+1] = mv8_h[base+1];				base+=width*2;				data_x[base]   = mv8_w[base];				data_y[base]   = mv8_h[base];				data_x[base+1] = mv8_w[base+1];				data_y[base+1] = mv8_h[base+1];			}		}										  /* end for*/	}											  /* end for*/	return(1);}/***********************************************************CommentBegin****** * * -- ChooseMode -- chooses coding mode INTRA/INTER dependig on the SAD values * * Purpose : *      chooses coding mode INTRA/INTER dependig on the SAD values * * Return values : *      1 for INTER, 0 for INTRA * ***********************************************************CommentEnd********/IntChooseMode(SInt   *curr,									  /* <-- current Y values (not extended)          */Int    x_pos,									  /* <-- upper-left MB corner hor. coor.          */Int    y_pos,									  /* <-- upper-left MB corner ver. coor.          */Int    min_SAD,									  /* <-- min SAD (from integer pel search)        */UInt   width									  /* <-- current Y picture width                  */){	Int   i, j;	Int   MB_mean = 0, A = 0;	Int   y_off;	for (j = 0; j < MB_SIZE; j++)	{		y_off = (y_pos + j) * width;		for (i = 0; i < MB_SIZE; i++)		{			MB_mean += *(curr + x_pos + i + y_off);		}	}	MB_mean /= 256;	for (j = 0; j < MB_SIZE; j++)	{		y_off = (y_pos + j) * width;		for (i = 0; i < MB_SIZE; i++)		{				A += abs( *(curr + x_pos + i + y_off) - MB_mean );		}	}	if (A < (min_SAD - 2*256))		return 0;	else		return 1;}/***********************************************************CommentBegin****** * * -- SAD_Macroblock -- obtains the SAD for a Macroblock * * Purpose : *      obtains the SAD for a Macroblock * * Return values : *      sad of the MB * ***********************************************************CommentEnd********/IntSAD_Macroblock(SInt   *ii,										  /* <-- Pointer to the upper-left pel of first MB */SInt   *act_block,								  /* <-- Id, second MB (width=16)                  */UInt   h_length,								  /* <-- Width of first area                       */Int    Min_FRAME								  /* <-- Minimum prediction error so far           */){/*	Int    i;	Int    sad = 0;	SInt   *kk;	register Int P_diff;	kk = act_block;	i = 16;	while (i--)	{		sad += (DIFF1(ii,kk,0)+DIFF1(ii,kk,1)			+DIFF1(ii,kk,2)+DIFF1(ii,kk,3)			+DIFF1(ii,kk,4)+DIFF1(ii,kk,5)			+DIFF1(ii,kk,6)+DIFF1(ii,kk,7)			+DIFF1(ii,kk,8)+DIFF1(ii,kk,9)			+DIFF1(ii,kk,10)+DIFF1(ii,kk,11)			+DIFF1(ii,kk,12)+DIFF1(ii,kk,13)			+DIFF1(ii,kk,14)+DIFF1(ii,kk,15)			);		ii += h_length;		kk += 16;		if (sad > Min_FRAME)			return MV_MAX_ERROR;	}	return sad;*/	int i, j;	int sad = 0;	SInt *p1 = ii, *p2 = act_block;	i = 16;	while (i--) {		j = 16;		while (j --)			sad += abs((int)*(p1++) - (int)*(p2++));		if (sad > Min_FRAME)			return MV_MAX_ERROR;		p1 += h_length - 16;	}	return sad;}/***********************************************************CommentBegin****** * * -- SAD_Block -- obtains the SAD for a Block * * Purpose : *      obtains the SAD for a Block * * Return values : *      sad of the Block * ***********************************************************CommentEnd********/IntSAD_Block(SInt   *ii,										  /* <-- First area                      */SInt   *act_block,								  /* <-- Id. second MB (width=16)        */UInt   h_length,								  /* <-- Width of first area             */Int    min_sofar								  /* <-- Minimum prediction error so far */){/*	Int    i;	Int    sad = 0;	SInt   *kk;	register Int P_diff;	kk = act_block;	i = 8;	while (i--)	{		sad += (DIFF1(ii,kk,0)+DIFF1(ii,kk,1)			+DIFF1(ii,kk,2)+DIFF1(ii,kk,3)			+DIFF1(ii,kk,4)+DIFF1(ii,kk,5)			+DIFF1(ii,kk,6)+DIFF1(ii,kk,7)			);		ii += h_length;		kk += 16;		if (sad > min_sofar)			return INT_MAX;	}	return sad;*/	int i, j;	int sad = 0;	SInt *p1 = ii, *p2 = act_block;	i = 8;	while (i--) {		j = 8;		while (j --)			sad += abs((int)*(p1++) - (int)*(p2++));		if (sad > min_sofar)			return INT_MAX;		p1 += h_length - 8;		p2 += 16 - 8;	}	return sad;}/***********************************************************CommentBegin****** * * -- LoadArea -- fills array with a image-data * * Purpose : *      fills array with a image-data * * Return values : *      Pointer to the filled array * ***********************************************************CommentEnd********/VoidLoadArea(SInt	*im,									  /* <-- pointer to image         */Int		x,										  /* <-- horizontal pos           */Int		y,										  /* <-- vertical  pos            */Int		x_size,									  /* <-- width of array           */Int		y_size,									  /* <-- height of array          */Int		lx,										  /* <-- width of the image data  */SInt	*block									  /* <-> pointer to the array     */){	SInt   *in;	SInt   *out;	Int    i = x_size;	Int    j = y_size;	in = im + (y*lx) + x;	out = block;	while (j--)	{		while (i--)			*out++ = *in++;		i = x_size;		in += lx - x_size;	}	return;}/***********************************************************CommentBegin****** * * -- SetArea -- fills a image-data with an array * * Purpose : *      fills a image-data with an array * ***********************************************************CommentEnd********/VoidSetArea(SInt   *block,									  /* <-- pointer to array         */Int    x,										  /* <-- horizontal pos in image  */Int    y,										  /* <-- vertical  pos in image   */Int    x_size,									  /* <-- width of array           */Int    y_size,									  /* <-- height of array          */Int    lx,										  /* <-- width of the image data  */SInt   *im										  /* --> pointer to image         */){	SInt   *in;	SInt   *out;	Int    i = x_size;	Int    j = y_size;	in  = block;	out = im + (y*lx) + x;	while (j--)	{		while (i--)			*out++ = *in++;		i = x_size;		out += lx - x_size;	}}

⌨️ 快捷键说明

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