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 <string.h>
#include <math.h>
#include <time.h>
#include <sys/timeb.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

#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 &amt;&amt; img->current_mb_nr!=0))||((!img->picture_structure)&amt;&amt;(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 &amt;&amt; (img->current_mb_nr ==0
||(img->current_mb_nr>0 &amt;&amt; 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 (&amt;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 &amt;&amt; (img->current_mb_nr ==0
||(img->current_mb_nr>0 &amt;&amt; 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 (&amt;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 &amt;&amt; (img->current_mb_nr ==0
||(img->current_mb_nr>0 &amt;&amt; 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 (&amt;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; i<img->height; 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; i<img->height_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 &amt;&amt; currBitStream->streamBuffer[current_slice_bytepos+1]==0 &amt;&amt; 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<<currStream->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]&amt;(0x01<<(j-1));
if(bitnum==2)
{
nonzero = rawbitsequence &amt; 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] &amt;= (~(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 *************************///
//////////////////////////////////////////////////////////////////////////