📄 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 "context_ini.h"
#include "biariencode.h"
#include "enc_statistics.h"
#include "conformance.h"
#include "report.h"
#include "q_matrix.h"
#include "q_offsets.h"
#include "wp.h"
#include "input.h"
#include "image.h"
#include "errdo.h"
#include "img_process.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, ImageData *imgData);
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, imgpel **pImage[3]);
static void rdPictureCoding(void);
static void ReportFirstframe(int64 tmp_time, int64 me_time);
static void ReportIntra(int64 tmp_time, int64 me_time);
static void ReportP(int64 tmp_time, int64 me_time);
static void ReportB(int64 tmp_time, int64 me_time);
static void ReportNALNonVLCBits(int64 tmp_time, int64 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(ImageParameters *p_img, int slice_type)
{
p_img->type = slice_type; // set slice type
p_img->RCMinQP = params->RCMinQP[p_img->type];
p_img->RCMaxQP = params->RCMaxQP[p_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
if (!img->MbaffFrameFlag)
NumberOfCodedMBs += encode_one_slice (SliceGroup, pic, NumberOfCodedMBs);
else
NumberOfCodedMBs += encode_one_slice_MBAFF (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;
img->currentPicture = pic;
img->currentPicture->idr_flag = get_idr_flag();
if (img->currentPicture->idr_flag && params->EnableIDRGOP && img->frm_number)
{
img->last_idr_number = img->frm_no_in_file;
}
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();
}
/*!
************************************************************************
* \brief
* Determine whether picture is coded as IDR
************************************************************************
*/
int get_idr_flag( void )
{
int idr_flag;
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);
}
idr_flag = ((!img->gop_number) && (!(img->structure==BOTTOM_FIELD)))
|| (idr_refresh && (img->type == I_SLICE || img->type==SI_SLICE)&& (!(img->structure==BOTTOM_FIELD)));
return idr_flag;
}
/*!
************************************************************************
* \brief
* Update global stats
************************************************************************
*/
void update_global_stats(StatParameters *gl_stats, StatParameters *cur_stats)
{
int i, j, k;
if (params->skip_gl_stats == 0)
{
for (i = 0; i < 4; i++)
{
gl_stats->intra_chroma_mode[i] += cur_stats->intra_chroma_mode[i];
}
for (i = 0; i < 5; i++)
{
gl_stats->quant[i] += cur_stats->quant[i];
gl_stats->num_macroblocks[i] += cur_stats->num_macroblocks[i];
gl_stats->bit_use_mb_type [i] += cur_stats->bit_use_mb_type[i];
gl_stats->bit_use_header [i] += cur_stats->bit_use_header[i];
gl_stats->tmp_bit_use_cbp [i] += cur_stats->tmp_bit_use_cbp[i];
gl_stats->bit_use_coeffC [i] += cur_stats->bit_use_coeffC[i];
gl_stats->bit_use_coeff[0][i] += cur_stats->bit_use_coeff[0][i];
gl_stats->bit_use_coeff[1][i] += cur_stats->bit_use_coeff[1][i];
gl_stats->bit_use_coeff[2][i] += cur_stats->bit_use_coeff[2][i];
gl_stats->bit_use_delta_quant[i] += cur_stats->bit_use_delta_quant[i];
gl_stats->bit_use_stuffingBits[i] += cur_stats->bit_use_stuffingBits[i];
for (k = 0; k < 2; k++)
gl_stats->b8_mode_0_use[i][k] += cur_stats->b8_mode_0_use[i][k];
for (j = 0; j < 15; j++)
{
gl_stats->mode_use[i][j] += cur_stats->mode_use[i][j];
gl_stats->bit_use_mode[i][j] += cur_stats->bit_use_mode[i][j];
for (k = 0; k < 2; k++)
gl_stats->mode_use_transform[i][j][k] += cur_stats->mode_use_transform[i][j][k];
}
}
}
}
/*!
************************************************************************
* \brief
* Free storable pictures
************************************************************************
*/
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 (ImageParameters *img)
{
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;
int64 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;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -