📄 mot_est.cpp
字号:
/*!
********************************************************
*\file
* mot_est.cpp
*\brief
* implementation for functions which is used for motion estimation.
*\date
* 12/6/2002
*
********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "mot_est.h"
#define MAX_SAD 99999 //!< MAX_SAD
#define PREF_NULL_VEC 100 //!< according to tmn
#define PREF_16_VEC 200 //!< according to tmn
//#define PRINTMV
//!MVFAST STRUCTURE
typedef struct {
int x;
int y;
int iStartNmbr;
} DPOINT;
//!MVFAST STRUCTURE
typedef struct {
int no_check_pts;
DPOINT dpoint[8];
} DIAMOND;
//!MVFAST DATA USED
static DIAMOND diamond[3]={
{4,{{0,1,3},{1,0,0},{0,-1,1},{-1,0,2}}},
{8,{{0,2,6},{1,1,0},{2,0,0},{1,-1,2},{0,-2,2},{-1,-1,4},{-2,0,4},{-1,1,6}}},
{3,{{0,0,0},{0,0,0,},{0,0,0}}}
};
//!MVFAST STRUCTURE
enum {SDiamond, LDiamond, MotAdaptPat} dType;
/*!
*******************************************************************************
*
* Name: interpolate_lum
* Description: make interpolated lum image for 1/2 pel mv search
* Input:
* Output:
* Side effect: fill the buffer for interpolated image(encoder->prev_ipol)
* Optimization: NO
* Last modified: 2002/11/21
*
*******************************************************************************/
void interpolate_lum_c(H263VencStatus *encoder)
{
int width = encoder->mv_outside_frame ? encoder->pels+32 : encoder->pels;
int height = encoder->mv_outside_frame ? encoder->lines+32: encoder->lines;
unsigned char *oo = encoder->mv_outside_frame ? (encoder->frame_buf[encoder->ref_index]).pLum-width*16-16 : (encoder->frame_buf[encoder->ref_index]).pLum;
unsigned char *ii = encoder->mv_outside_frame ? encoder->prev_ipol-width*64-32 : encoder->prev_ipol;
int i, j;
if (encoder->PTYPE == B_IMG)
{
/* for backward mv search */
// it is always permitted that MVs be across the picture boundary
oo = encoder->frame_buf[encoder->zero_index].pLum - width*16 - 16;
ii = encoder->next_ipol - width*64 - 32;
}
/* 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)>>1;
*(ii + (i<<1)+(width<<1)) = (*(oo + i) + *(oo + i + width) + 1)>>1;
*(ii + (i<<1)+1+(width<<1)) = (*(oo+i) + *(oo+i+1) +
*(oo+i+width) + *(oo+i+1+width) + 2)>>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)>>1;
*(ii+ (width<<1)+ (width<<1)-1) = (*(oo+width-1)+*(oo+width+width-1)+1)>>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)>>1;
*(ii+ (width<<1)+ (i<<1)) = *(oo + i);
*(ii+ (width<<1)+ (i<<1)+1) = (*(oo + i) + *(oo + i + 1) + 1)>>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);
}
/*!
*******************************************************************************
*
* Name: grabVec
* Description: refine best motion vectors and choose best mode for all mbs
* of one picture
* Input: the pointer of encoder strcture and MC structure
* Output: MV(in MC structure)
* Last modified: 2002/11/21
*
*******************************************************************************/
void grabVec(H263VencStatus *encoder, MCParam *MC, int BACKWARD)
{
int i, j;
int pix_x, pix_y;
int pix_x_8, pix_y_8;
int block;
int x_center, y_center;
int sad_gate = 512;
void (*mv_search) (H263VencStatus*, MCParam*, int, int, int, int); //!< search functions
// added by lcl on 2003/2/26, parameter for calculation of SAD
int lx1 = encoder->pels;
int lx2 = encoder->mv_outside_frame ? encoder->pels+32 : encoder->pels;
unsigned char *p1 = (encoder->frameToEncode).pLum ;
if (encoder->PTYPE == B_IMG)
{
p1 = (encoder->BPicture[encoder->B_count]).pLum;
}
//! choose search method
if (0 == MC->method)
{
mv_search = mv_search_fs;
}
else if(1 == MC->method)
{
mv_search = mv_search_dmd;
}
else
{
printf("Invalid MV search method");
exit(-1);
}
/*! main loop */
for (pix_y = 0, i = 0; pix_y < encoder->lines; pix_y+=16, i++)
{
for (pix_x = 0, j = 0; pix_x < encoder->pels; pix_x+=16, j++)
{
if (!BACKWARD)
{
/* Forward MV search(for both P frames and B frames). */
MC->mv = MC->mv_frame[0][i+1][j+1]; //!< assign a pointer for current mv
//! check zero point ahead of searching
(MC->mv)->x = 0;
(MC->mv)->y = 0;
(MC->mv)->min_sad = encoder->method.me_sad_a(lx1, lx2, pix_x, pix_y, pix_x, pix_y, p1,
encoder->frame_buf[encoder->ref_index].pLum,
MAX_SAD, 16) - PREF_NULL_VEC;
// (MC->mv)->min_sad = me_sad_a(encoder, pix_x, pix_y, pix_x, pix_y, MAX_SAD, 16, 0) - PREF_NULL_VEC;
if ((MC->mv)->min_sad > sad_gate)
{
mv_search(encoder, MC, pix_x, pix_y, 16, BACKWARD); //!< search integer mv (predictor of mv not used)
}
findhalfpel(encoder, MC, pix_x, pix_y, 16, BACKWARD);
//! 8x8 block Search(only for P frames).
if (encoder->use4mv && (encoder->PTYPE!=B_IMG))
{
for (block = 0; block < 4; block++)
{
pix_x_8 = pix_x+((block&1)<<3);
pix_y_8 = pix_y+((block&2)<<2);
MC->mv = MC->mv_frame[block+1][i+1][j+1]; //!< assign a pointer
// decide searching center
x_center = MC->mv_frame[0][i+1][j+1]->x;
y_center = MC->mv_frame[0][i+1][j+1]->y;
if (x_center > 15 - MC->search_range_8x8) { x_center = 15 - MC->search_range_8x8; }
if (y_center > 15 - MC->search_range_8x8) { y_center = 15 - MC->search_range_8x8; }
if (x_center < -15 + MC->search_range_8x8) { x_center = -15 + MC->search_range_8x8; }
if (y_center < -15 + MC->search_range_8x8) { y_center = -15 + MC->search_range_8x8; }
// do pre-search check
(MC->mv)->x = x_center;
(MC->mv)->y = y_center;
(MC->mv)->min_sad = encoder->method.me_sad_a(lx1, lx2, pix_x_8, pix_y_8, pix_x_8+x_center, pix_y_8+y_center, p1,
encoder->frame_buf[encoder->ref_index].pLum, MAX_SAD, 8);
// (MC->mv)->min_sad = me_sad_a(encoder, pix_x_8, pix_y_8, pix_x_8+x_center, pix_y_8+y_center, MAX_SAD, 8, 0);
if((MC->mv)->min_sad > sad_gate/4)
{
mv_search(encoder, MC, pix_x_8, pix_y_8, 8, BACKWARD);
}
findhalfpel(encoder, MC, pix_x_8, pix_y_8, 8, BACKWARD);
}
}
}
else
{
/*! Backward MV Search(only for B frames). */
if (encoder->PTYPE == B_IMG)
{
MC->mv = MC->mv_frame[5][i+1][j+1]; //!< assign a pointer
// check zero point ahead of searching
(MC->mv)->x = 0;
(MC->mv)->y = 0;
(MC->mv)->min_sad = encoder->method.me_sad_a(lx1, lx2, pix_x, pix_y, pix_x, pix_y, p1,
encoder->frame_buf[encoder->zero_index].pLum,
MAX_SAD, 16) - PREF_NULL_VEC;
// (MC->mv)->min_sad = me_sad_a(encoder, pix_x, pix_y, pix_x, pix_y, MAX_SAD, 16, 1) - PREF_NULL_VEC;
if ((MC->mv)->min_sad > sad_gate)
{
mv_search(encoder, MC, pix_x, pix_y, 16, BACKWARD); //!< search integer mv (predictor of mv not used)
}
findhalfpel(encoder, MC, pix_x, pix_y, 16, BACKWARD);
}
}
/* Choose mode(only for P frames, prediction mode of B frames
will be decided outside). */
if (encoder->PTYPE != B_IMG)
{
choose_mode(encoder, MC, pix_x, pix_y);
}
#ifdef PRINTMV
printmv(encoder, MC, i, j, BACKWARD);
#endif
}
#ifdef PRINTMV
printf("\n");
#endif
}
}
/*!
*******************************************************************************
*
* Name: FindPMV
* Description: find predictor for mv of current block
* Input: Array of motion vectors, positon of current block
* Output: x value and y value of predictor
* Last modified: 2002/11/23 by lcl
*
*******************************************************************************/
void FindPMV(MotionVector *MV[6][MBR+1][MBC+2], int x, int y,
int *pmv0, int *pmv1, int block, int newgob, int half_pel)
{
int p1,p2,p3;
int xin1,xin2,xin3;
int yin1,yin2,yin3;
int vec1,vec2,vec3;
int l8,o8,or8;
l8 = o8 = or8 = 0;
if ((MV[0][y][x-1]->Mode == MODE_INTER4V) || (MV[0][y][x-1]->Mode == MODE_INTER4V_Q))
{
l8 = 1;
}
if ((MV[0][y-1][x]->Mode == MODE_INTER4V) || (MV[0][y-1][x]->Mode == MODE_INTER4V_Q))
{
o8 = 1;
}
if ((MV[0][y-1][x+1]->Mode == MODE_INTER4V || MV[0][y-1][x+1]->Mode == MODE_INTER4V_Q))
{
or8 = 1;
}
switch (block)
{
case 0:
vec1 = (l8 ? 2 : 0) ; yin1 = y ; xin1 = x-1;
vec2 = (o8 ? 3 : 0) ; yin2 = y-1; xin2 = x;
vec3 = (or8? 3 : 0) ; yin3 = y-1; xin3 = x+1;
break;
case 1:
vec1 = (l8 ? 2 : 0) ; yin1 = y ; xin1 = x-1;
vec2 = (o8 ? 3 : 0) ; yin2 = y-1; xin2 = x;
vec3 = (or8? 3 : 0) ; yin3 = y-1; xin3 = x+1;
break;
case 2:
vec1 = 1 ; yin1 = y ; xin1 = x;
vec2 = (o8 ? 4 : 0) ; yin2 = y-1; xin2 = x;
vec3 = (or8? 3 : 0) ; yin3 = y-1; xin3 = x+1;
break;
case 3:
vec1 = (l8 ? 4 : 0) ; yin1 = y ; xin1 = x-1;
vec2 = 1 ; yin2 = y ; xin2 = x;
vec3 = 2 ; yin3 = y ; xin3 = x;
break;
case 4:
vec1 = 3 ; yin1 = y ; xin1 = x;
vec2 = 1 ; yin2 = y ; xin2 = x;
vec3 = 2 ; yin3 = y ; xin3 = x;
break;
default:
fprintf(stderr,"Illegal block number in FindPMV (countbit.c)\n");
exit(-1);
break;
}
if (half_pel)
{
p1 = 2*MV[vec1][yin1][xin1]->x + MV[vec1][yin1][xin1]->x_half;
p2 = 2*MV[vec2][yin2][xin2]->x + MV[vec2][yin2][xin2]->x_half;
p3 = 2*MV[vec3][yin3][xin3]->x + MV[vec3][yin3][xin3]->x_half;
}
else
{
p1 = 2*MV[vec1][yin1][xin1]->x;
p2 = 2*MV[vec2][yin2][xin2]->x;
p3 = 2*MV[vec3][yin3][xin3]->x;
}
if (newgob && (block == 0 || block == 1 || block == 2))
{
p2 = 2 * NO_VEC; //!< MV above can not be accessed
}
if (p2 == 2*NO_VEC)
{
p2 = p3 = p1; //!< When MV above can not be accessed, use left MV instead
}
*pmv0 = p1+p2+p3 - mmax(p1,mmax(p2,p3)) - mmin(p1,mmin(p2,p3));
if (half_pel)
{
p1 = 2*MV[vec1][yin1][xin1]->y + MV[vec1][yin1][xin1]->y_half;
p2 = 2*MV[vec2][yin2][xin2]->y + MV[vec2][yin2][xin2]->y_half;
p3 = 2*MV[vec3][yin3][xin3]->y + MV[vec3][yin3][xin3]->y_half;
}
else
{
p1 = 2*MV[vec1][yin1][xin1]->y;
p2 = 2*MV[vec2][yin2][xin2]->y;
p3 = 2*MV[vec3][yin3][xin3]->y;
}
if (newgob && (block == 0 || block == 1 || block == 2))
{
p2 = 2 * NO_VEC; //!< MV above can not be accessed
}
if (p2 == 2*NO_VEC)
{
p2 = p3 = p1; //!< When MV above can not be accessed, use left MV instead
}
*pmv1 = p1+p2+p3 - mmax(p1,mmax(p2,p3)) - mmin(p1,mmin(p2,p3));
}
/*!
*******************************************************************************
*
* Name: FindPMV_B
* Description: find predictor for mv of current block for B picture
* Input: Array of motion vectors, positon of current block
* Output: x value and y value of predictor
* Last modified: 2003/1/13 by lcl
*
*******************************************************************************/
void FindPMV_B(MotionVector *MV[6][MBR+1][MBC+2], int x, int y,
int *pmv0, int *pmv1, int newgob, int half_pel, int BACKWARD)
{
int vec = BACKWARD ? 5 : 0;
int yin1 = y;
int xin1 = x-1;
int yin2 = y-1;
int xin2 = x;
int yin3 = y-1;
int xin3 = x+1;
int p1, p2, p3;
if (half_pel)
{
p1 = 2*MV[vec][yin1][xin1]->x + MV[vec][yin1][xin1]->x_half;
p2 = 2*MV[vec][yin2][xin2]->x + MV[vec][yin2][xin2]->x_half;
p3 = 2*MV[vec][yin3][xin3]->x + MV[vec][yin3][xin3]->x_half;
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -