www.pudn.com > lencod.rar > slice.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  
#include  
#include  
#include  
#include  
#include  
#include  
 
#include "global.h" 
#include "header.h" 
#include "bitstream.h" 
#include "vlc.h" 
#include "image.h" 
#include "rdopt_coding_state.h" 
#include "loopfilter.h" 
 
/* 
************************************************************************* 
* Function:This function terminates a slice 
* Input: 
* Output: 
* Return: 0 if OK,                                                         \n 
      1 in case of error 
* Attention:                                                  by jlzheng 
************************************************************************* 
*/ 
 
int start_slice() 
{ 
  Bitstream *currStream; 
     
  currStream = currBitStream; 
 
   if(((img->picture_structure && img->current_mb_nr!=0))||((!img->picture_structure)&&(img->current_mb_nr_fld!=0))) 
     Demulate(currStream,current_slice_bytepos);                  //qhg 20060327  for de-emulation 
 
  if (currStream->bits_to_go!=8) //   hzjia 2004-08-20  
  { 
	   
	  currStream->byte_buf <<= currStream->bits_to_go; 
	  currStream->byte_buf |= ( 1 << (currStream->bits_to_go - 1) ); 
	   
	  currStream->streamBuffer[currStream->byte_pos++] = currStream->byte_buf; 
	  currStream->bits_to_go = 8; 
	  currStream->byte_buf = 0; 
  }  
   else		// cjw 20060321  
  { 
	  currStream->streamBuffer[currStream->byte_pos++] = 0x80; 
	  currStream->bits_to_go = 8; 
	  currStream->byte_buf = 0;  
  } 
   
   //qhg 20060327 for de-emulation  
  current_slice_bytepos=currStream->byte_pos;   
 
  return 0;    
} 
 
/* 
************************************************************************* 
* Function:This function terminates a picture 
* Input: 
* Output: 
* Return: 0 if OK,                                                         \n 
      1 in case of error 
* Attention: 
************************************************************************* 
*/ 
 
int terminate_picture() 
{ 
  Bitstream *currStream; 
     
  currStream = currBitStream; 
  
////////////////////////////////////////////////////////////////////////// 
    Demulate(currStream,current_slice_bytepos);                    //qhg 20060327  
//  currStream->byte_buf <<= currStream->bits_to_go; 
//  currStream->byte_buf |= (1 << (currStream->bits_to_go - 1) );    // Yulj 2004.07.16 
//   
//  currStream->streamBuffer[currStream->byte_pos++] = currStream->byte_buf; 
//  currStream->bits_to_go = 8; 
//  currStream->byte_buf = 0; 
////////////////////////////////////////////////////////////////////////// 
 
 
  //---deleted by Yulj 2004.07.16 
	// '10..' should be filled even if currStream is bytealign.  
  //if (currStream->bits_to_go==8)   
  //  return 0; 
    
  currStream->byte_buf <<= currStream->bits_to_go; 
  currStream->byte_buf |= (1 << (currStream->bits_to_go - 1) );    // Yulj 2004.07.16 
   
  currStream->streamBuffer[currStream->byte_pos++] = currStream->byte_buf; 
  currStream->bits_to_go = 8; 
  currStream->byte_buf = 0; 
   
  return 0;    
} 
 
/* 
************************************************************************* 
* Function:Encodes one slice 
* Input: 
* Output: 
* Return: the number of coded MBs in the SLice  
* Attention:                                     
************************************************************************* 
*/ 
void picture_data(Picture *pic) 
{ 
  Boolean end_of_picture = FALSE; 
  int CurrentMbNumber=0; 
  int MBRowSize = img->width / MB_BLOCK_SIZE;         // jlzheng 7.1 
	int slice_nr = 0; 
	int slice_qp = img->qp; 
	int len; 
	 
         
     
	while (end_of_picture == FALSE) // loop over macroblocks 
	{ 
		set_MB_parameters (CurrentMbNumber); 
		 
		if (input->slice_row_nr && (img->current_mb_nr ==0   
			||(img->current_mb_nr>0 && img->mb_data[img->current_mb_nr].slice_nr != img->mb_data[img->current_mb_nr-1].slice_nr))) 
		{ 
			   // slice header start     jlzheng 7.1 
			   start_slice ();  
			   img->current_slice_qp = img->qp; 
			   img->current_slice_start_mb = img->current_mb_nr; 
               len = SliceHeader(slice_nr, slice_qp);   
			   stat->bit_slice += len;   
			   slice_nr++;  
			   // slcie header end 
		} 
		    
		   start_macroblock (); 
		   encode_one_macroblock (); 
		   write_one_macroblock (1); 
		   terminate_macroblock (&end_of_picture); 
		   proceed2nextMacroblock (); 
		   CurrentMbNumber++; 
		    
	} 
	 
	terminate_picture (); 
	 
	DeblockFrame (img, imgY, imgUV); 
 
} 
 
 
void top_field(Picture *pic) 
{ 
	Boolean end_of_picture = FALSE; 
	int CurrentMbNumber=0; 
	int MBRowSize = img->width / MB_BLOCK_SIZE; 
	int slice_nr =0; 
	int slice_qp = img->qp; 
	int len; 
 
	img->top_bot = 0;  // Yulj 2004.07.20 
	while (end_of_picture == FALSE) // loop over macroblocks 
	{ 
		set_MB_parameters (CurrentMbNumber); 
		 
		img->current_mb_nr_fld = img->current_mb_nr; //qhg 20060327 for de-emulation 
							     //img->current_mb_nr_fld is used in start_slice() 
		if (input->slice_row_nr && (img->current_mb_nr ==0   
			||(img->current_mb_nr>0 && img->mb_data[img->current_mb_nr].slice_nr != img->mb_data[img->current_mb_nr-1].slice_nr))) 
		{ 
			// slice header start jlzheng 7.1 
			start_slice ();   
			img->current_slice_qp = img->qp; 
			img->current_slice_start_mb = img->current_mb_nr; 
			len = SliceHeader(slice_nr, slice_qp); 
			stat->bit_slice += len; 
			slice_nr++; 
			// slice header end 
		} 
		 
		//img->current_mb_nr_fld = img->current_mb_nr;  //delete by qhg 20060327 for de-emulation 
		start_macroblock (); 
		encode_one_macroblock (); 
		write_one_macroblock (1); 
		terminate_macroblock (&end_of_picture); 
		proceed2nextMacroblock (); 
		CurrentMbNumber++; 
	} 
	 
	DeblockFrame (img, imgY, imgUV); 
 
	//rate control 
	pic->bits_per_picture = 8 * (currBitStream->byte_pos); 
} 
 
void bot_field(Picture *pic) 
{ 
	Boolean end_of_picture = FALSE; 
	int CurrentMbNumber=0; 
	int MBRowSize = img->width / MB_BLOCK_SIZE; 
	int slice_nr =0; 
	int slice_qp = img->qp; 
	int len; 
	 
	img->top_bot = 1; //Yulj 2004.07.20 
	while (end_of_picture == FALSE) // loop over macroblocks 
	{ 
		set_MB_parameters (CurrentMbNumber); 
		if (input->slice_row_nr && (img->current_mb_nr ==0   
			||(img->current_mb_nr>0 && img->mb_data[img->current_mb_nr].slice_nr != img->mb_data[img->current_mb_nr-1].slice_nr))) 
		{ 
			// slice header start  jlzheng 7.11 
			start_slice ();   
			img->current_slice_qp = img->qp; 
			img->current_slice_start_mb = img->current_mb_nr; 
			len = SliceHeader(slice_nr, slice_qp); 
			stat->bit_slice += len; 
			slice_nr++; 
			// slice header end 
		} 
		 
		img->current_mb_nr_fld = img->current_mb_nr+img->total_number_mb; 
		start_macroblock (); 
		encode_one_macroblock (); 
		write_one_macroblock (1); 
		terminate_macroblock (&end_of_picture); 
		proceed2nextMacroblock (); 
		CurrentMbNumber++; 
	} 
	 
	terminate_picture (); 
	DeblockFrame (img, imgY, imgUV); 
 
	pic->bits_per_picture = 8 * (currBitStream->byte_pos); 
} 
 
void combine_field() 
{ 
  int i; 
	 
  for (i=0; iheight; i++) 
  { 
    memcpy(imgY_com[i*2], imgY_top[i], img->width);     // top field 
    memcpy(imgY_com[i*2 + 1], imgY_bot[i], img->width); // bottom field 
  } 
	 
  for (i=0; iheight_cr; i++) 
  { 
    memcpy(imgUV_com[0][i*2], imgUV_top[0][i], img->width_cr); 
    memcpy(imgUV_com[0][i*2 + 1], imgUV_bot[0][i], img->width_cr); 
    memcpy(imgUV_com[1][i*2], imgUV_top[1][i], img->width_cr); 
    memcpy(imgUV_com[1][i*2 + 1], imgUV_bot[1][i], img->width_cr); 
  } 
} 
 
 
void store_field_MV () 
{ 
    int i, j; 
 
    if (img->type != B_IMG)     //all I- and P-frames 
     { 
        if (!img->picture_structure) 
	 { 
            for (i = 0; i < img->width / 8 + 4; i++) 
	    { 
                for (j = 0; j < img->height / 16; j++) 
	  	{ 
                    tmp_mv_frm[0][2 * j][i] = tmp_mv_frm[0][2 * j + 1][i] = tmp_mv_top[0][j][i]; 
                    tmp_mv_frm[0][2 * j][i] = tmp_mv_frm[0][2 * j + 1][i] = tmp_mv_top[0][j][i];        // ?? 
                    tmp_mv_frm[1][2 * j][i] = tmp_mv_frm[1][2 * j + 1][i] = tmp_mv_top[1][j][i] * 2; 
                    tmp_mv_frm[1][2 * j][i] = tmp_mv_frm[1][2 * j + 1][i] = tmp_mv_top[1][j][i] * 2;    // ?? 
					 
                    if (refFrArr_top[j][i] == -1) 
			{ 
				refFrArr_frm[2 * j][i] = 
				refFrArr_frm[2 * j + 1][i] = -1; 
			} 
                    else 
			{ 
				refFrArr_frm[2 * j][i] = 
				refFrArr_frm[2 * j + 1][i] = 
				(int) (refFrArr_top[j][i] / 2); 
			} 
	        } 
	    } 
	} 
        else 
  	{ 
            for (i = 0; i < img->width / 8 + 4; i++) 
	    { 
                for (j = 0; j < img->height / 16; j++) 
		{ 
                    tmp_mv_top[0][j][i] = tmp_mv_bot[0][j][i] =	(int) (tmp_mv_frm[0][2 * j][i]); 
                    tmp_mv_top[1][j][i] = tmp_mv_bot[1][j][i] =	(int) ((tmp_mv_frm[1][2 * j][i]) / 2); 
					 
		    if (refFrArr_frm[2 * j][i] == -1) 
		    { 
			refFrArr_top[j][i] = refFrArr_bot[j][i] = -1; 
		    } 
		    else 
		    { 
			// 	refFrArr_top[j][i] = refFrArr_bot[j][i] = 
		  	// 	refFrArr_frm[2 * j][i] * 2; 
			refFrArr_top[j][i] = refFrArr_frm[2*j][i]*2; 
                        refFrArr_bot[j][i] = refFrArr_frm[2*j][i]*2 + 1; 
	                //by oliver 0512 
		     } 
		} 
	    } 
         } 
    } 
} 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Picture Structure Decision 
 ************************************************************************ 
 */ 
int picture_structure_decision (Picture *frame, Picture *top, Picture *bot) 
{ 
  double lambda_picture; 
  int bframe = (img->type == B_IMG); 
  float snr_frame, snr_field; 
  int bit_frame, bit_field; 
 
  lambda_picture = 0.85 * pow (2, (img->qp - SHIFT_QP) / 4.0) * (bframe?4 : 1); 
 
  snr_frame = frame->distortion_y + frame->distortion_u + frame->distortion_v; 
  //! all distrortions of a field picture are accumulated in the top field 
  snr_field = bot->distortion_y + bot->distortion_u + bot->distortion_v; 
  bit_field = bot->bits_per_picture; 
  bit_frame = frame->bits_per_picture; 
 
  return decide_fld_frame (snr_frame, snr_field, bit_field, bit_frame, lambda_picture); 
} 
 
 
 
 
/* 
************************************************************************* 
* Function: allocates the memory for the coded picture data 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
void AllocateBitstream() 
{ 
  const int buffer_size = (img->width * input->img_height * 4);  
   
  if ((currBitStream = (Bitstream *) calloc(1, sizeof(Bitstream))) == NULL) 
    no_mem_exit ("malloc_slice: Bitstream"); 
  if ((currBitStream->streamBuffer = (byte *) calloc(buffer_size, sizeof(byte))) == NULL) 
    no_mem_exit ("malloc_slice: StreamBuffer"); 
 
  currBitStream->bits_to_go = 8; 
} 
/* 
************************************************************************* 
* Function:free the allocated memory for the coded picture data 
* Input: 
* Output: 
* Return:  
************************************************************************* 
*/ 
void FreeBitstream() 
{ 
  const int buffer_size = (img->width * img->height * 4);  
 
  if (currBitStream->streamBuffer) 
    free(currBitStream->streamBuffer); 
  if (currBitStream) 
    free(currBitStream); 
} 
 
////////////////////////////////////////////////////////////////////////// 
////////////********************* qhg add 20060327*****************/////// 
////////////////////////////////////////////////////////////////////////// 
void Demulate(Bitstream *currStream, int current_slice_bytepos) 
{ 
	int i, j; 
	unsigned int rawbitsequence=-1; 
	int bitvalue, nonzero, bitnum;  
	if(!(currBitStream->streamBuffer[current_slice_bytepos]==0 && currBitStream->streamBuffer[current_slice_bytepos+1]==0 && currBitStream->streamBuffer[current_slice_bytepos+2]==1)) 
		printf ("Fatal bitstream error"); 
	AllocatetmpBitstream(); 
 
	bitnum=8; 
	tmpStream->bits_to_go=0; 
	currStream->streamBuffer[currStream->byte_pos]=currStream->byte_buf<bits_to_go;	 
	 
	for(tmpStream->byte_pos=i=current_slice_bytepos+3 ; i<=currStream->byte_pos; i++) 
	{  
		for(j=8; j>(i==currStream->byte_pos? currStream->bits_to_go:0); j--) 
		{ 
			bitvalue=currBitStream->streamBuffer[i]&(0x01<<(j-1)); 
			if(bitnum==2) 
			{ 
				nonzero = rawbitsequence & 0x003fffff; 
				if(!nonzero) 
				{ 
					tmpStream->streamBuffer[tmpStream->byte_pos] = 0x02; 
					tmpStream->byte_pos++; 
					tmpStream->bits_to_go += 2; 
					rawbitsequence = 0x00000002; 
					bitnum = 8; 
				} 
			} 
			 
			rawbitsequence <<= 1; 
			if(bitvalue) 
			{ 
				tmpStream->streamBuffer[tmpStream->byte_pos] |= 1<<(bitnum-1); 
				rawbitsequence |= 1; 
			} 
			else 
			{ 
				tmpStream->streamBuffer[tmpStream->byte_pos] &= (~(1<<(bitnum-1))); 
			} 
			bitnum--; 
			tmpStream->bits_to_go++; 
			if(bitnum==0) 
			{ 
				bitnum = 8; 
				tmpStream->byte_pos++; 
			} 
		} 
		 
	} 
	for(i=current_slice_bytepos+3; i<=tmpStream->byte_pos; i++) 
	{ 
		currStream->streamBuffer[i]=tmpStream->streamBuffer[i]; 
	} 
 
	currStream->byte_pos=tmpStream->byte_pos;	 
	currStream->bits_to_go=8-tmpStream->bits_to_go%8; 
	currStream->byte_buf=tmpStream->streamBuffer[tmpStream->byte_pos]>>currStream->bits_to_go; 
	FreetmpBitstream(); 
} 
 
void AllocatetmpBitstream() 
{ 
	const int buffer_size = (img->width * input->img_height * 4);  
	 
	if ((tmpStream = (Bitstream *) calloc(1, sizeof(Bitstream))) == NULL) 
		no_mem_exit ("malloc_slice: Bitstream"); 
	if ((tmpStream->streamBuffer = (byte *) calloc(buffer_size, sizeof(byte))) == NULL) 
		no_mem_exit ("malloc_slice: StreamBuffer"); 
	 
	tmpStream->bits_to_go = 8; 
} 
 
void FreetmpBitstream() 
{ 
  const int buffer_size = (img->width * img->height * 4);  
 
  if (tmpStream->streamBuffer) 
    free(tmpStream->streamBuffer); 
  if (tmpStream) 
    free(tmpStream); 
} 
 
////////////////////////////////////////////////////////////////////////// 
////////////////*********************end  qhg *************************/// 
//////////////////////////////////////////////////////////////////////////