www.pudn.com > NETVIDEO.rar > motion.c


#include "mpeg3video.h" 
#include "vlc.h" 
 
#include  
 
 
/* calculate motion vector component */ 
 
void mpeg3video_calc_mv(int *pred, int r_size, int motion_code, int motion_r, int full_pel_vector) 
{ 
	int lim = 16 << r_size; 
	int vec = full_pel_vector ? (*pred >> 1) : (*pred); 
 
	if(motion_code > 0) 
	{ 
    	vec += ((motion_code - 1) << r_size) + motion_r + 1; 
    	if(vec >= lim) vec -= lim + lim; 
	} 
	else  
	if(motion_code < 0) 
	{ 
    	vec -= ((-motion_code - 1) << r_size) + motion_r + 1; 
    	if(vec < -lim) vec += lim + lim; 
	} 
	*pred = full_pel_vector ? (vec << 1) : vec; 
} 
 
 
/* 
int *dmvector, * differential motion vector * 
int mvx, int mvy  * decoded mv components (always in field format) * 
*/ 
void mpeg3video_calc_dmv(mpeg3video_t *video,  
		int DMV[][2],  
		int *dmvector,  
		int mvx,  
		int mvy) 
{ 
	if(video->pict_struct == FRAME_PICTURE) 
	{ 
    	if(video->topfirst) 
		{ 
/* vector for prediction of top field from bottom field */ 
    		DMV[0][0] = ((mvx  + (mvx>0)) >> 1) + dmvector[0]; 
    		DMV[0][1] = ((mvy  + (mvy>0)) >> 1) + dmvector[1] - 1; 
 
/* vector for prediction of bottom field from top field */ 
    		DMV[1][0] = ((3 * mvx + (mvx > 0)) >> 1) + dmvector[0]; 
    		DMV[1][1] = ((3 * mvy + (mvy > 0)) >> 1) + dmvector[1] + 1; 
    	} 
    	else  
		{ 
/* vector for prediction of top field from bottom field */ 
    		DMV[0][0] = ((3 * mvx + (mvx>0)) >> 1) + dmvector[0]; 
    		DMV[0][1] = ((3 * mvy + (mvy>0)) >> 1) + dmvector[1] - 1; 
 
/* vector for prediction of bottom field from top field */ 
    		DMV[1][0] = ((mvx + (mvx>0)) >> 1) + dmvector[0]; 
    		DMV[1][1] = ((mvy + (mvy>0)) >> 1) + dmvector[1] + 1; 
    	} 
	} 
	else  
	{ 
/* vector for prediction from field of opposite 'parity' */ 
    	DMV[0][0] = ((mvx + (mvx > 0)) >> 1) + dmvector[0]; 
    	DMV[0][1] = ((mvy + (mvy > 0)) >> 1) + dmvector[1]; 
 
/* correct for vertical field shift */ 
    	if(video->pict_struct == TOP_FIELD) 
			DMV[0][1]--; 
    	else  
			DMV[0][1]++; 
	} 
} 
 
int mpeg3video_get_mv(mpeg3_slice_t *slice) 
{ 
  	int code; 
	mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; 
 
  	if(mpeg3slice_getbit(slice_buffer)) 
	{ 
    	return 0; 
  	} 
 
  	if((code = mpeg3slice_showbits9(slice_buffer)) >= 64) 
	{ 
    	code >>= 6; 
    	mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab0[code].len); 
    	return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab0[code].val : mpeg3_MVtab0[code].val; 
  	} 
 
  	if(code >= 24) 
	{ 
    	code >>= 3; 
    	mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab1[code].len); 
	    return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab1[code].val : mpeg3_MVtab1[code].val; 
  	} 
 
  	if((code -= 12) < 0) 
	{ 
/*    	fprintf(stdout,"mpeg3video_get_mv: invalid motion_vector code\n"); */ 
    	slice->fault = 1; 
    	return 1; 
  	} 
 
  	mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab2[code].len); 
 	return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab2[code].val : mpeg3_MVtab2[code].val; 
} 
 
/* get differential motion vector (for dual prime prediction) */ 
 
int mpeg3video_get_dmv(mpeg3_slice_t *slice) 
{ 
	mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; 
  	if(mpeg3slice_getbit(slice_buffer)) 
	{ 
    	return mpeg3slice_getbit(slice_buffer) ? -1 : 1; 
  	} 
  	else  
	{ 
    	return 0; 
  	} 
} 
 
 
 
/* get and decode motion vector and differential motion vector */ 
 
void mpeg3video_motion_vector(mpeg3_slice_t *slice, 
		mpeg3video_t *video,  
		int *PMV,  
		int *dmvector,  
		int h_r_size,  
		int v_r_size, 
		int dmv,  
		int mvscale,  
		int full_pel_vector) 
{ 
	int motion_r; 
	int motion_code = mpeg3video_get_mv(slice); 
	mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; 
 
	if(slice->fault) return; 
	motion_r = (h_r_size != 0 && motion_code != 0) ? mpeg3slice_getbits(slice_buffer, h_r_size) : 0; 
 
  	mpeg3video_calc_mv(&PMV[0], h_r_size, motion_code, motion_r, full_pel_vector); 
 
  	if(dmv) dmvector[0] = mpeg3video_get_dmv(slice); 
 
  	motion_code = mpeg3video_get_mv(slice); 
  	if(slice->fault)  return; 
  	motion_r = (v_r_size != 0 && motion_code != 0) ? mpeg3slice_getbits(slice_buffer, v_r_size) : 0; 
 
/* DIV 2 */ 
  	if(mvscale) PMV[1] >>= 1;  
 
  	mpeg3video_calc_mv(&PMV[1], v_r_size, motion_code, motion_r, full_pel_vector); 
 
	if(mvscale) PMV[1] <<= 1; 
	if(dmv) dmvector[1] = mpeg3video_get_dmv(slice); 
} 
 
int mpeg3video_motion_vectors(mpeg3_slice_t *slice, 
		mpeg3video_t *video,  
		int PMV[2][2][2],  
		int dmvector[2],  
		int mv_field_sel[2][2], 
		int s,  
		int mv_count,  
		int mv_format,  
		int h_r_size,  
		int v_r_size,  
		int dmv,  
		int mvscale) 
{ 
	int result = 0; 
	mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; 
	if(mv_count == 1) 
	{ 
		if(mv_format == MV_FIELD && !dmv) 
		{ 
			mv_field_sel[1][s] = mv_field_sel[0][s] = mpeg3slice_getbit(slice_buffer); 
		} 
 
    	mpeg3video_motion_vector(slice,  
			video,  
			PMV[0][s],  
			dmvector,  
			h_r_size,  
			v_r_size,  
			dmv,  
			mvscale,  
			0); 
    	if(slice->fault) return 1; 
 
/* update other motion vector predictors */ 
    	PMV[1][s][0] = PMV[0][s][0]; 
    	PMV[1][s][1] = PMV[0][s][1]; 
  	} 
  	else  
	{ 
    	mv_field_sel[0][s] = mpeg3slice_getbit(slice_buffer); 
    	mpeg3video_motion_vector(slice,  
			video,  
			PMV[0][s],  
			dmvector,  
			h_r_size,  
			v_r_size,  
			dmv,  
			mvscale,  
			0); 
    	if(slice->fault) return 1; 
 
    	mv_field_sel[1][s] = mpeg3slice_getbit(slice_buffer); 
    	mpeg3video_motion_vector(slice,  
			video,  
			PMV[1][s],  
			dmvector,  
			h_r_size,  
			v_r_size,  
			dmv,  
			mvscale,  
			0); 
    	if(slice->fault) return 1; 
  	} 
	return 0; 
}