📄 image.c
字号:
/*!
*************************************************************************************
* \file image.c
*
* \brief
* Code one image/slice
*
* \author
* Main contributors (see contributors.h for copyright, address and affiliation details)
* - Inge Lille-Langoy <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
* - Thomas Wedi <wedi@tnt.uni-hannover.de>
* - Ragip Kurceren <ragip.kurceren@nokia.com>
* - Antti Hallapuro <antti.hallapuro@nokia.com>
* - Alexis Michael Tourapis <alexismt@ieee.org>
* - Athanasios Leontaris <aleon@dolby.com>
*************************************************************************************
*/
#include "contributors.h"
#include <math.h>
#include <time.h>
#include <sys/timeb.h>
#include "global.h"
#include "filehandle.h"
#include "mbuffer.h"
#include "img_luma.h"
#include "img_chroma.h"
#include "img_distortion.h"
#include "intrarefresh.h"
#include "slice.h"
#include "fmo.h"
#include "sei.h"
#include "memalloc.h"
#include "nalu.h"
#include "ratectl.h"
#include "mb_access.h"
#include "cabac.h"
#include "context_ini.h"
#include "enc_statistics.h"
#include "conformance.h"
#include "q_matrix.h"
#include "q_offsets.h"
#include "wp.h"
#include "input.h"
#include "image.h"
#include "errdo.h"
extern pic_parameter_set_rbsp_t *PicParSet[MAXPPS];
extern void DeblockFrame(ImageParameters *img, imgpel **, imgpel ***);
static void code_a_picture(Picture *pic);
static void field_picture(Picture *top, Picture *bottom);
static void prepare_enc_frame_picture (StorablePicture **stored_pic);
static void writeout_picture(Picture *pic);
static byte picture_structure_decision(Picture *frame, Picture *top, Picture *bot);
static void distortion_fld (Picture *field_pic);
static void field_mode_buffer (ImageParameters *img, InputParameters *params);
static void frame_mode_buffer (ImageParameters *img, InputParameters *params);
static void init_frame(ImageParameters *img);
static void init_field(ImageParameters *img);
static void put_buffer_frame(ImageParameters *img);
static void put_buffer_top(ImageParameters *img);
static void put_buffer_bot(ImageParameters *img);
static void PaddAutoCropBorders (FrameFormat output, int img_size_x, int img_size_y, int img_size_x_cr, int img_size_y_cr);
static void rdPictureCoding(void);
#ifdef _ADAPT_LAST_GROUP_
int *last_P_no;
int *last_P_no_frm;
int *last_P_no_fld;
#endif
int FrameNumberInFile;
static void ReportFirstframe(time_t tmp_time, time_t me_time);
static void ReportIntra(time_t tmp_time, time_t me_time);
static void ReportSP(time_t tmp_time, time_t me_time);
static void ReportP(time_t tmp_time, time_t me_time);
static void ReportB(time_t tmp_time, time_t me_time);
static void ReportNALNonVLCBits(time_t tmp_time, time_t me_time);
StorablePicture *enc_picture;
StorablePicture **enc_frame_picture;
StorablePicture **enc_field_picture;
StorablePicture *enc_frame_picture_JV[MAX_PLANE]; //!< enc_frame_picture to be used during 4:4:4 independent mode encoding
void MbAffPostProc(void)
{
imgpel temp[32][16];
imgpel ** imgY = enc_picture->imgY;
imgpel ***imgUV = enc_picture->imgUV;
int i, y, x0, y0, uv;
if (img->yuv_format != YUV400)
{
for (i=0; i<(int)img->PicSizeInMbs; i+=2)
{
if (enc_picture->motion.mb_field[i])
{
get_mb_pos(i, img->mb_size[IS_LUMA], &x0, &y0);
for (y=0; y<(2*MB_BLOCK_SIZE);y++)
memcpy(&temp[y],&imgY[y0+y][x0], MB_BLOCK_SIZE * sizeof(imgpel));
for (y=0; y<MB_BLOCK_SIZE;y++)
{
memcpy(&imgY[y0+(2*y)][x0],temp[y], MB_BLOCK_SIZE * sizeof(imgpel));
memcpy(&imgY[y0+(2*y + 1)][x0],temp[y+ MB_BLOCK_SIZE], MB_BLOCK_SIZE * sizeof(imgpel));
}
x0 = x0 / (16/img->mb_cr_size_x);
y0 = y0 / (16/img->mb_cr_size_y);
for (uv=0; uv<2; uv++)
{
for (y=0; y < (2 * img->mb_cr_size_y); y++)
memcpy(&temp[y],&imgUV[uv][y0+y][x0], img->mb_cr_size_x * sizeof(imgpel));
for (y=0; y<img->mb_cr_size_y;y++)
{
memcpy(&imgUV[uv][y0+(2*y)][x0],temp[y], img->mb_cr_size_x * sizeof(imgpel));
memcpy(&imgUV[uv][y0+(2*y + 1)][x0],temp[y+ img->mb_cr_size_y], img->mb_cr_size_x * sizeof(imgpel));
}
}
}
}
}
else
{
for (i=0; i<(int)img->PicSizeInMbs; i+=2)
{
if (enc_picture->motion.mb_field[i])
{
get_mb_pos(i, img->mb_size[IS_LUMA], &x0, &y0);
for (y=0; y<(2*MB_BLOCK_SIZE);y++)
memcpy(&temp[y],&imgY[y0+y][x0], MB_BLOCK_SIZE * sizeof(imgpel));
for (y=0; y<MB_BLOCK_SIZE;y++)
{
memcpy(&imgY[y0+(2*y)][x0],temp[y], MB_BLOCK_SIZE * sizeof(imgpel));
memcpy(&imgY[y0+(2*y + 1)][x0],temp[y+ MB_BLOCK_SIZE], MB_BLOCK_SIZE * sizeof(imgpel));
}
}
}
}
}
/*!
************************************************************************
* \brief
* Sets slice type
*
************************************************************************
*/
void set_slice_type(int slice_type)
{
img->type = slice_type; // set slice type
img->RCMinQP = params->RCMinQP[img->type];
img->RCMaxQP = params->RCMaxQP[img->type];
}
void code_a_plane(ImageParameters *img, Picture *pic)
{
unsigned int NumberOfCodedMBs = 0;
int SliceGroup = 0;
// The slice_group_change_cycle can be changed here.
// FmoInit() is called before coding each picture, frame or field
img->slice_group_change_cycle=1;
FmoInit(img, active_pps, active_sps);
FmoStartPicture (); //! picture level initialization of FMO
CalculateQuantParam();
CalculateOffsetParam();
if(params->Transform8x8Mode)
{
CalculateQuant8Param();
CalculateOffset8Param();
}
reset_pic_bin_count();
img->bytes_in_picture = 0;
while (NumberOfCodedMBs < img->PicSizeInMbs) // loop over slices
{
// Encode one SLice Group
while (!FmoSliceGroupCompletelyCoded (SliceGroup))
{
// Encode the current slice
NumberOfCodedMBs += encode_one_slice (SliceGroup, pic, NumberOfCodedMBs);
FmoSetLastMacroblockInSlice (img->current_mb_nr);
// Proceed to next slice
img->current_slice_nr++;
stats->bit_slice = 0;
}
// Proceed to next SliceGroup
SliceGroup++;
}
FmoEndPicture ();
if ((params->SkipDeBlockNonRef == 0) || (img->nal_reference_idc != 0))
DeblockFrame (img, enc_picture->imgY, enc_picture->imgUV); //comment out to disable deblocking filter
}
/*!
************************************************************************
* \brief
* Encodes a picture
*
* This is the main picture coding loop.. It is called by all this
* frame and field coding stuff after the img-> elements have been
* set up. Not sure whether it is useful for MB-adaptive frame/field
* coding
************************************************************************
*/
static void code_a_picture(Picture *pic)
{
int pl;
int idr_refresh;
// currently this code only supports fixed enhancement layer distance
if ( params->idr_period && !params->adaptive_idr_period )
idr_refresh = (( ( img->frm_number - img->lastIDRnumber ) % params->idr_period ) == 0);
else if ( params->idr_period && params->adaptive_idr_period == 1 )
idr_refresh = (( ( img->frm_number - imax(img->lastIntraNumber, img->lastIDRnumber) ) % params->idr_period ) == 0);
else
idr_refresh = (img->frm_number == 0);
img->currentPicture = pic;
img->currentPicture->idr_flag = ((!IMG_NUMBER) && (!(img->structure==BOTTOM_FIELD)))
|| (idr_refresh && (img->type == I_SLICE || img->type==SI_SLICE)&& (!(img->structure==BOTTOM_FIELD)));
pic->no_slices = 0;
RandomIntraNewPicture (); //! Allocates forced INTRA MBs (even for fields!)
if( IS_INDEPENDENT( params ) )
{
for( pl=0; pl<MAX_PLANE; pl++ )
{
img->current_mb_nr = 0;
img->current_slice_nr = 0;
img->SumFrameQP = 0;
img->colour_plane_id = pl;
code_a_plane(img, pic);
}
}
else
{
code_a_plane(img, pic);
}
if (img->MbaffFrameFlag)
MbAffPostProc();
}
void update_global_stats(StatParameters *cur_stats)
{
int i, j, k;
for (i = 0; i < 4; i++)
stats->intra_chroma_mode[i] += cur_stats->intra_chroma_mode[i];
for (i = 0; i < 5; i++)
{
stats->quant[i] += cur_stats->quant[i];
stats->num_macroblocks[i] += cur_stats->num_macroblocks[i];
stats->bit_use_mb_type [i] += cur_stats->bit_use_mb_type[i];
stats->bit_use_header [i] += cur_stats->bit_use_header[i];
stats->tmp_bit_use_cbp [i] += cur_stats->tmp_bit_use_cbp[i];
stats->bit_use_coeffC [i] += cur_stats->bit_use_coeffC[i];
stats->bit_use_coeff[0][i] += cur_stats->bit_use_coeff[0][i];
stats->bit_use_coeff[1][i] += cur_stats->bit_use_coeff[1][i];
stats->bit_use_coeff[2][i] += cur_stats->bit_use_coeff[2][i];
stats->bit_use_delta_quant[i] += cur_stats->bit_use_delta_quant[i];
stats->bit_use_stuffingBits[i] += cur_stats->bit_use_stuffingBits[i];
for (k = 0; k < 2; k++)
stats->b8_mode_0_use[i][k] += cur_stats->b8_mode_0_use[i][k];
for (j = 0; j < 15; j++)
{
stats->mode_use[i][j] += cur_stats->mode_use[i][j];
stats->bit_use_mode[i][j] += cur_stats->bit_use_mode[i][j];
for (k = 0; k < 2; k++)
stats->mode_use_transform[i][j][k] += cur_stats->mode_use_transform[i][j][k];
}
}
}
void free_pictures(int stored_pic)
{
int i;
for (i = 0; i < 6; i++)
{
if (i != stored_pic)
free_storable_picture(enc_frame_picture[i]);
}
}
/*!
************************************************************************
* \brief
* Encodes one frame
************************************************************************
*/
int encode_one_frame (void)
{
static int prev_frame_no = 0; // POC200301
static int consecutive_non_reference_pictures = 0; // POC200301
int i, j;
int nplane;
//Rate control
int bits = 0;
#ifdef _LEAKYBUCKET_
//extern long Bit_Buffer[20000];
extern unsigned long total_frame_buffer;
#endif
TIME_T start_time;
TIME_T end_time;
time_t tmp_time;
me_time = 0;
img->rd_pass = 0;
if( IS_INDEPENDENT(params) )
{
for( nplane=0; nplane<MAX_PLANE; nplane++ ){
enc_frame_picture_JV[nplane] = NULL;
}
}
for (i = 0; i < 6; i++)
enc_frame_picture[i] = NULL;
gettime(&start_time); // start time in ms
//Rate control
img->write_macroblock = FALSE;
/*
//Shankar Regunathan (Oct 2002)
//Prepare Panscanrect SEI payload
UpdatePanScanRectInfo ();
//Prepare Arbitrarydata SEI Payload
UpdateUser_data_unregistered ();
//Prepare Registered data SEI Payload
UpdateUser_data_registered_itu_t_t35 ();
//Prepare RandomAccess SEI Payload
UpdateRandomAccess ();
*/
if ((params->ResendPPS) && (img->frm_number !=0))
{
stats->bit_ctr_parametersets_n = write_PPS(0, 0);
stats->bit_ctr_parametersets += stats->bit_ctr_parametersets_n;
}
put_buffer_frame (img); // sets the pointers to the frame structures
// (and not to one of the field structures)
init_frame (img);
ReadOneFrame (FrameNumberInFile, params->infile_header, ¶ms->source, ¶ms->output);
PaddAutoCropBorders (params->output, img->width, img->height, img->width_cr, img->height_cr);
// set parameters for direct mode and deblocking filter
img->direct_spatial_mv_pred_flag = params->direct_spatial_mv_pred_flag;
img->DFDisableIdc = params->DFDisableIdc[img->nal_reference_idc > 0][img->type];
img->DFAlphaC0Offset = params->DFAlpha [img->nal_reference_idc > 0][img->type];
img->DFBetaOffset = params->DFBeta [img->nal_reference_idc > 0][img->type];
img->AdaptiveRounding = params->AdaptiveRounding;
// Following code should consider optimal coding mode. Currently also does not support
// multiple slices per frame.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -