www.pudn.com > lencod.rar > image.c


/*
***********************************************************************
* COPYRIGHT AND WARRANTY INFORMATION
*
* Copyright 2003, Advanced Audio Video Coding Standard, Part II
*
* DISCLAIMER OF WARRANTY
*
* These software programs are available to the users without any
* license fee or royalty on an "as is" basis. The AVS disclaims
* any and all warranties, whether express, implied, or statutory,
* including any implied warranties of merchantability or of fitness
* for a particular purpose. In no event shall the contributors or
* the AVS be liable for any incidental, punitive, or consequential
* damages of any kind whatsoever arising from the use of this program.
*
* This disclaimer of warranty extends to the user of this program
* and user's customers, employees, agents, transferees, successors,
* and assigns.
*
* The AVS does not represent or warrant that the program furnished
* hereunder are free of infringement of any third-party patents.
* Commercial implementations of AVS, including shareware, may be
* subject to royalty fees to patent holders. Information regarding
* the AVS patent policy is available from the AVS Web site at
* http://www.avs.org.cn
*
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY.
************************************************************************
*/

/*
*************************************************************************************
* File name:
* Function:
*
*************************************************************************************
*/
#include "contributors.h"

#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <sys/timeb.h>
#include <string.h>
#include <memory.h>
#include <assert.h>

#include "global.h"
#include "image.h"
#include "refbuf.h"
#include "mbuffer.h"
#include "header.h"
#include "memalloc.h"
#include "bitstream.h"
#include "ratectl.h"
#include "vlc.h"

#define TO_SAVE 4711
#define FROM_SAVE 4712
#define Clip(min,max,val) (((val)<(min))?(min):(((val)>(max))?(max):(val)))

static void code_a_picture(Picture *frame);
static void ReadOneFrame (int FrameNoInFile, int HeaderSize, int xs, int ys);
static void write_reconstructed_image();
static int writeout_picture();
static int writeout_slice();
static void find_snr();
static void frame_mode_buffer (int bit_frame, float snr_frame_y, float snr_frame_u, float snr_frame_v);
static void init_frame();
void init_field ();

void top_field(Picture *pic);
void bot_field(Picture *pic);

void combine_field();
int terminate_picture();


void put_buffer_frame();
void put_buffer_top();
void put_buffer_bot();
void interpolate_frame_to_fb();

static void CopyFrameToOldImgOrgVariables ();
static void UnifiedOneForthPix (pel_t ** imgY, pel_t ** imgU, pel_t ** imgV,
pel_t ** out4Y);
static void ReportFirstframe(int tmp_time);
static void ReportIntra(int tmp_time);
static void ReportP(int tmp_time);
static void ReportB(int tmp_time);

static int CalculateFrameNumber(); // Calculates the next frame number
static int FrameNumberInFile; // The current frame number in the input file

// !! weighting prediction
// The two fuctions below can be rewritten by other algorithms
// Determine the parameters of weighting prediction
void estimate_weighting_factor();
//cjw 20051219 weighting prediction for field
void estimate_weighting_factor_field();

#define IClip( Min, Max, Val) (((Val)<(Min))? (Min):(((Val)>(Max))? (Max):(Val)))

//Rate control
int QP;

/*
*************************************************************************
* Function:
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void stuffing_byte(int n)
{
int i;
Bitstream *currStream;

currStream = currBitStream;

for(i=0; i<n; i++)
{
currStream->streamBuffer[currStream->byte_pos++] = 0x80;
currStream->bits_to_go = 8;
currStream->byte_buf = 0;
}
}

/*
*************************************************************************
* Function:
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

static void picture_header()
{
int len=0;

Bitstream *bitstream = currBitStream;
img->cod_counter = 0;

if(img->type==INTRA_IMG)
{
if((input->InterlaceCodingOption == FRAME_CODING)||(input->InterlaceCodingOption == FIELD_CODING)) //add by wuzhongmou
{
if(input->vec_period) //add by wuzhongmou
{
if(img->count>input->vec_period ==0)
{
len = u_v(32, "video_edit_code",0x1B7,bitstream); //add by wuzhongmou
img->VEC_FLAG=1;
img->count_PAFF=0; //add by wuzhongmou
}
}

if(input->vec_period==0)
{
if(img->count==0)
{
len = u_v(32, "video_edit_code",0x1B7,bitstream); //add by cjw only first
img->VEC_FLAG=1;
img->count_PAFF=0; //add by cjw only first
}
}
}
if((input->InterlaceCodingOption == PAFF_CODING))
{
if(input->vec_period) //add by wuzhongmou
{
if(((img->count-1)>input->vec_period ==0)||(img->count>input->vec_period ==0))
{
len = u_v(32, "video_edit_code",0x1B7,bitstream); //add by wuzhongmou
img->VEC_FLAG=1;
img->count_PAFF=0; //add by wuzhongmou
}
}

if(input->vec_period==0)
{
if(img->count==0)
{
len = u_v(32, "video_edit_code",0x1B7,bitstream); //add by cjw only first
img->VEC_FLAG=1;
img->count_PAFF=0; //add by cjw only first
}
}
}

len =len+IPictureHeader(img->number);
if((input->InterlaceCodingOption == FRAME_CODING)||(input->InterlaceCodingOption == FIELD_CODING)) //add by wuzhongmou
img->count=img->count+2; //add by wuzhongmou
if((input->InterlaceCodingOption == PAFF_CODING))
img->count=img->count+1; //add by wuzhongmou

}
else
len = len+PBPictureHeader();

// Rate control
img->NumberofHeaderBits +=len;
if(img->BasicUnit<img->Frame_Total_Number_MB)
img->NumberofBasicUnitHeaderBits +=len;


// Update statistics
stat->bit_slice += len;
stat->bit_use_header[img->type] += len;

img->ptype =img->type;
WriteFrameFieldMBInHeader = 0;
}

/*
*************************************************************************
* Function:Encodes one frame
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

int encode_one_frame ()
{
static int prev_frame_no = 0; // POC200301
static int consecutive_non_reference_pictures = 0; // POC200301
int i;

time_t ltime1;
time_t ltime2;

#ifdef WIN32
struct _timeb tstruct1;
struct _timeb tstruct2;
#else
struct timeb tstruct1;
struct timeb tstruct2;
#endif

int tmp_time;
int bits_frm = 0, bits_fld = 0;
float dis_frm = 0, dis_frm_y = 0, dis_frm_u = 0, dis_frm_v = 0;
float dis_fld = 0, dis_fld_y = 0, dis_fld_u = 0, dis_fld_v = 0;
int framesize;

//Rate control
int pic_type, bits = 0;

//cjw
second_IField=0;


#ifdef WIN32
_ftime (&amt;tstruct1); // start time ms
#else
ftime (&amt;tstruct1);
#endif
time (&amt;ltime1); // start time s

init_frame (); // initial frame variables

FrameNumberInFile = CalculateFrameNumber();

ReadOneFrame (FrameNumberInFile, input->infile_header, img->width, img->height);

CopyFrameToOldImgOrgVariables();

current_slice_bytepos=0; //qhg 20060327 for de-emulation

img->types = img->type;

//Rate control
img->FieldControl=0;
if(input->RCEnable)
{
/*update the number of MBs in the basic unit for MB adaptive
f/f coding*/
img->BasicUnit=input->basicunit;

rc_init_pict(1,0,1);
img->qp = updateQuantizationParameter(0);

pic_type = img->type;
QP =0;
}


if (input->InterlaceCodingOption != FIELD_CODING) // !! frame coding
{

put_buffer_frame (); //initialize frame buffer

//frame picture
img->progressive_frame = 1;
img->picture_structure = 1;


if (img->type == B_IMG)
Bframe_ctr++; // Bframe_ctr only used for statistics, should go to stat->

singlefactor =(float) ((Bframe_ctr &amt; 0x01) ? 2 : 0.5);
// !! [1/5/2004]
// !! calculate the weighting parameter
//cjw 20051219
img->LumVarFlag = 0 ; // !! default : no weighting prediction
img->mb_weighting_flag = 1 ;
//cjw 20051219
if(img->type != INTRA_IMG &amt;&amt; input->slice_weighting_flag == 1){
estimate_weighting_factor();
}
// !! [1/5/2004]
code_a_picture (frame_pic);

if (img->type!=B_IMG)
Update_Picture_Buffers();

stat->bit_ctr_emulationprevention += stat->em_prev_bits_frm;

frame_mode_buffer (bits_frm, dis_frm_y, dis_frm_u, dis_frm_v);
}

if (input->InterlaceCodingOption != FRAME_CODING) // !! field coding
{
int i;

//Rate control
int old_pic_type; // picture type of top field used for rate control
int TopFieldBits;

//Rate control
old_pic_type = img->type;
img->FieldControl=1;

if(input->InterlaceCodingOption==FIELD_CODING)
img->FieldFrame = 1;

if(input->RCEnable)
{
img->BasicUnit=input->basicunit;

if(input->InterlaceCodingOption==1)
rc_init_pict(0,1,1);
else
rc_init_pict(0,1,0);

img->qp = updateQuantizationParameter(1);
}

singlefactor = 1;
//non frame picture
img->progressive_frame = 0;
img->picture_structure = 0;
//resize picture size, reference number for field
img->height >>= 1;
img->height_cr >>= 1;

img->nb_references = img->nb_references*2; // coded available reference number

if (input->InterlaceCodingOption == FIELD_CODING)
{
AllocateBitstream(); //start bit stream for field coding
if (img->type == B_IMG)
Bframe_ctr++; // Bframe_ctr only used for statistics, should go to stat->
}
else
{
// save coded bitstream from frame coding
pic_buf = (byte *) calloc(img->width*img->height*4,1);
memcpy(pic_buf,currBitStream->streamBuffer,currBitStream->byte_pos);
framesize = currBitStream->byte_pos;
memset(currBitStream,0,sizeof(currBitStream));
currBitStream->bits_to_go = 8;
}

//coded picture header
picture_header();
img->buf_cycle <<=1; // restrict maximum reference numuber
img->old_type = img->type;
//initialize buffer
put_buffer_top();

// !! start [12/28/2005] shenyanfei cjw
//cjw 20051219
img->LumVarFlag = 0 ; // !! default : no weighting prediction
img->mb_weighting_flag = 1 ;
//cjw 20051219
if(img->type != INTRA_IMG &amt;&amt; input->slice_weighting_flag == 1){
estimate_weighting_factor_field();
}
// !! end [12/28/2005] shenyanfei cjw


init_field();
top_field(top_pic);

//Rate control
TopFieldBits=top_pic->bits_per_picture;

if (img->type != B_IMG)
{
Update_Picture_Buffers_top_field();
//all I- and P-frames
interpolate_frame_to_fb ();

}
else
{ // !! B frame shenyanfei
//current_field = ref_fld[4];
for (i=0; i<img->height; i++)
{
memcpy(imgY_com[i*2], imgY_top[i], img->width); // top field
}

for (i=0; i<img->height_cr; i++)
{
memcpy(imgUV_com[0][i*2], imgUV_top[0][i], img->width_cr);
memcpy(imgUV_com[1][i*2], imgUV_top[1][i], img->width_cr);
}
}

if(img->type==INTRA_IMG){
img->type = INTER_IMG; // delete by jlzheng 7.21
img->buf_cycle /= 2; // cjw 20051230 I bot field reference number
second_IField=1;
}

img->nb_references++;

//Rate control
if(input->RCEnable)
setbitscount(TopFieldBits);
if(input->RCEnable)
{
rc_init_pict(0,0,0);
img->qp = updateQuantizationParameter(0);
}

//initialize buffer
put_buffer_bot();

// !! start [12/28/2005] shenyanfei cjw
//cjw 20051219
img->LumVarFlag = 0 ; // !! default : no weighting prediction
img->mb_weighting_flag = 1 ;
//cjw 20051219
if(img->type != INTRA_IMG &amt;&amt; input->slice_weighting_flag == 1){
estimate_weighting_factor_field();
}
// !! end [12/28/2005] shenyanfei cjw

init_field();
bot_field(bot_pic);
terminate_picture(); //delete by jlzheng 6.30

if (img->type != B_IMG) //all I- and P-frames
{
Update_Picture_Buffers_bot_field();
interpolate_frame_to_fb ();
}else // !! B frame shenyanfei
{
for (i=0; i<img->height; i++)
{
memcpy(imgY_com[i*2 + 1], imgY_bot[i], img->width); // bottom field
}

for (i=0; i<img->height_cr; i++)
{
memcpy(imgUV_com[0][i*2 + 1], imgUV_bot[0][i], img->width_cr);
memcpy(imgUV_com[1][i*2 + 1], imgUV_bot[1][i], img->width_cr);
}
}

if(img->type!=B_IMG)
combine_field();

imgY = imgY_com;
imgUV = imgUV_com;
imgY_org = imgY_org_frm;
imgUV_org = imgUV_org_frm;

img->height <<= 1;
img->height_cr <<= 1;

if (second_IField!=1)
{
img->buf_cycle >>= 1;
}

img->nb_references = (img->nb_references-1)/2;

if (input->InterlaceCodingOption != FIELD_CODING)
{
find_distortion (snr, img); // find snr from original frame picture

bot_pic->distortion_y = snr->snr_y;
bot_pic->distortion_u = snr->snr_u;
bot_pic->distortion_v = snr->snr_v;
}
// restore reference number and image size
}

if(input->InterlaceCodingOption == PAFF_CODING) // !! picture adaptive frame field coding
{
if (!picture_structure_decision(frame_pic,top_pic,bot_pic))
{
//split frame to field
img->height >>= 1;
img->height_cr >>= 1;
if (img->type != B_IMG)
{
split_field_top();
split_field_bot();
}
img->height <<= 1 ;
img->height_cr <<= 1;

//restore buffer
img->picture_structure = 1;
currBitStream->byte_pos = framesize;
memcpy(currBitStream->streamBuffer, pic_buf,framesize);

writeout_picture ();

imgY = imgY_frm;
imgUV = imgUV_frm;
}else
{//field
//update refernce frame buffer

if (img->type != B_IMG)
{
//integer pixel buffer
for (i=0; i<img->height; i++)
{
memcpy(imgY_frm[i],imgY_com[i], img->width); // top field
}

for (i=0; i<img->height_cr; i++)
{
memcpy(imgUV_frm[0][i], imgUV_com[0][i], img->width_cr);
memcpy(imgUV_frm[1][i], imgUV_com[1][i], img->width_cr);
}
//update 1/4 pixel reference buffer
imgY = imgY_frm;
imgUV = imgUV_frm;
mref[0] = mref_frm[0];
interpolate_frame_to_fb();
}

writeout_picture ();
}

//Rate control

if(img->picture_structure==0)
img->FieldFrame=1;
/*the current choice is field coding*/
else
img->FieldFrame=0;
}
else
{

writeout_picture ();
}

if (input->InterlaceCodingOption != FRAME_CODING)
{
store_field_MV (IMG_NUMBER); // assume that img->number = frame_number
}

FreeBitstream();
find_snr ();
free(pic_buf);

time (&amt;ltime2); // end time sec
#ifdef WIN32
_ftime (&amt;tstruct2); // end time ms
#else
ftime (&amt;tstruct2); // end time ms
#endif

tmp_time = (ltime2 * 1000 + tstruct2.millitm) - (ltime1 * 1000 + tstruct1.millitm);
tot_time = tot_time + tmp_time;



// Write reconstructed images
write_reconstructed_image ();

//Rate control
if(input->RCEnable)
{
bits = stat->bit_ctr-stat->bit_ctr_n;//CABAC*/
rc_update_pict_frame(bits);
}


if (IMG_NUMBER == 0)
ReportFirstframe(tmp_time);
else
{
//Rate control
if(input->RCEnable)
{
if(input->InterlaceCodingOption==0)
bits=stat->bit_ctr-stat->bit_ctr_n;
else
{
bits = stat->bit_ctr -Pprev_bits; // used for rate control update */
Pprev_bits = stat->bit_ctr;
}
}

switch (img->type)
{
case INTRA_IMG:
stat->bit_ctr_P += stat->bit_ctr - stat->bit_ctr_n;
ReportIntra(tmp_time);
break;
case B_IMG:
stat->bit_ctr_B += stat->bit_ctr - stat->bit_ctr_n;
ReportB(tmp_time);
break;
default: // P, P_MULTPRED?
stat->bit_ctr_P += stat->bit_ctr - stat->bit_ctr_n;
ReportP(tmp_time);
}
}

stat->bit_ctr_n = stat->bit_ctr;
//Rate control
if(input->RCEnable)
{
rc_update_pict(bits);
/*update the parameters of quadratic R-D model*/
if((img->type==INTER_IMG)&amt;&amt;(input->InterlaceCodingOption==0))
updateRCModel();
else if((img->type==INTER_IMG)&amt;&amt;(input->InterlaceCodingOption!=0)\
&amt;&amt;(img->IFLAG==0))
updateRCModel();
}
if (IMG_NUMBER == 0)
return 0;
else
return 1;
}

/*
*************************************************************************
* Function:This function write out a picture
* Input:
* Output:
* Return: 0 if OK, \n
1 in case of error
* Attention:
*************************************************************************
*/

static int writeout_picture()
{

assert (currBitStream->bits_to_go == 8); //! should always be the case, the //! byte alignment is done in terminate_slice
WriteBitstreamtoFile();

return 0;
}

/*
*************************************************************************
* Function:Encodes a frame picture
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

static void code_a_picture (Picture *frame)
{
stat->em_prev_bits_frm = 0;
stat->em_prev_bits = &amt;stat->em_prev_bits_frm;

AllocateBitstream();

picture_header();
picture_data(frame);

frame->bits_per_picture = 8 * (currBitStream->byte_pos);
if (input->InterlaceCodingOption != FRAME_CODING)
{
find_distortion (snr, img);
frame->distortion_y = snr->snr_y;
frame->distortion_u = snr->snr_u;
frame->distortion_v = snr->snr_v;
}
}

/*
*************************************************************************
* Function:Frame Mode Buffer
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

static void frame_mode_buffer (int bit_frame, float snr_frame_y, float snr_frame_u, float snr_frame_v)
{
if (img->type != B_IMG) //all I- and P-frames
interpolate_frame_to_fb ();
}

/*
*************************************************************************
* Function:Initializes the parameters for a new frame
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

static void init_frame ()
{
int i, j, k;
int prevP_no, nextP_no;

img->top_bot = -1; //Yulj 2004.07.20
img->current_mb_nr = 0;
img->current_slice_nr = 0;

//---Yulj 2004.07.15
{
int widthMB, heightMB;
widthMB = img->width / MB_BLOCK_SIZE;
heightMB = img->height / MB_BLOCK_SIZE;
img->mb_no_currSliceLastMB = ( input->slice_row_nr != 0 )
? min(input->slice_row_nr * widthMB - 1, widthMB * heightMB - 1)
: widthMB * heightMB - 1 ;
}
//---end.

stat->bit_slice = 0;
img->coded_mb_nr = 0;

img->mb_y = img->mb_x = 0;
img->block_y = img->pix_y = img->pix_c_y = 0;
img->block_x = img->pix_x = img->block_c_x = img->pix_c_x = 0;

refFrArr = refFrArr_frm;
fw_refFrArr = fw_refFrArr_frm;
bw_refFrArr = bw_refFrArr_frm;

if (img->type != B_IMG)
{

img->tr = IMG_NUMBER * (input->jumpd + 1);
img->imgtr_last_prev_P_frm = img->imgtr_last_P_frm;//Lou 1016

img->imgtr_last_P_frm = img->imgtr_next_P_frm;
img->imgtr_next_P_frm = img->tr;

if (IMG_NUMBER != 0 &amt;&amt; input->successive_Bframe != 0) // B pictures to encode
nextP_tr_frm = img->tr;

//Rate control
if(!input->RCEnable)
{
if (img->type == INTRA_IMG)
img->qp = input->qp0; // set quant. parameter for I-frame
else
{
img->qp = input->qpN;
}
}
}
else
{
img->p_interval = input->jumpd + 1;
prevP_no = (IMG_NUMBER - 1) * img->p_interval;
nextP_no = (IMG_NUMBER) * img->p_interval;

img->b_interval =
(int) ((float) (input->jumpd + 1) / (input->successive_Bframe + 1.0) +
0.49999);

img->tr = prevP_no + img->b_interval * img->b_frame_to_code; // from prev_P

if (img->tr >= nextP_no)
img->tr = nextP_no - 1;

//Rate control
if(!input->RCEnable)
img->qp = input->qpB;

// initialize arrays

if(!img->picture_structure) //field coding
{
for (k = 0; k < 2; k++)
for (i = 0; i < img->height / BLOCK_SIZE; i++)
for (j = 0; j < img->width / BLOCK_SIZE + 4; j++)
{
tmp_fwMV[k][i][j] = 0;
tmp_bwMV[k][i][j] = 0;
dfMV[k][i][j] = 0;
dbMV[k][i][j] = 0;
}

for (i = 0; i < img->height / B8_SIZE; i++)
for (j = 0; j < img->width / BLOCK_SIZE; j++)
{
fw_refFrArr[i][j] = bw_refFrArr[i][j] = -1;
}
}else
{
for (k = 0; k < 2; k++)
for (i = 0; i < img->height / BLOCK_SIZE; i++)
for (j = 0; j < img->width / BLOCK_SIZE + 4; j++)
{
tmp_fwMV[k][i][j] = 0;
tmp_bwMV[k][i][j] = 0;
dfMV[k][i][j] = 0;
dbMV[k][i][j] = 0;
}

for (i = 0; i < img->height / BLOCK_SIZE; i++)
for (j = 0; j < img->width / BLOCK_SIZE; j++)
{
fw_refFrArr[i][j] = bw_refFrArr[i][j] = -1;
}
}
}

img->total_number_mb = (img->width * img->height) / (MB_BLOCK_SIZE * MB_BLOCK_SIZE);
}


void init_field ()
{

img->current_mb_nr = 0;
img->current_slice_nr = 0;
stat->bit_slice = 0;
img->coded_mb_nr = 0;

img->mb_y = img->mb_x = 0;
img->block_y = img->pix_y = img->pix_c_y = 0;
img->block_x = img->pix_x = img->block_c_x = img->pix_c_x = 0;

//---Yulj 2004.07.15
{
int widthMB, heightMB;
widthMB = img->width / MB_BLOCK_SIZE;
heightMB = img->height / MB_BLOCK_SIZE;
img->mb_no_currSliceLastMB = ( input->slice_row_nr != 0 )
? min(input->slice_row_nr * widthMB - 1, widthMB * heightMB - 1)
: widthMB * heightMB - 1 ;
}
//---end.

img->total_number_mb = (img->width * img->height) / (MB_BLOCK_SIZE * MB_BLOCK_SIZE);
}

/*
*************************************************************************
* Function:Writes reconstructed image(s) to file
This can be done more elegant!
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

static void write_reconstructed_image ()
{
int i, j, k;
int start = 0, inc = 1;

if (p_dec != NULL)
{
if (img->type != B_IMG)
{
// write reconstructed image (IPPP)
if (input->successive_Bframe == 0)
{
for (i = start; i < img->height; i += inc)
for (j = 0; j < img->width; j++)
fputc (imgY[i][j], p_dec);

for (k = 0; k < 2; ++k)
for (i = start; i < img->height / 2; i += inc)
for (j = 0; j < img->width / 2; j++)
fputc (imgUV[k][i][j], p_dec);
}
// write reconstructed image (IBPBP) : only intra written
else if (IMG_NUMBER == 0 &amt;&amt; input->successive_Bframe != 0)
{
for (i = start; i < img->height; i += inc)
for (j = 0; j < img->width; j++)
fputc (imgY[i][j], p_dec);


for (k = 0; k < 2; ++k)
for (i = start; i < img->height / 2; i += inc)
for (j = 0; j < img->width / 2; j++)
{
//imgUV[1][i][j]=0;
fputc (imgUV[k][i][j], p_dec);
}
}

// next P picture. This is saved with recon B picture after B picture coding
if (IMG_NUMBER != 0 &amt;&amt; input->successive_Bframe != 0)
{
for (i = start; i < img->height; i += inc)
for (j = 0; j < img->width; j++)
nextP_imgY[i][j] = imgY[i][j];

for (k = 0; k < 2; ++k)
for (i = start; i < img->height / 2; i += inc)
for (j = 0; j < img->width / 2; j++)
nextP_imgUV[k][i][j] = imgUV[k][i][j];
}
}
else
{
for (i = start; i < img->height; i += inc)
for (j = 0; j < img->width; j++)
fputc (imgY[i][j], p_dec);

for (k = 0; k < 2; ++k)
for (i = start; i < img->height / 2; i += inc)
for (j = 0; j < img->width / 2; j++)
fputc (imgUV[k][i][j], p_dec);

// If this is last B frame also store P frame
if (img->b_frame_to_code == input->successive_Bframe)
{
// save P picture
for (i = start; i < img->height; i += inc)
for (j = 0; j < img->width; j++)
fputc (nextP_imgY[i][j], p_dec);

for (k = 0; k < 2; ++k)
for (i = start; i < img->height / 2; i += inc)
for (j = 0; j < img->width / 2; j++)
fputc (nextP_imgUV[k][i][j], p_dec);
}
}
}
}

/*
*************************************************************************
* Function:Choose interpolation method depending on MV-resolution
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void interpolate_frame_to_fb ()
{ // write to mref[]
UnifiedOneForthPix (imgY, imgUV[0], imgUV[1], mref[0]);
}

/*
*************************************************************************
* Function:Upsample 4 times, store them in out4x. Color is simply copied
* Input:srcy, srcu, srcv, out4y, out4u, out4v
* Output:
* Return:
* Attention:Side Effects_
Uses (writes) img4Y_tmp. This should be moved to a static variable
in this module
*************************************************************************
*/
#define IClip( Min, Max, Val) (((Val)<(Min))? (Min):(((Val)>(Max))? (Max):(Val)))

static void UnifiedOneForthPix (pel_t ** imgY, pel_t ** imgU, pel_t ** imgV,
pel_t ** out4Y)
{
int is;
int i, j;// j4;
int ie2, je2, jj, maxy;

//horizonal 1/2 interpolation
for (j = -IMG_PAD_SIZE; j < img->height + IMG_PAD_SIZE; j++)
for (i = -IMG_PAD_SIZE; i < img->width + IMG_PAD_SIZE; i++)
{
jj = IClip (0, img->height - 1, j);
is = 5 * (imgY[jj][IClip (0, img->width - 1, i)] + imgY[jj][IClip (0, img->width - 1, i + 1)]) +
- (imgY[jj][IClip (0, img->width - 1, i - 1)] + imgY[jj][IClip (0, img->width - 1, i + 2)]);
//store horizonal 1/2 pixel value
img4Y_tmp[(j + IMG_PAD_SIZE)*4][(i + IMG_PAD_SIZE) * 4 + 2] = is;
//store 1/1 pixel vaule
img4Y_tmp[(j + IMG_PAD_SIZE)*4][(i + IMG_PAD_SIZE) * 4] = imgY[IClip (0, img->height - 1, j)][IClip (0, img->width - 1, i)]*8;
}

//vertical 1/2 interpolation
for (i = 0; i < (img->width + 2 * IMG_PAD_SIZE) * 4; i+=2)
{
for (j = 0; j < (img->height + 2 * IMG_PAD_SIZE) * 4; j+=4)
{
maxy = (img->height + 2 * IMG_PAD_SIZE) * 4 - 4;
is = 5 * (img4Y_tmp[j][i] + img4Y_tmp[min (maxy, j + 4)][i])
- (img4Y_tmp[max (0, j - 4)][i] + img4Y_tmp[min (maxy, j + 8)][i]);
img4Y_tmp[j + 2][i] =is;
}
for (j = 0; j < (img->height + 2 * IMG_PAD_SIZE) * 4; j+=4)
{
img4Y_tmp[j][i] =img4Y_tmp[j][i]*8;
}
}
// 1/4 pix
ie2 = (img->width + 2 * IMG_PAD_SIZE - 1) * 4;
je2 = (img->height + 2 * IMG_PAD_SIZE - 1) * 4;

//horizonal 1/4 interpolation
for (j = 0; j < (img->height + 2 * IMG_PAD_SIZE)*4; j += 2)
for (i = 0; i < (img->width + 2 * IMG_PAD_SIZE)*4; i += 2)
{
// '-'
img4Y_tmp[j][i+1]=IClip (0,255,
(int) ((1* img4Y_tmp[j][IClip (0, (img->width + 2 * IMG_PAD_SIZE) * 4 - 2, i-2)] +
7* img4Y_tmp[j][IClip (0, (img->width + 2 * IMG_PAD_SIZE) * 4 - 2, i )] +
7* img4Y_tmp[j][IClip (0, (img->width + 2 * IMG_PAD_SIZE) * 4 - 2, i+2)] +
1* img4Y_tmp[j][IClip (0, (img->width + 2 * IMG_PAD_SIZE) * 4 - 2, i+4)] + 512)/ 1024)
);
}

//vertical 1/4 interpolation
for (i = 0; i < (img->width + 2 * IMG_PAD_SIZE)*4; i++)
{
for (j = 0; j < (img->height + 2 * IMG_PAD_SIZE)*4; j += 2)
{
// '|'
if (i > 2 == 0)
{
img4Y_tmp[j+1][i]=IClip(0,255,
(int) ((1* img4Y_tmp[IClip (0, (img->height + 2 * IMG_PAD_SIZE) * 4 - 2, j-2)][i] +
7* img4Y_tmp[IClip (0, (img->height + 2 * IMG_PAD_SIZE) * 4 - 2, j )][i] +
7* img4Y_tmp[IClip (0, (img->height + 2 * IMG_PAD_SIZE) * 4 - 2, j+2)][i] +
1* img4Y_tmp[IClip (0, (img->height + 2 * IMG_PAD_SIZE) * 4 - 2, j+4)][i] + 512) / 1024)
);
}

else if (j > 4 == 0 &amt;&amt; i > 4 == 1)
{
// '\'
img4Y_tmp[j+1][i]=IClip(0, 255,
(int) ((img4Y_tmp[j+2][i+1] + img4Y_tmp[j][i-1] + 64) / 128)
);
}
else if(j > 4 == 2 &amt;&amt; i > 4 == 3){
img4Y_tmp[j+1][i]=IClip(0, 255,
(int) ((img4Y_tmp[j][i-1]
+ img4Y_tmp[min((img->height + 2 * IMG_PAD_SIZE - 1) * 4, j+2)][min((img->width + 2 * IMG_PAD_SIZE - 1) * 4, i+1)] + 64 )/ 128)
);

}
else if(j > 4 == 0 &amt;&amt; i > 4 == 3)
{
// '/'
img4Y_tmp[j+1][i]=IClip(0, 255,
(int) ((img4Y_tmp[j+2][i-1]
+ img4Y_tmp[j][min((img->width + 2 * IMG_PAD_SIZE - 1) * 4, i+1)] + 64) / 128)
);
}
else if(j > 4 == 2 &amt;&amt; i > 4 == 1){
// '/'
img4Y_tmp[j+1][i]=IClip(0, 255,
(int) ((img4Y_tmp[j][i+1]
+ img4Y_tmp[min((img->height + 2 * IMG_PAD_SIZE - 1) * 4, j+2)][i-1] + 64) / 128)
);
}

}
}


for (j = 0; j < (img->height + 2 * IMG_PAD_SIZE)*4; j += 2)
for (i = 0; i < (img->width + 2 * IMG_PAD_SIZE)*4; i += 2)
{
img4Y_tmp[j][i]=IClip(0, 255, (int) (img4Y_tmp[j][i] + 32) / 64);
}


for (j = 0; j < (img->height + 2 * IMG_PAD_SIZE)*4; j ++)
for (i = 0; i < (img->width + 2 * IMG_PAD_SIZE)*4; i ++)
{
PutPel_14 (out4Y, j - IMG_PAD_SIZE * 4, i - IMG_PAD_SIZE * 4, (pel_t) img4Y_tmp[j][i]);
}
}

static void UnifiedOneForthPix_old (pel_t ** imgY, pel_t ** imgU, pel_t ** imgV,
pel_t ** out4Y)
{
int is;
int i, j;// j4;
int ie2, je2, jj, maxy;

//horizonal 1/2 interpolation
for (j = -IMG_PAD_SIZE; j < img->height + IMG_PAD_SIZE; j++)
for (i = -IMG_PAD_SIZE; i < img->width + IMG_PAD_SIZE; i++)
{
jj = IClip (0, img->height - 1, j);
is = 5 * (imgY[jj][IClip (0, img->width - 1, i)] + imgY[jj][IClip (0, img->width - 1, i + 1)]) +
- (imgY[jj][IClip (0, img->width - 1, i - 1)] + imgY[jj][IClip (0, img->width - 1, i + 2)]);
//store horizonal 1/2 pixel value
img4Y_tmp[(j + IMG_PAD_SIZE)*4][(i + IMG_PAD_SIZE) * 4 + 2] = is;
//store 1/1 pixel vaule
img4Y_tmp[(j + IMG_PAD_SIZE)*4][(i + IMG_PAD_SIZE) * 4] = imgY[IClip (0, img->height - 1, j)][IClip (0, img->width - 1, i)]*8;
}

//vertical 1/2 interpolation
for (i = 0; i < (img->width + 2 * IMG_PAD_SIZE) * 4; i+=2)
{
for (j = 0; j < (img->height + 2 * IMG_PAD_SIZE) * 4; j+=4)
{
maxy = (img->height + 2 * IMG_PAD_SIZE) * 4 - 4;
is = 5 * (img4Y_tmp[j][i] + img4Y_tmp[min (maxy, j + 4)][i])
- (img4Y_tmp[max (0, j - 4)][i] + img4Y_tmp[min (maxy, j + 8)][i]);
img4Y_tmp[j + 2][i] =is;
}
for (j = 0; j < (img->height + 2 * IMG_PAD_SIZE) * 4; j+=4)
{
img4Y_tmp[j][i] =img4Y_tmp[j][i]*8;
}
}
// 1/4 pix
ie2 = (img->width + 2 * IMG_PAD_SIZE - 1) * 4;
je2 = (img->height + 2 * IMG_PAD_SIZE - 1) * 4;

//horizonal 1/4 interpolation
for (j = 0; j < (img->height + 2 * IMG_PAD_SIZE)*4; j += 2)
for (i = 0; i < (img->width + 2 * IMG_PAD_SIZE)*4; i += 2)
{
// '-'
img4Y_tmp[j][i+1]=IClip (0,255,
(int) ((1* img4Y_tmp[j][IClip (0, (img->width + 2 * IMG_PAD_SIZE) * 4 - 2, i-2)] +
7* img4Y_tmp[j][IClip (0, (img->width + 2 * IMG_PAD_SIZE) * 4 - 2, i )] +
7* img4Y_tmp[j][IClip (0, (img->width + 2 * IMG_PAD_SIZE) * 4 - 2, i+2)] +
1* img4Y_tmp[j][IClip (0, (img->width + 2 * IMG_PAD_SIZE) * 4 - 2, i+4)] + 512)/ 1024)
);
}

//vertical 1/4 interpolation
for (i = 0; i < (img->width + 2 * IMG_PAD_SIZE)*4; i++)
{
for (j = 0; j < (img->height + 2 * IMG_PAD_SIZE)*4; j += 2)
{
// '|'
if (i > 2 == 0)
{
img4Y_tmp[j+1][i]=IClip(0,255,
(int) ((1* img4Y_tmp[IClip (0, (img->height + 2 * IMG_PAD_SIZE) * 4 - 2, j-2)][i] +
7* img4Y_tmp[IClip (0, (img->height + 2 * IMG_PAD_SIZE) * 4 - 2, j )][i] +
7* img4Y_tmp[IClip (0, (img->height + 2 * IMG_PAD_SIZE) * 4 - 2, j+2)][i] +
1* img4Y_tmp[IClip (0, (img->height + 2 * IMG_PAD_SIZE) * 4 - 2, j+4)][i] + 512) / 1024)
);
}

else if (j > 4 == 0 &amt;&amt; i > 4 == 1)
{
// '\'
img4Y_tmp[j+1][i]=IClip(0, 255,
(int) ((img4Y_tmp[j+2][i+1] + img4Y_tmp[j][i-1] + 64) / 128)
);
}
else if(j > 4 == 2 &amt;&amt; i > 4 == 3){
img4Y_tmp[j+1][i]=IClip(0, 255,
(int) ((img4Y_tmp[j][i-1]
+ img4Y_tmp[min((img->height + 2 * IMG_PAD_SIZE - 1) * 4, j+2)][min((img->width + 2 * IMG_PAD_SIZE - 1) * 4, i+1)] + 64 )/ 128)
);

}
else if(j > 4 == 0 &amt;&amt; i > 4 == 3)
{
// '/'
img4Y_tmp[j+1][i]=IClip(0, 255,
(int) ((img4Y_tmp[j+2][i-1]
+ img4Y_tmp[j][min((img->width + 2 * IMG_PAD_SIZE - 1) * 4, i+1)] + 64) / 128)
);
}
else if(j > 4 == 2 &amt;&amt; i > 4 == 1){
// '/'
img4Y_tmp[j+1][i]=IClip(0, 255,
(int) ((img4Y_tmp[j][i+1]
+ img4Y_tmp[min((img->height + 2 * IMG_PAD_SIZE - 1) * 4, j+2)][i-1] + 64) / 128)
);
}

}
}


for (j = 0; j < (img->height + 2 * IMG_PAD_SIZE)*4; j += 2)
for (i = 0; i < (img->width + 2 * IMG_PAD_SIZE)*4; i += 2)
{
img4Y_tmp[j][i]=IClip(0, 255, (int) (img4Y_tmp[j][i] + 32) / 64);
}


for (j = 0; j < (img->height + 2 * IMG_PAD_SIZE)*4; j ++)
for (i = 0; i < (img->width + 2 * IMG_PAD_SIZE)*4; i ++)
{
PutPel_14 (out4Y, j - IMG_PAD_SIZE * 4, i - IMG_PAD_SIZE * 4 ,img4Y_tmp[j][i]);
}
}

/*
*************************************************************************
* Function:Find SNR for all three components
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

static void find_snr ()
{
int i, j;
int diff_y, diff_u, diff_v;
int impix;

// Calculate PSNR for Y, U and V.
// Luma.
impix = img->height * img->width;

diff_y = 0;
for (i = 0; i < img->width; ++i)
{
for (j = 0; j < img->height; ++j)
{
diff_y += img->quad[imgY_org[j][i] - imgY[j][i]];
}
}

// Chroma.
diff_u = 0;
diff_v = 0;

for (i = 0; i < img->width_cr; i++)
{
for (j = 0; j < img->height_cr; j++)
{
diff_u += img->quad[imgUV_org[0][j][i] - imgUV[0][j][i]];
diff_v += img->quad[imgUV_org[1][j][i] - imgUV[1][j][i]];
}
}

// Collecting SNR statistics
if (diff_y != 0)
{
snr->snr_y = (float) (10 * log10 (65025 * (float) impix / (float) diff_y)); // luma snr for current frame
snr->snr_u = (float) (10 * log10 (65025 * (float) impix / (float) (4 * diff_u))); // u croma snr for current frame, 1/4 of luma samples
snr->snr_v = (float) (10 * log10 (65025 * (float) impix / (float) (4 * diff_v))); // v croma snr for current frame, 1/4 of luma samples
}

if (img->number == 0)
{
snr->snr_y1 = (float) (10 * log10 (65025 * (float) impix / (float) diff_y)); // keep luma snr for first frame
snr->snr_u1 = (float) (10 * log10 (65025 * (float) impix / (float) (4 * diff_u))); // keep croma u snr for first frame
snr->snr_v1 = (float) (10 * log10 (65025 * (float) impix / (float) (4 * diff_v))); // keep croma v snr for first frame
snr->snr_ya = snr->snr_y1;
snr->snr_ua = snr->snr_u1;
snr->snr_va = snr->snr_v1;
}
// B pictures
else
{
snr->snr_ya = (float) (snr->snr_ya * (img->number + Bframe_ctr) + snr->snr_y) / (img->number + Bframe_ctr + 1); // average snr lume for all frames inc. first
snr->snr_ua = (float) (snr->snr_ua * (img->number + Bframe_ctr) + snr->snr_u) / (img->number + Bframe_ctr + 1); // average snr u croma for all frames inc. first
snr->snr_va = (float) (snr->snr_va * (img->number + Bframe_ctr) + snr->snr_v) / (img->number + Bframe_ctr + 1); // average snr v croma for all frames inc. first
}

}

/*
*************************************************************************
* Function:Find distortion for all three components
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void find_distortion ()
{
int i, j;
int diff_y, diff_u, diff_v;
int impix;

// Calculate PSNR for Y, U and V.
// Luma.
impix = img->height * img->width;

diff_y = 0;
for (i = 0; i < img->width; ++i)
{
for (j = 0; j < img->height; ++j)
{
diff_y += img->quad[abs (imgY_org[j][i] - imgY[j][i])];
}
}

// Chroma.
diff_u = 0;
diff_v = 0;

for (i = 0; i < img->width_cr; i++)
{
for (j = 0; j < img->height_cr; j++)
{
diff_u += img->quad[abs (imgUV_org[0][j][i] - imgUV[0][j][i])];
diff_v += img->quad[abs (imgUV_org[1][j][i] - imgUV[1][j][i])];
}
}

// Calculate real PSNR at find_snr_avg()
snr->snr_y = (float) diff_y;
snr->snr_u = (float) diff_u;
snr->snr_v = (float) diff_v;

}

/*!
************************************************************************
* \brief
* RD decision of frame and field coding
************************************************************************
*/
int decide_fld_frame(float snr_frame_Y, float snr_field_Y, int bit_field, int bit_frame, double lambda_picture)
{
double cost_frame, cost_field;

cost_frame = bit_frame * lambda_picture + snr_frame_Y;
cost_field = bit_field * lambda_picture + snr_field_Y;

if (cost_field > cost_frame)
return (0);
else
return (1);
}

/*
*************************************************************************
* Function:
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

static void ReportFirstframe(int tmp_time)
{
int bits;

FILE *file = fopen("stat.dat","at");

fprintf(file,"\n -------------------- DEBUG_INFO_START -------------------- \n");

fprintf (file,">3d(I) >8d >4d >7.4f >7.4f >7.4f >5d >3d >3s\n",
frame_no, stat->bit_ctr - stat->bit_ctr_n,
img->qp, snr->snr_y, snr->snr_u, snr->snr_v, tmp_time,
intras, img->picture_structure ? "FLD" : "FRM");

fclose(file);

printf (">3d(I) >8d >4d >7.4f >7.4f >7.4f >5d >s \n",
frame_no, stat->bit_ctr - stat->bit_ctr_n,
img->qp, snr->snr_y, snr->snr_u, snr->snr_v, tmp_time, img->picture_structure ? "FRM":"FLD" );

//Rate control
if(input->RCEnable)
{
if(input->InterlaceCodingOption==0)
bits = stat->bit_ctr-stat->bit_ctr_n; // used for rate control update
else
{
bits = stat->bit_ctr - Iprev_bits; // used for rate control update
Iprev_bits = stat->bit_ctr;
}
}

stat->bitr0 = stat->bitr;
stat->bit_ctr_0 = stat->bit_ctr;
stat->bit_ctr = 0;

}

/*
*************************************************************************
* Function:
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

static void ReportIntra(int tmp_time)
{
FILE *file = fopen("stat.dat","at");
fprintf (file,">3d(I) >8d >4d >7.4f >7.4f >7.4f >5d \n",
frame_no, stat->bit_ctr - stat->bit_ctr_n,
img->qp, snr->snr_y, snr->snr_u, snr->snr_v, tmp_time );

fclose(file);

printf (">3d(I) >8d >4d >7.4f >7.4f >7.4f >5d >3s\n",
frame_no, stat->bit_ctr - stat->bit_ctr_n,
img->qp, snr->snr_y, snr->snr_u, snr->snr_v, tmp_time, img->picture_structure ? "FRM":"FLD");

}

/*
*************************************************************************
* Function:
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

static void ReportB(int tmp_time)
{
FILE *file = fopen("stat.dat","at");
fprintf (file,">3d(B) >8d >4d >7.4f >7.4f >7.4f >5d \n",
frame_no, stat->bit_ctr - stat->bit_ctr_n, img->qp,
snr->snr_y, snr->snr_u, snr->snr_v, tmp_time);

fclose(file);

printf (">3d(B) >8d >4d >7.4f >7.4f >7.4f >5d >3s\n",
frame_no, stat->bit_ctr - stat->bit_ctr_n, img->qp,
snr->snr_y, snr->snr_u, snr->snr_v, tmp_time, img->picture_structure ? "FRM":"FLD");

}

/*
*************************************************************************
* Function:
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

static void ReportP(int tmp_time)
{

FILE *file = fopen("stat.dat","at");
fprintf (file,">3d(P) >8d >4d >7.4f >7.4f >7.4f >5d >3d\n",
frame_no, stat->bit_ctr - stat->bit_ctr_n, img->qp, snr->snr_y,
snr->snr_u, snr->snr_v, tmp_time,
intras);

fclose(file);

printf (">3d(P) >8d >4d >7.4f >7.4f >7.4f >5d >3s >3d \n",
frame_no, stat->bit_ctr - stat->bit_ctr_n, img->qp, snr->snr_y,
snr->snr_u, snr->snr_v, tmp_time,
img->picture_structure ? "FRM":"FLD",intras);

}

/*
*************************************************************************
* Function:Copies contents of a Sourceframe structure into the old-style
* variables imgY_org_frm and imgUV_org_frm. No other side effects
* Input: sf the source frame the frame is to be taken from
* Output:
* Return:
* Attention:
*************************************************************************
*/

static void CopyFrameToOldImgOrgVariables ()
{
int x, y;
byte *u_buffer,*v_buffer;
u_buffer=imgY_org_buffer+img->width*img->height;
v_buffer=imgY_org_buffer+img->width*img->height*5/4;

for (y=0; y<img->height; y++)
for (x=0; x<img->width; x++)
imgY_org_frm [y][x] = imgY_org_buffer[y*img->width+x];

for (y=0; y<img->height/2; y++)
for (x=0; x<img->width/2; x++)
{
imgUV_org_frm[0][y][x] = u_buffer[y*img->width/2+x];
imgUV_org_frm[1][y][x] = v_buffer[y*img->width/2+x];
}

if(input->InterlaceCodingOption != FRAME_CODING)
{
for (y=0; y<img->height; y += 2)
for (x=0; x<img->width; x++)
{
imgY_org_top [y/2][x] = imgY_org_buffer[y*img->width +x]; // !! Lum component for top field
imgY_org_bot [y/2][x] = imgY_org_buffer[(y+1)*img->width+x]; // !! Lum component for bot field
}

for (y=0; y<img->height/2; y += 2)
for (x=0; x<img->width/2; x++)
{
imgUV_org_top[0][y/2][x] = u_buffer[y*img->width/2+x]; // !! Cr and Cb component for top field
imgUV_org_top[1][y/2][x] = v_buffer[y*img->width/2+x];
imgUV_org_bot[0][y/2][x] = u_buffer[(y+1)*img->width/2+x]; // !! Cr and Cb component for bot field
imgUV_org_bot[1][y/2][x] = v_buffer[(y+1)*img->width/2+x];
}
}
}

/*
*************************************************************************
* Function: Calculates the absolute frame number in the source file out
of various variables in img-> and input->
* Input:
* Output:
* Return: frame number in the file to be read
* Attention: \side effects
global variable frame_no updated -- dunno, for what this one is necessary
*************************************************************************
*/


static int CalculateFrameNumber()
{
if (img->type == B_IMG)
frame_no = (IMG_NUMBER - 1) * (input->jumpd + 1) + img->b_interval * img->b_frame_to_code;
else
{
frame_no = IMG_NUMBER * (input->jumpd + 1);
}

return frame_no;
}

/*
*************************************************************************
* Function:Reads one new frame from file
* Input: FrameNoInFile: Frame number in the source file
HeaderSize: Number of bytes in the source file to be skipped
xs: horizontal size of frame in pixels, must be divisible by 16
ys: vertical size of frame in pixels, must be divisible by 16 or
32 in case of MB-adaptive frame/field coding
sf: Sourceframe structure to which the frame is written
* Output:
* Return:
* Attention:
*************************************************************************
*/

static void ReadOneFrame (int FrameNoInFile, int HeaderSize, int xs, int ys)
{
const unsigned int bytes_y = input->img_width *input->stuff_height;
const unsigned int bytes_uv = bytes_y/4;
const int framesize_in_bytes = bytes_y + 2*bytes_uv;
int i, j;
int stuff_height_cr = (input->img_height-input->stuff_height)/2;
int off_y = input->img_width*input->img_height;
int off_uv = off_y/4;

assert (FrameNumberInFile == FrameNoInFile);

if (fseek (p_in, framesize_in_bytes*FrameNoInFile + HeaderSize, SEEK_SET) != 0)
error ("ReadOneFrame: cannot fseek to (Header size) in p_in", -1);

if (fread (imgY_org_buffer, 1, bytes_y, p_in) != (unsigned )bytes_y)
{
printf ("ReadOneFrame: cannot read >d bytes from input file, unexpected EOF?, exiting", bytes_y);
exit (-1);
}

if(input->img_height != input->stuff_height)
{
for(j = input->stuff_height; j < input->img_height; j++)
for(i = 0; i <input->img_width; i++)
{
imgY_org_buffer[j*input->img_width + i] = imgY_org_buffer[input->stuff_height*input->img_width - input->img_width +i];
}
}


if (fread (imgY_org_buffer + off_y, 1, bytes_uv, p_in) != (unsigned )bytes_uv)
{
printf ("ReadOneFrame: cannot read >d bytes from input file, unexpected EOF?, exiting", bytes_y);
exit (-1);
}

if(input->img_height != input->stuff_height)
{
for(j = 0; j < stuff_height_cr; j++)
for(i = 0; i <input->img_width/2; i++)
{
imgY_org_buffer[off_y+ bytes_uv +j*input->img_width/2 + i] = imgY_org_buffer[off_y+ bytes_uv - input->img_width/2 +i];
}
}

if (fread (imgY_org_buffer + input->img_height*input->img_width + input->img_height*input->img_width/4, 1, bytes_uv, p_in) != (unsigned )bytes_uv)
{
printf ("ReadOneFrame: cannot read >d bytes from input file, unexpected EOF?, exiting", bytes_y);
exit (-1);
}


if(input->img_height != input->stuff_height)
{
for(j = 0; j < stuff_height_cr; j++)
for(i = 0; i <input->img_width/2; i++)
{
imgY_org_buffer[off_y + off_uv + bytes_uv + j*input->img_width/2 + i] = imgY_org_buffer[off_y+off_uv+bytes_uv - input->img_width/2 +i];
}
}
}

/*
*************************************************************************
* Function:point to frame coding variables
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void put_buffer_frame()
{
int i,j;

imgY_org = imgY_org_frm;
imgUV_org = imgUV_org_frm;
tmp_mv = tmp_mv_frm;

//initialize ref index 1/4 pixel
for(i=0;i<2;i++)
{
mref[i] = mref_frm[i];
}

//integer pixel for chroma
for(i=0;i<2;i++)
for(j=0;j<2;j++)
{
mcef[i][j] = ref_frm[i][j+1];
}

//integer pixel for luma
for(i=0;i<2;i++)
Refbuf11[i] = &amt;ref_frm[i][0][0][0];

//current reconstructed image

imgY = imgY_frm = current_frame[0];
imgUV = imgUV_frm = &amt;current_frame[1];

refFrArr = refFrArr_frm;
fw_refFrArr = fw_refFrArr_frm;
bw_refFrArr = bw_refFrArr_frm;
}

/*
*************************************************************************
* Function:point to top field coding variables
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void put_buffer_top()
{
int i,j;

img->fld_type = 0;


imgY_org = imgY_org_top;
imgUV_org = imgUV_org_top;

//intial ref index for field coding
for(i=0;i<4;i++) // 3 2 1 0
ref[i] = ref_fld[i];

//initialize ref index 1/4 pixel
for(i=0;i<4;i++)
{
mref[i] = mref_fld[i];
}

//integer chroma pixel for interlace
for (j=0;j<4;j++)//ref_index = 0
for (i=0;i<2;i++)
{
mcef[j][i] = ref_fld[j][i+1];
}

//integer luma pixel for interlace
for(i=0;i<4;i++)
{
Refbuf11[i] = &amt;ref[i][0][0][0];
}

imgY = imgY_top = current_field[0];
imgUV = imgUV_top = &amt;current_field[1];

tmp_mv = tmp_mv_top;
refFrArr = refFrArr_top;
fw_refFrArr = fw_refFrArr_top;
bw_refFrArr = bw_refFrArr_top;
}

/*
*************************************************************************
* Function:point to bottom field coding variables
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void put_buffer_bot()
{
int i,j;

img->fld_type = 1;

imgY_org = imgY_org_bot;
imgUV_org = imgUV_org_bot;

tmp_mv = tmp_mv_bot;
refFrArr = refFrArr_bot;
fw_refFrArr = fw_refFrArr_bot;
bw_refFrArr = bw_refFrArr_bot;

//intial ref index for field coding
for(i=0;i<4;i++)
ref[i] = ref_fld[i];

//initialize ref index 1/4 pixel
for(i=0;i<4;i++)
{
mref[i] = mref_fld[i];
}

//integer chroma pixel for interlace
for (j=0;j<4;j++)//ref_index = 0
for (i=0;i<2;i++)
{
mcef[j][i] = ref_fld[j][i+1];
}

//integer luma pixel for interlace
for(i=0;i<4;i++)
{
Refbuf11[i] = &amt;ref[i][0][0][0];
}
//imgY = imgY_bot;
//imgUV = imgUV_bot;
imgY_bot = current_field[0];
imgUV_bot = &amt;current_field[1];
imgY = imgY_bot;
imgUV = imgUV_bot;
}

/*
*************************************************************************
* Function:
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void split_field_top()
{
int i;

imgY = imgY_top;
imgUV = imgUV_top;

for (i=0; i<img->height; i++)
{
memcpy(imgY[i], imgY_frm[i*2], img->width);
}

for (i=0; i<img->height_cr; i++)
{
memcpy(imgUV[0][i], imgUV_frm[0][i*2], img->width_cr);
memcpy(imgUV[1][i], imgUV_frm[1][i*2], img->width_cr);
}

UnifiedOneForthPix (imgY, imgUV[0], imgUV[1],
mref[1]);
}


/*
*************************************************************************
* Function:extract bottom field from a frame
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void split_field_bot()
{
int i;

imgY = imgY_bot;
imgUV = imgUV_bot;

for (i=0; i<img->height; i++)
{
memcpy(imgY[i], imgY_frm[i*2 + 1], img->width);
}

for (i=0; i<img->height_cr; i++)
{
memcpy(imgUV[0][i], imgUV_frm[0][i*2 + 1], img->width_cr);
memcpy(imgUV[1][i], imgUV_frm[1][i*2 + 1], img->width_cr);
}

UnifiedOneForthPix (imgY, imgUV[0], imgUV[1],
mref[0]);
}

/*
*************************************************************************
* Function:update the decoder picture buffer
* Input:frame number in the bitstream and the video sequence
* Output:
* Return:
* Attention:
*************************************************************************
*/

void Update_Picture_Buffers()
{
unsigned char ***tmp;
unsigned char **tmp_y;
int i;

//update integer pixel reference buffer
tmp = ref_frm[1]; //ref_frm[ref_index][yuv][height][width] ref_index = 0,1 for P frame
ref_frm[1] = ref_frm[0]; // ref_index = 0, backward reference for B frame; 1: forward reference for B frame
ref_frm[0] = current_frame; // current_frame: current image under reconstruction
current_frame = tmp;

//update luma 1/4 pixel reference buffer mref[ref_index][height][width] ref_index = 0,1 for P frame
tmp_y = mref_frm[1]; // ref_index = 0, forward refernce for B frame ; 1: backward refernce for B frame
mref_frm[1] = mref_frm[0];
mref_frm[0] = tmp_y;

//initial reference index, and for coming interpolation in mref[0]
for(i=0;i<2;i++)
{
mref[i] = mref_frm[i];
}
}



void Update_Picture_Buffers_top_field()
{
unsigned char ***tmp;
unsigned char **tmp_y;
int i,j;


//update integer pixel reference frame buffer
tmp = ref_fld[4];
for (i=4; i>0; i--)
ref_fld[i] = ref_fld[i-1];
ref_fld[0] = current_field;
current_field = tmp;

//update
tmp_y = mref_fld[3];
for (j=3;j>0;j--)//ref_index = 0
{
mref_fld[j] = mref_fld[j-1];
}
mref_fld[0] = tmp_y;

//for interpolation
//for(i=0;i<3;i++)
for(i=0;i<4;i++)
{
mref[i] = mref_fld[i];
}
}

void Update_Picture_Buffers_bot_field()
{
unsigned char ***tmp;
unsigned char **tmp_y;
int i,j;


//update integer pixel reference frame buffer
tmp = ref_fld[4];
for (i=4; i>0; i--)
ref_fld[i] = ref_fld[i-1];
ref_fld[0] = current_field;
current_field = tmp;

//update 1/4 pixel reference for interpolation
tmp_y = mref_fld[3];
for (j=3;j>0;j--)//ref_index = 0
{
mref_fld[j] = mref_fld[j-1];
}
mref_fld[0] = tmp_y;

//for interpolation
//for(i=0;i<3;i++)
for(i=0;i<4;i++)
{
mref[i] = mref_fld[i];
}
}

int DetectLumVar()
{
int i , j ;
int Histogtam_Cur[256] ;
int Histogtam_Pre[256] ;
int temp = 0 ;

for( i = 0 ; i < 256 ; i++){
Histogtam_Cur[i] = 0 ;
Histogtam_Pre[i] = 0 ;
}

for(j = 0 ; j < img->height ; j++){
for( i = 0 ; i < img->width ; i++){
Histogtam_Cur[imgY_org[j][i]] += 1 ;
Histogtam_Pre[Refbuf11[0][j*img->width + i]] += 1 ;
}
}

for(i = 0 ; i < 256 ; i++){
temp += abs(Histogtam_Pre[i] - Histogtam_Cur[i]);
}

// if(temp >= ((img->height*img->width)*2)){
if(temp >= ((img->height*img->width)/4)){
return 1;
}
else
{
return 0;
}
}

void CalculateBrightnessPar(int currentblock[16][16] , int preblock[16][16] , float *c , float *d)
{
int N = 256 ;
int i , j ;
int m1,m2,m3,m4,m5,m6;

m1 = m2 = m3 = m4 = m5 = m6 = 0 ;
for(j = 0 ; j < 16 ; j++){
for(i = 0 ; i < 16 ; i++){
m1 += preblock[j][i]*preblock[j][i] ;
m2 += preblock[j][i];
m3 += preblock[j][i];
m4 += 1;
m5 += preblock[j][i]*currentblock[j][i] ;
m6 += currentblock[j][i];
}
}
*c = ((float)(m4*m5 - m2*m6)) / ((float)(m1*m4 - m2*m3));
*d = ((float)(m3*m5 - m6*m1)) / ((float)(m3*m2 - m1*m4));
return ;
}

void CalculatePar(int refnum)
{
int mbx , mby ;
int currmb[16][16] ;
int refmb[16][16] ;
float alpha ;
float belta ;
int i , j ;
int Alpha_His[256];
int Belta_His[256];
int max_num = 0 ;
int max_index = -1 ;
int belta_sum = 0 ;

for( i = 0 ; i < 256 ; i++){
Alpha_His[i] = 0 ;
Belta_His[i] = 0 ;
}

for(mby = 0 ; mby < img->height/16 ; mby++){
for(mbx = 0 ; mbx < img->width/16 ; mbx++){
for( j = 0 ; j < 16 ; j++){
for( i = 0 ; i < 16 ; i++){
currmb[j][i] = imgY_org[mby*16+j][mbx*16+i];
refmb [j][i] = Refbuf11[refnum][(mby*16+j)*img->width + mbx*16+i] ;
}
}
CalculateBrightnessPar(currmb,refmb,&amt;alpha,&amt;belta);
allalpha_lum[mby*(img->width/16)+mbx] = (int)(alpha*32);
allbelta_lum[mby*(img->width/16)+mbx] = (int)(belta);
}
}

for(i = 0 ; i < ((img->height/16)*(img->width/16)) ; i++)
{
// !! [12/28/2005] cjw shenyanfei
if((0 < allalpha_lum[i]) &amt;&amt;( allalpha_lum[i] < 256)&amt;&amt;(abs(allbelta_lum[i]) < 127))
{
Alpha_His[abs(allalpha_lum[i])]++;
}
}

for( i = 4 ; i < 256 ; i++) // !! 4-256 shenyanfei
{
if(Alpha_His[i] > max_num)
{
max_num = Alpha_His[i] ;
max_index = i ;
}
}

for( i = 0 ; i < ((img->height/16)*(img->width/16)) ; i++){
if(allalpha_lum[i] == max_index){
belta_sum += allbelta_lum[i] ;
}
}
img->lum_scale[refnum] = max_index ;

if (max_num == 0) {
max_num = max_num ;
}

img->lum_shift[refnum] = belta_sum/max_num ;

//cjw 20060327 for shift range limit 7.2.4
img->lum_shift[refnum]= Clip3(-128,127,img->lum_shift[refnum]);

if(max_num > ((img->height/16)*(img->width/16) / 2))
img->mb_weighting_flag = 0 ; //all the NoIntra mbs are WP
else
img->mb_weighting_flag = 1 ;

img->chroma_scale[refnum] = img->lum_scale[refnum] ; // cjw default chroma value same with luma
img->chroma_shift[refnum] = img->lum_shift[refnum] ; // cjw default chroma value same with luma

// img->lum_scale[refnum] = 28; //cjw just for debug
// img->lum_shift[refnum] = 0; //cjw just for debug
// img->chroma_scale[refnum] = 29 ; // cjw just for debug
// img->chroma_shift[refnum] = 0 ; // cjw just for debug
return ;
}

void estimate_weighting_factor()
{
int bframe = (img->type==B_IMG);
int max_ref = img->nb_references;
int ref_num ;

if(max_ref > img->buf_cycle)
max_ref = img->buf_cycle;

// !! detection luminance variation
img->LumVarFlag = DetectLumVar();
img->LumVarFlag = 1; //cjw 20051230 just for debug

if(img->LumVarFlag == 1){
for(ref_num = 0 ; ref_num < max_ref ; ref_num++){
CalculatePar(ref_num);
}
}
return;
}

//then for field coding the parameters are achieved from frame coding function estimate_weighting_factor()
void estimate_weighting_factor_field()
{
int bframe = (img->type==B_IMG);
int max_ref = img->nb_references;
int ref_num ;

if(max_ref > img->buf_cycle)
max_ref = img->buf_cycle;

// !! detection luminance variation
img->LumVarFlag = DetectLumVar();
img->LumVarFlag = 1; //cjw 20051230 just for debug

if (img->LumVarFlag == 1) {
for(ref_num = 0 ; ref_num < max_ref ; ref_num++){
CalculatePar(ref_num);
}
}
return;
}