📄 image.c
字号:
// *************************************************************************************
// *************************************************************************************
// Image.c Code one image/slice
//
// Main contributors (see contributors.h for copyright, address and affiliation details)
//
// Inge Lille-Lang鴜 <inge.lille-langoy@telenor.com>
// Rickard Sjoberg <rickard.sjoberg@era.ericsson.se>
// Jani Lainema <jani.lainema@nokia.com>
// Sebastian Purreiter <sebastian.purreiter@mch.siemens.de>
// Byeong-Moon Jeon <jeonbm@lge.com>
// Yoon-Seong Soh <yunsung@lge.com>
// Thomas Stockhammer <stockhammer@ei.tum.de>
// Detlev Marpe <marpe@hhi.de>
// Guido Heising <heising@hhi.de>
// Thomas Wedi <wedi@tnt.uni-hannover.de>
// *************************************************************************************
// *************************************************************************************
#include "contributors.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <sys/timeb.h>
#include <string.h>
#include <memory.h>
#include <assert.h>
#include "global.h"
//#include "elements.h"
#include "image.h"
#include "refbuf.h"
#ifdef _ADAPT_LAST_GROUP_
int *last_P_no;
#endif
static void UnifiedOneForthPix (pel_t **imgY, pel_t** imgU, pel_t **imgV,
pel_t **out4Y, pel_t **outU, pel_t **outV, pel_t *ref11);
/************************************************************************
*
* Name : encode_one_frame()
*
* Description: Encodes one frame
*
************************************************************************/
int encode_one_frame()
{
Boolean end_of_frame = FALSE;
SyntaxElement sym;
time_t ltime1; // for time measurement
time_t ltime2;
#ifdef WIN32
struct _timeb tstruct1;
struct _timeb tstruct2;
#else
//struct tm *l_time;
//char string[20];
struct timeb tstruct1;
struct timeb tstruct2;
//time_t now;
#endif
int tmp_time;
#ifdef WIN32
_ftime( &tstruct1 ); // start time ms
#else
ftime(&tstruct1);
#endif
time( <ime1 ); // start time s
/* Initialize frame with all stat and img variables */
img->total_number_mb = (img->width * img->height)/(MB_BLOCK_SIZE*MB_BLOCK_SIZE);
init_frame();
/* Initialize loopfilter */
init_loop_filter();
// StW: The following used to set imgTypeSymbol's len and info fields to a value according
// to img->no_multpred and img->type. Those two were set elsewhere (in lencod.c to be
// precise.
// The function was moved to header.c, function PictureHeader().
//
// /* Select picture type: write coding to symbol */
// select_picture_type(&imgTypeSymbol);
/* Read one new frame */
read_one_new_frame();
if (img->type == B_IMG)
Bframe_ctr++;
while (end_of_frame == FALSE) /* loop over slices */
{
/* Encode the current slice */
encode_one_slice(&sym);
/* Proceed to next slice */
img->current_slice_nr++;
stat->bit_slice = 0;
if (img->current_mb_nr == img->total_number_mb) /* end of frame reached? */
end_of_frame = TRUE;
}
loopfilter(img); // reconstructed imgY, imgUV -> loop-filtered imgY, imgUV
// in future only one call of oneforthpix() for all frame tyoes will be necessary, because
// mref buffer will be increased by one frame to store also the next P-frame. Then mref_P
// will not be used any more
if (img->type != B_IMG) /*all I- and P-frames*/
{
if (input->successive_Bframe == 0 || img->number == 0)
interpolate_frame(); // I- and P-frames:loop-filtered imgY, imgUV -> mref[][][], mcef[][][][]
else
interpolate_frame_2(); // I- and P-frames prior a B-frame:loop-filtered imgY, imgUV -> mref_P[][][], mcef_P[][][][]
// I- and P-frames prior a B-frame:loop-filtered imgY, imgUV -> mref_P[][][], mcef_P[][][][]
}
else
if (img->b_frame_to_code == input->successive_Bframe)
copy2mref(img); // last successive B-frame: mref_P[][][], mcef_P[][][][] (loop-filtered imgY, imgUV)-> mref[][][], mcef[][][][]
find_snr(snr,img);
time(<ime2); // end time sec
#ifdef WIN32
_ftime(&tstruct2); // end time ms
#else
ftime(&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();
if(img->number == 0)
{
printf("%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);
stat->bitr0=stat->bitr;
stat->bit_ctr_0=stat->bit_ctr;
stat->bit_ctr=0;
}
else
{
if (img->type != B_IMG)
{
stat->bit_ctr_P += stat->bit_ctr-stat->bit_ctr_n;
printf("%3d(P) %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);
}
else
{
stat->bit_ctr_B += stat->bit_ctr-stat->bit_ctr_n;
printf("%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);
}
}
stat->bit_ctr_n=stat->bit_ctr;
if(img->number == 0)
return 0;
else
return 1;
}
/************************************************************************
*
* Name : encode_one_slice()
*
* Description: Encodes one slice
*
************************************************************************/
void encode_one_slice(SyntaxElement *sym)
{
Boolean end_of_slice = FALSE;
Boolean recode_macroblock;
int len;
/* Initializes the parameters of the current slice */
init_slice();
/* Write slice or picture header */
len = start_slice(sym);
/* Update statistics */
if (img->current_mb_nr > 0)
{
img->mb_data[img->current_mb_nr].bitcounter[BITS_HEADER_MB] = len;
}
else /* first slice includes picture header */
{
if (input->symbol_mode == UVLC)
{
stat->bit_ctr += len;
stat->bit_slice += len;
}
stat->bit_use_head_mode[img->type] += len;
}
while (end_of_slice == FALSE) /* loop over macroblocks */
{
/* recode_macroblock is used in slice mode two and three where */
/* backing of one macroblock in the bitstream is possible */
recode_macroblock = FALSE;
/* Initializes the current macroblock */
start_macroblock();
/* Encode one macroblock */
encode_one_macroblock();
/* Pass the generated syntax elements to the NAL */
write_one_macroblock();
/* Terminate processing of the current macroblock */
terminate_macroblock(&end_of_slice, &recode_macroblock);
if (recode_macroblock == FALSE) /* The final processing of the macroblock has been done */
proceed2nextMacroblock(); /* Go to next macroblock */
}
terminate_slice();
}
/************************************************************************
*
* Name : init_frame()
*
* Description: Initializes the parameters for a new frame
*
************************************************************************/
void init_frame()
{
int i,j,k;
int prevP_no, nextP_no;
img->current_mb_nr=0;
img->current_slice_nr=0;
stat->bit_slice = 0;
#ifdef UMV
img->mhor = img->width *4-1;
img->mvert = img->height*4-1;
#endif
img->mb_y = img->mb_x = 0;
img->block_y = img->pix_y = img->pix_c_y = 0; /* define vertical positions */
img->block_x = img->pix_x = img->block_c_x = img->pix_c_x = 0; /* define horizontal positions */
if (input->intra_upd > 0 && img->mb_y <= img->mb_y_intra)
img->height_err=(img->mb_y_intra*16)+15; /* for extra intra MB */
else
img->height_err=img->height-1;
if(img->type != B_IMG)
{
img->tr=img->number*(input->jumpd+1);
#ifdef _ADAPT_LAST_GROUP_
if (input->last_frame && img->number+1 == input->no_frames)
img->tr=input->last_frame;
#endif
if(img->number!=0 && input->successive_Bframe != 0) /* B pictures to encode */
nextP_tr=img->tr;
if (img->type == INTRA_IMG)
img->qp = input->qp0; /* set quant. parameter for I-frame */
else
{
#ifdef _CHANGE_QP_
if (input->qp2start > 0 && img->tr >= input->qp2start)
img->qp = input->qpN2;
else
#endif
img->qp = input->qpN;
}
img->mb_y_intra=img->mb_y_upd; /* img->mb_y_intra indicates which GOB to intra code for this frame */
if (input->intra_upd > 0) /* if error robustness, find next GOB to update */
{
img->mb_y_upd=(img->number/input->intra_upd) % (img->width/MB_BLOCK_SIZE);
}
}
else
{
img->p_interval = input->jumpd+1;
prevP_no = (img->number-1)*img->p_interval;
nextP_no = img->number*img->p_interval;
#ifdef _ADAPT_LAST_GROUP_
last_P_no[0] = prevP_no; for (i=1; i<img->buf_cycle; i++) last_P_no[i] = last_P_no[i-1]-img->p_interval;
if (input->last_frame && img->number+1 == input->no_frames)
{
nextP_no =input->last_frame;
img->p_interval =nextP_no - prevP_no;
}
#endif
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; /* ????? */
#ifdef _CHANGE_QP_
if (input->qp2start > 0 && img->tr >= input->qp2start)
img->qp = input->qpB2;
else
#endif
img->qp = input->qpB;
// initialize arrays
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;
}
}
}
/************************************************************************
*
* Name : init_slice()
*
* Description: Initializes the parameters for a new slice
*
************************************************************************/
void init_slice()
{
int i;
Slice *curr_slice = img->currentSlice;
DataPartition *dataPart;
Bitstream *currStream;
curr_slice->picture_id = img->tr%256;
curr_slice->slice_nr = img->current_slice_nr;
curr_slice->qp = img->qp;
curr_slice->start_mb_nr = img->current_mb_nr;
curr_slice->dp_mode = input->partition_mode;
curr_slice->slice_too_big = dummy_slice_too_big;
for (i=0; i<curr_slice->max_part_nr; i++)
{
dataPart = &(curr_slice->partArr[i]);
/* in priciple it is possible to assign to each partition */
/* a different entropy coding method */
if (input->symbol_mode == UVLC)
dataPart->writeSyntaxElement = writeSyntaxElement_UVLC;
else
dataPart->writeSyntaxElement = writeSyntaxElement_CABAC;
// A little hack until CABAC can handle non-byte aligned start positions StW!
// For UVLC, the stored_ positions in the bit buffer are necessary. For CABAC,
// the buffer is initialized to start at zero.
if (input->symbol_mode == UVLC) {
currStream = dataPart->bitstream;
currStream->bits_to_go = currStream->stored_bits_to_go;
currStream->byte_pos = currStream->stored_byte_pos;
currStream->byte_buf = currStream->stored_byte_buf;
} else { // CABAC
currStream = dataPart->bitstream;
currStream->bits_to_go = 8;
currStream->byte_pos = 0;
currStream->byte_buf = 0;
}
}
}
/************************************************************************
*
* Name : init_loop_filter()
*
* Description: initializes loop filter
*
************************************************************************/
void init_loop_filter()
{
int i, j;
for (i=0;i<img->width/4+2;i++)
for (j=0;j<img->height/4+2;j++)
loopb[i+1][j+1]=0;
for (i=0;i<img->width_cr/4+2;i++)
for (j=0;j<img->height_cr/4+2;j++)
loopc[i+1][j+1]=0;
}
/************************************************************************
*
* Name : read_one_new frame()
*
* Description: Reads new frame from file and sets frame_no
*
************************************************************************/
void read_one_new_frame()
{
int i, j, uv;
int status; //frame_no;
int frame_size = img->height*img->width*3/2;
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);
#ifdef _ADAPT_LAST_GROUP_
if (input->last_frame && img->number+1 == input->no_frames)
frame_no=input->last_frame;
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -