/************************************************************************** * * * 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 * **************************************************************************/ /* 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********/ Void InterpolateImage( 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********/ Int GetMotionImages( 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 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********/ Int SAD_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********/ Void LoadArea( 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********/ Void SetArea( 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; } }