/* recon.c */

#include "mphead.h"

extern short block[64];
extern full_pel_forw,full_pel_back;
extern mb_address,mb_past_mb_addr;
extern down_for_prev,right_for_prev;
extern down_back_prev,right_back_prev;
extern past_forw,past_back;
extern mb_width,mod_y,mod_c;
extern struct pict_image *past,*future,*current;

#define COPY_8(a,b)	(((int *)(a))[0]=((int *)(b))[0],((int *)(a))[1]=((int *)(b))[1])
#define ZERO_8(a)	(((int *)(a))[0]=((int *)(a))[1]=0)

static unsigned char crop_table_array[256+255];
unsigned char *crop_table;

init_recon()
{
	int i;

	crop_table = (unsigned char *)((int)(crop_table_array+255) & ~255);
	for (i=0; i<64; i++)
		crop_table[96+i] = i;
	for (i=0; i<96; i++) {
		crop_table[i] = 0;
		crop_table[i+96+64] = 63;
	}
}

recon_i_mblock(n,zflag)
{
	int i;
	int row,col,mod;
	unsigned char *d;

	row = mb_address / mb_width;
	col = mb_address % mb_width;
	d = current->o[n];
	if (n < 4) {
		mod = mod_y;
		d += (row*mod+col)*16;
	}
	else {
		mod = mod_c;
		d += (row*mod+col)*8;
	}
	if (!zflag) {
		copy_crop_8x8(d,block,mod);
		return;
	}
	zero_8x8(d,mod);
}

recon_p_or_b_mblock(n,right,down,p,zflag)
struct pict_image *p;
{
	int i;
	int mod,row,col;
	unsigned char *d,*e;

	row = mb_address / mb_width;
	col = mb_address % mb_width;
	if (n < 4) {
		mod = mod_y;
		i = (row*mod+col)*16;
		d = current->o[n] + i;
		e = p->o[n] + i + (down>>1)*mod + (right>>1);
	}
	else {
		mod = mod_c;
		i = (row*mod+col)*8;
		d = current->o[n] + i;
		e = p->o[n] + i + (down>>2)*mod + (right>>2);
	}
	if (!zflag) {
		add_crop_8x8(d,e,block,mod);
		return;
	}
	copy_8x8(d,e,mod);
}

recon_bi_mblock(n,p_right,p_down,f_right,f_down,zflag)
{
	int i;
	int mod,row,col;
	unsigned char *d,*e,*f;

	row = mb_address / mb_width;
	col = mb_address % mb_width;
	if (n < 4) {
		mod = mod_y;
		i = (row*mod+col)*16;
		d = current->o[n] + i;
		e = past->o[n] + i + (p_down>>1)*mod + (p_right>>1);
		f = future->o[n] + i + (f_down>>1)*mod + (f_right>>1);
	}
	else {
		mod = mod_c;
		i = (row*mod+col)*8;
		d = current->o[n] + i;
		e = past->o[n] + i + (p_down>>2)*mod + (p_right>>2);
		f = future->o[n] + i + (f_down>>2)*mod + (f_right>>2);
	}
	if (!zflag) {
		add_average_crop_8x8(d,e,f,block,mod);
		return;
	}
	average_8x8(d,e,f,mod);
}

process_skipped_b_mblocks()
{
	int a,i,j,o,o2,fo,fo2,po,po2;
	unsigned char *d,*e,*f;

	i = down_for_prev;
	j = right_for_prev;
	if (!full_pel_forw) {
		i >>= 1;
		j >>= 1;
	}
	po = i*mod_y+j;
	po2 = (i>>1)*mod_c+(j>>1);
	i = down_back_prev;
	j = right_back_prev;
	if (!full_pel_back) {
		i >>= 1;
		j >>= 1;
	}
	fo = i*mod_y+j;
	fo2 = (i>>1)*mod_c+(j>>1);
	for (a=mb_past_mb_addr+1; a<mb_address; a++) {
		i = a / mb_width;
		j = a % mb_width;
		o = (i*mod_y+j)*16;
		o2 = (i*mod_c+j)*8;
		if (past_forw && past_back) {
			average_16x16(current->lum+o,past->lum+o+po,future->lum+o+fo,mod_y);
			average_8x8(current->cr+o2,past->cr+o2+po2,future->cr+o2+fo2,mod_c);
			average_8x8(current->cb+o2,past->cb+o2+po2,future->cb+o2+fo2,mod_c);
		}
		else if (past_forw) {
			copy_16x16(current->lum+o,past->lum+o+po,mod_y);
			copy_8x8(current->cr+o2,past->cr+o2+po2,mod_c);
			copy_8x8(current->cb+o2,past->cb+o2+po2,mod_c);
		}
		else {
			copy_16x16(current->lum+o,future->lum+o+fo,mod_y);
			copy_8x8(current->cr+o2,future->cr+o2+fo2,mod_c);
			copy_8x8(current->cb+o2,future->cb+o2+fo2,mod_c);
		}
	}
}

process_skipped_p_mblocks()
{
	int i,j,a;
	int o,o2;

	for (a=mb_past_mb_addr+1; a<mb_address; a++) {
		i = a / mb_width;
		j = a % mb_width;
		o = (i*mod_y+j)*16;
		o2 = (i*mod_c+j)*8;
		copy_16x16(current->lum+o,future->lum+o,mod_y);
		copy_8x8(current->cr+o2,future->cr+o2,mod_c);
		copy_8x8(current->cb+o2,future->cb+o2,mod_c);
	}
	right_for_prev = 0;
	down_for_prev = 0;
}
