blob: 1beb509c28d1f163fa239d688348e46b9001685e [file] [log] [blame]
/*!
***********************************************************************
* \mainpage
* This is the H.264/AVC encoder reference software. For detailed documentation
* see the comments in each file.
*
* \author
* The main contributors are listed in contributors.h
*
* \version
* JM 12.1 (FRExt)
*
* \note
* tags are used for document system "doxygen"
* available at http://www.doxygen.org
*/
/*!
* \file
* lencod.c
* \brief
* H.264/AVC reference encoder project main()
* \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>
* - Stephan Wenger <stewe@cs.tu-berlin.de>
* - Jani Lainema <jani.lainema@nokia.com>
* - 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>
* - Valeri George <george@hhi.de>
* - Karsten Suehring <suehring@hhi.de>
* - Alexis Michael Tourapis <alexismt@ieee.org>
***********************************************************************
*/
#include "contributors.h"
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <sys/timeb.h>
#include "global.h"
#include "configfile.h"
#include "leaky_bucket.h"
#include "memalloc.h"
#include "intrarefresh.h"
#include "fmo.h"
#include "sei.h"
#include "parset.h"
#include "image.h"
#include "output.h"
#include "me_epzs.h"
#include "me_umhex.h"
#include "me_umhexsmp.h"
#include "ratectl.h"
#include "rc_quadratic.h"
#include "explicit_gop.h"
#define JM "12 (FRExt)"
#define VERSION "12.1"
#define EXT_VERSION "(FRExt)"
static const char *mybasename(const char *str) {
const char *base = strrchr(str, '/');
return base ? base+1 : str;
}
InputParameters inputs, *input = &inputs;
ImageParameters images, *img = &images;
StatParameters statistics, *stats = &statistics;
SNRParameters snrs, *snr = &snrs;
Decoders decoders, *decs=&decoders;
static void information_init(void);
#ifdef _ADAPT_LAST_GROUP_
int initial_Bframes = 0;
#endif
Boolean In2ndIGOP = FALSE;
int start_frame_no_in_this_IGOP = 0;
int start_tr_in_this_IGOP = 0;
int FirstFrameIn2ndIGOP=0;
int cabac_encoding = 0;
int frame_statistic_start;
extern ColocatedParams *Co_located;
extern double *mb16x16_cost_frame;
static char DistortionType[3][20] = {"SAD","SSE","Hadamard SAD"};
void Init_Motion_Search_Module (void);
void Clear_Motion_Search_Module (void);
void report_frame_statistic(void);
void SetLevelIndices(void);
void chroma_mc_setup(void);
void init_stats(void)
{
stats->successive_Bframe = input->successive_Bframe;
stats->bit_ctr_I = 0;
stats->bit_ctr_P = 0;
stats->bit_ctr_B = 0;
snr->snr_y = 0.0;
snr->snr_u = 0.0;
snr->snr_v = 0.0;
snr->snr_y1 = 0.0;
snr->snr_u1 = 0.0;
snr->snr_v1 = 0.0;
snr->snr_ya = 0.0;
snr->snr_ua = 0.0;
snr->snr_va = 0.0;
snr->sse_y = 0.0;
snr->sse_u = 0.0;
snr->sse_v = 0.0;
snr->msse_y = 0.0;
snr->msse_u = 0.0;
snr->msse_v = 0.0;
snr->frame_ctr = 0;
}
/*!
***********************************************************************
* \brief
* Main function for encoder.
* \param argc
* number of command line arguments
* \param argv
* command line arguments
* \return
* exit code
***********************************************************************
*/
int main(int argc,char **argv)
{
int M,N,n,np,nb; //Rate control
int primary_disp = 0;
giRDOpt_B8OnlyFlag = 0;
p_dec = p_in = -1;
p_stat = p_log = p_trace = NULL;
frame_statistic_start = 1;
Configure (argc, argv);
Init_QMatrix();
Init_QOffsetMatrix();
AllocNalPayloadBuffer();
init_poc();
GenerateParameterSets();
SetLevelIndices();
init_img();
frame_pic_1= malloc_picture();
if (input->RDPictureDecision)
{
frame_pic_2 = malloc_picture();
frame_pic_3 = malloc_picture();
}
if (input->si_frame_indicator)
{
si_frame_indicator=0; //indicates whether the frame is SP or SI
number_sp2_frames=0;
frame_pic_si = malloc_picture();//picture buffer for the encoded SI picture
//allocation of lrec and lrec_uv for SI picture
get_mem2Dint (&lrec, img->height, img->width);
get_mem3Dint (&lrec_uv, 2, img->height, img->width);
}
if (input->PicInterlace != FRAME_CODING)
{
top_pic = malloc_picture();
bottom_pic = malloc_picture();
}
init_rdopt ();
#ifdef _LEAKYBUCKET_
Bit_Buffer = malloc((input->no_frames * (input->successive_Bframe + 1) + 1) * sizeof(long));
#endif
if (input->HierarchicalCoding )
{
init_gop_structure();
if (input->successive_Bframe && input->HierarchicalCoding == 3)
{
interpret_gop_structure();
}
else
{
create_hierarchy();
}
}
dpb.init_done = 0;
init_dpb();
init_out_buffer();
init_stats();
enc_picture = enc_frame_picture = enc_top_picture = enc_bottom_picture = NULL;
init_global_buffers();
create_context_memory ();
Init_Motion_Search_Module ();
information_init();
//Rate control
if (input->RCEnable)
rc_init_seq(quadratic_RC);
if(input->SearchMode == UM_HEX)
UMHEX_DefineThreshold();
// Init frame type counter. Only supports single slice per frame.
memset(frame_ctr, 0, 5 * sizeof(int));
img->last_valid_reference = 0;
tot_time=0; // time for total encoding session
#ifdef _ADAPT_LAST_GROUP_
if (input->last_frame > 0)
input->no_frames = 1 + (input->last_frame + input->jumpd) / (input->jumpd + 1);
initial_Bframes = input->successive_Bframe;
#endif
PatchInputNoFrames();
// Write sequence header (with parameter sets)
stats->bit_ctr_parametersets = 0;
stats->bit_slice = start_sequence();
stats->bit_ctr_parametersets += stats->bit_ctr_parametersets_n;
start_frame_no_in_this_IGOP = 0;
if ( input->ChromaMCBuffer )
chroma_mc_setup();
for (img->number=0; img->number < input->no_frames; img->number++)
{
//img->nal_reference_idc = 1;
if (input->intra_period)
img->nal_reference_idc = ((IMG_NUMBER % input->intra_period) && input->DisposableP) ? (img->number + 1)% 2 : 1;
else
img->nal_reference_idc = (img->number && input->DisposableP) ? (img->number + 1)% 2 : 1;
//much of this can go in init_frame() or init_field()?
//poc for this frame or field
img->toppoc = (input->intra_period && input->idr_enable ? IMG_NUMBER % input->intra_period : IMG_NUMBER) * (2*(input->jumpd+1));
if ((input->PicInterlace==FRAME_CODING)&&(input->MbInterlace==FRAME_CODING))
img->bottompoc = img->toppoc; //progressive
else
img->bottompoc = img->toppoc+1; //hard coded
img->framepoc = imin (img->toppoc, img->bottompoc);
//frame_num for this frame
//if (input->BRefPictures== 0 || input->successive_Bframe == 0 || img-> number < 2)
if ((input->BRefPictures != 1 && input->HierarchicalCoding == 0) || input->successive_Bframe == 0 || img-> number < 2)// || input->HierarchicalCoding == 0)
{
if (input->intra_period && input->idr_enable)
{
img->frame_num = ((IMG_NUMBER - primary_disp) % input->intra_period ) % (1 << (log2_max_frame_num_minus4 + 4));
if (IMG_NUMBER % input->intra_period == 0)
{
img->frame_num = 0;
primary_disp = 0;
}
}
else
img->frame_num = (IMG_NUMBER - primary_disp) % (1 << (log2_max_frame_num_minus4 + 4));
}
else
{
//img->frame_num ++;
if (input->intra_period && input->idr_enable)
{
if (0== (img->number % input->intra_period))
{
img->frame_num=0;
primary_disp = 0;
}
}
img->frame_num %= (1 << (log2_max_frame_num_minus4 + 4));
}
//the following is sent in the slice header
img->delta_pic_order_cnt[0]=0;
if (input->BRefPictures == 1)
{
if (img->number)
{
img->delta_pic_order_cnt[0]=+2 * input->successive_Bframe;
}
}
SetImgType();
if (input->ResendSPS == 1 && img->type == I_SLICE && img->number != 0)
{
stats->bit_slice = rewrite_paramsets();
stats->bit_ctr_parametersets += stats->bit_ctr_parametersets_n;
}
#ifdef _ADAPT_LAST_GROUP_
if (input->successive_Bframe && input->last_frame && IMG_NUMBER+1 == input->no_frames)
{
int bi = (int)((float)(input->jumpd+1)/(input->successive_Bframe+1.0)+0.499999);
input->successive_Bframe = (input->last_frame-(img->number-1)*(input->jumpd+1))/bi-1;
//about to code the last ref frame, adjust delta poc
img->delta_pic_order_cnt[0]= -2*(initial_Bframes - input->successive_Bframe);
img->toppoc += img->delta_pic_order_cnt[0];
img->bottompoc += img->delta_pic_order_cnt[0];
img->framepoc = imin (img->toppoc, img->bottompoc);
}
#endif
//Rate control
if (img->type == I_SLICE && ((input->RCUpdateMode != RC_MODE_1 && input->RCUpdateMode != RC_MODE_3) || (!IMG_NUMBER) ) )
{
if(input->RCEnable)
{
if (input->intra_period == 0)
{
n = input->no_frames + (input->no_frames - 1) * input->successive_Bframe;
/* number of P frames */
np = input->no_frames-1;
/* number of B frames */
nb = (input->no_frames - 1) * input->successive_Bframe;
}
else if ( input->RCUpdateMode != RC_MODE_1 && input->RCUpdateMode != RC_MODE_3 )
{
N = input->intra_period*(input->successive_Bframe+1);
M = input->successive_Bframe+1;
n = (img->number==0) ? N - ( M - 1) : N;
/* last GOP may contain less frames */
if(img->number/input->intra_period >= input->no_frames / input->intra_period)
{
if (img->number != 0)
n = (input->no_frames - img->number) + (input->no_frames - img->number - 1) * input->successive_Bframe + input->successive_Bframe;
else
n = input->no_frames + (input->no_frames - 1) * input->successive_Bframe;
}
/* number of P frames */
if (img->number == 0)
np = (n + 2 * (M - 1)) / M - 1; /* first GOP */
else
np = (n + (M - 1)) / M - 1;
/* number of B frames */
nb = n - np - 1;
}
else // applies RC to I and B slices
{
np = input->no_frames - 1; // includes I and P slices/frames except the very first IDR I_SLICE
nb = (input->no_frames - 1) * input->successive_Bframe;
}
rc_init_GOP(quadratic_RC,np,nb);
}
}
// which layer the image belonged to?
if ( IMG_NUMBER % (input->NumFramesInELSubSeq+1) == 0 )
img->layer = 0;
else
img->layer = 1;
// redundant frame initialization and allocation
if(input->redundant_pic_flag)
{
Init_redundant_frame();
Set_redundant_frame();
}
encode_one_frame(); // encode one I- or P-frame
// if key frame is encoded, encode one redundant frame
if(input->redundant_pic_flag && key_frame)
{
encode_one_redundant_frame();
}
if (img->type == I_SLICE && input->EnableOpenGOP)
img->last_valid_reference = img->ThisPOC;
if (input->ReportFrameStats)
report_frame_statistic();
if (img->nal_reference_idc == 0)
{
primary_disp ++;
img->frame_num -= 1;
img->frame_num %= (1 << (log2_max_frame_num_minus4 + 4));
}
encode_enhancement_layer();
process_2nd_IGOP();
}
// terminate sequence
terminate_sequence();
flush_dpb();
close(p_in);
if (-1!=p_dec)
close(p_dec);
if (p_trace)
fclose(p_trace);
Clear_Motion_Search_Module ();
RandomIntraUninit();
FmoUninit();
if (input->HierarchicalCoding)
clear_gop_structure ();
// free structure for rd-opt. mode decision
clear_rdopt ();
#ifdef _LEAKYBUCKET_
calc_buffer();
#endif
// report everything
report();
#ifdef _LEAKYBUCKET_
free(Bit_Buffer);
#endif
free_picture (frame_pic_1);
if (input->RDPictureDecision)
{
free_picture (frame_pic_2);
free_picture (frame_pic_3);
}
// Deallocation of SI picture related memory
if (input->si_frame_indicator)
{
free_picture (frame_pic_si);
//deallocation of lrec and lrec_uv for SI frames
free_mem2Dint (lrec);
free_mem3Dint (lrec_uv,2);
}
if (top_pic)
free_picture (top_pic);
if (bottom_pic)
free_picture (bottom_pic);
free_dpb();
free_colocated(Co_located);
uninit_out_buffer();
free_global_buffers();
// free image mem
free_img ();
free_context_memory ();
FreeNalPayloadBuffer();
FreeParameterSets();
return 0;
}
/*!
***********************************************************************
* \brief
* Terminates and reports statistics on error.
*
***********************************************************************
*/
void report_stats_on_error(void)
{
input->no_frames=img->number;
terminate_sequence();
flush_dpb();
close(p_in);
if (-1!=p_dec)
close(p_dec);
if (p_trace)
fclose(p_trace);
Clear_Motion_Search_Module ();
RandomIntraUninit();
FmoUninit();
if (input->HierarchicalCoding)
clear_gop_structure ();
// free structure for rd-opt. mode decision
clear_rdopt ();
#ifdef _LEAKYBUCKET_
calc_buffer();
#endif
if (input->ReportFrameStats)
report_frame_statistic();
// report everything
report();
free_picture (frame_pic_1);
if (top_pic)
free_picture (top_pic);
if (bottom_pic)
free_picture (bottom_pic);
free_dpb();
free_colocated(Co_located);
uninit_out_buffer();
free_global_buffers();
// free image mem
free_img ();
free_context_memory ();
FreeNalPayloadBuffer();
FreeParameterSets();
}
/*!
***********************************************************************
* \brief
* Initializes the POC structure with appropriate parameters.
*
***********************************************************************
*/
void init_poc()
{
//the following should probably go in sequence parameters
// frame poc's increase by 2, field poc's by 1
img->pic_order_cnt_type=input->pic_order_cnt_type;
img->delta_pic_order_always_zero_flag = FALSE;
img->num_ref_frames_in_pic_order_cnt_cycle= 1;
if (input->BRefPictures == 1)
{
img->offset_for_non_ref_pic = 0;
img->offset_for_ref_frame[0] = 2;
}
else
{
img->offset_for_non_ref_pic = -2*(input->successive_Bframe);
img->offset_for_ref_frame[0] = 2*(input->successive_Bframe+1);
}
if ((input->PicInterlace==FRAME_CODING)&&(input->MbInterlace==FRAME_CODING))
img->offset_for_top_to_bottom_field=0;
else
img->offset_for_top_to_bottom_field=1;
if ((input->PicInterlace==FRAME_CODING)&&(input->MbInterlace==FRAME_CODING))
{
img->pic_order_present_flag=FALSE;
img->delta_pic_order_cnt_bottom = 0;
}
else
{
img->pic_order_present_flag=TRUE;
img->delta_pic_order_cnt_bottom = 1;
}
}
/*!
***********************************************************************
* \brief
* Initializes the img->nz_coeff
* \par Input:
* none
* \par Output:
* none
* \ side effects
* sets omg->nz_coef[][][][] to -1
***********************************************************************
*/
void CAVLC_init(void)
{
unsigned int i, k, l;
for (i=0;i < img->PicSizeInMbs; i++)
for (k=0;k<4;k++)
for (l=0;l < (4 + (unsigned int)img->num_blk8x8_uv);l++)
img->nz_coeff[i][k][l]=0;
}
/*!
***********************************************************************
* \brief
* Initializes the Image structure with appropriate parameters.
* \par Input:
* Input Parameters struct inp_par *inp
* \par Output:
* Image Parameters struct img_par *img
***********************************************************************
*/
void init_img()
{
int i;
int byte_abs_range;
static int mb_width_cr[4] = {0,8, 8,16};
static int mb_height_cr[4]= {0,8,16,16};
img->yuv_format = input->yuv_format;
//pel bitdepth init
img->bitdepth_luma = input->BitDepthLuma;
img->bitdepth_luma_qp_scale = 6*(img->bitdepth_luma - 8);
img->bitdepth_lambda_scale = 2*(img->bitdepth_luma - 8);
img->dc_pred_value_luma = 1<<(img->bitdepth_luma - 1);
img->max_imgpel_value = (1<<img->bitdepth_luma) - 1;
img->mb_size[0][0] = img->mb_size[0][1] = MB_BLOCK_SIZE;
if (img->yuv_format != YUV400)
{
img->bitdepth_chroma = input->BitDepthChroma;
img->dc_pred_value_chroma = 1<<(img->bitdepth_chroma - 1);
img->max_imgpel_value_uv = (1<<img->bitdepth_chroma) - 1;
img->num_blk8x8_uv = (1<<img->yuv_format)&(~(0x1));
img->num_cdc_coeff = img->num_blk8x8_uv<<1;
img->mb_size[1][0] = img->mb_size[2][0] = img->mb_cr_size_x = (img->yuv_format==YUV420 || img->yuv_format==YUV422)? 8:16;
img->mb_size[1][1] = img->mb_size[2][1] = img->mb_cr_size_y = (img->yuv_format==YUV444 || img->yuv_format==YUV422)? 16:8;
img->bitdepth_chroma_qp_scale = 6*(img->bitdepth_chroma - 8);
img->chroma_qp_offset[0] = active_pps->cb_qp_index_offset;
img->chroma_qp_offset[1] = active_pps->cr_qp_index_offset;
}
else
{
img->bitdepth_chroma = 0;
img->max_imgpel_value_uv = 0;
img->num_blk8x8_uv = 0;
img->num_cdc_coeff = 0;
img->mb_size[1][0] = img->mb_size[2][0] = img->mb_cr_size_x = 0;
img->mb_size[1][1] = img->mb_size[2][1] = img->mb_cr_size_y = 0;
img->bitdepth_chroma_qp_scale = 0;
img->bitdepth_chroma_qp_scale = 0;
img->chroma_qp_offset[0] = 0;
img->chroma_qp_offset[1] = 0;
}
if((img->bitdepth_luma > img->bitdepth_chroma) || img->yuv_format == YUV400)
img->pic_unit_size_on_disk = (img->bitdepth_luma > 8)? 16:8;
else
img->pic_unit_size_on_disk = (img->bitdepth_chroma > 8)? 16:8;
img->max_bitCount = 128 + 256 * img->bitdepth_luma + 2 * img->mb_cr_size_y * img->mb_cr_size_x * img->bitdepth_chroma;
img->max_qp_delta = (25 + (img->bitdepth_luma_qp_scale>>1));
img->min_qp_delta = img->max_qp_delta + 1;
img->num_ref_frames = active_sps->num_ref_frames;
img->max_num_references = active_sps->frame_mbs_only_flag ? active_sps->num_ref_frames : 2 * active_sps->num_ref_frames;
img->buf_cycle = input->num_ref_frames;
img->DeblockCall = 0;
img->framerate=(float) input->FrameRate; // The basic frame rate (of the original sequence)
get_mem_mv (&(img->pred_mv));
get_mem_mv (&(img->all_mv));
if (input->BiPredMotionEstimation)
{
get_mem_mv (&(img->bipred_mv1));
get_mem_mv (&(img->bipred_mv2));
}
get_mem_ACcoeff (&(img->cofAC));
get_mem_DCcoeff (&(img->cofDC));
if (input->AdaptiveRounding)
{
get_mem3Dint(&(img->fadjust4x4), 4, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
get_mem3Dint(&(img->fadjust8x8), 3, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
get_mem4Dint(&(img->fadjust4x4Cr), 4, 2, img->mb_cr_size_y, img->mb_cr_size_x);
get_mem4Dint(&(img->fadjust8x8Cr), 1, 2, img->mb_cr_size_y, img->mb_cr_size_x);
}
if(input->MbInterlace)
{
get_mem_mv (&(rddata_top_frame_mb.pred_mv));
get_mem_mv (&(rddata_top_frame_mb.all_mv));
get_mem_mv (&(rddata_bot_frame_mb.pred_mv));
get_mem_mv (&(rddata_bot_frame_mb.all_mv));
get_mem_ACcoeff (&(rddata_top_frame_mb.cofAC));
get_mem_DCcoeff (&(rddata_top_frame_mb.cofDC));
get_mem_ACcoeff (&(rddata_bot_frame_mb.cofAC));
get_mem_DCcoeff (&(rddata_bot_frame_mb.cofDC));
if ( input->MbInterlace != FRAME_MB_PAIR_CODING )
{
get_mem_mv (&(rddata_top_field_mb.pred_mv));
get_mem_mv (&(rddata_top_field_mb.all_mv));
get_mem_mv (&(rddata_bot_field_mb.pred_mv));
get_mem_mv (&(rddata_bot_field_mb.all_mv));
get_mem_ACcoeff (&(rddata_top_field_mb.cofAC));
get_mem_DCcoeff (&(rddata_top_field_mb.cofDC));
get_mem_ACcoeff (&(rddata_bot_field_mb.cofAC));
get_mem_DCcoeff (&(rddata_bot_field_mb.cofDC));
}
}
if(img->max_imgpel_value > img->max_imgpel_value_uv)
byte_abs_range = (img->max_imgpel_value + 1) * 2;
else
byte_abs_range = (img->max_imgpel_value_uv + 1) * 2;
if ((img->quad = (int*)calloc (byte_abs_range, sizeof(int))) == NULL)
no_mem_exit ("init_img: img->quad");
img->quad+=byte_abs_range/2;
for (i=0; i < byte_abs_range/2; ++i)
{
img->quad[i]=img->quad[-i]=i*i;
}
img->width = (input->img_width+img->auto_crop_right);
img->height = (input->img_height+img->auto_crop_bottom);
img->width_blk = img->width / BLOCK_SIZE;
img->height_blk = img->height / BLOCK_SIZE;
img->width_padded = img->width + 2 * IMG_PAD_SIZE;
img->height_padded = img->height + 2 * IMG_PAD_SIZE;
if (img->yuv_format != YUV400)
{
img->width_cr = img->width/(16/mb_width_cr[img->yuv_format]);
img->height_cr= img->height/(16/mb_height_cr[img->yuv_format]);
input->img_width_cr = input->img_width/(16/mb_width_cr[img->yuv_format]);
input->img_height_cr = input->img_height/(16/mb_height_cr[img->yuv_format]);
}
else
{
img->width_cr = 0;
img->height_cr= 0;
input->img_width_cr = 0;
input->img_height_cr = 0;
}
img->height_cr_frame = img->height_cr;
img->size = img->width * img->height;
img->size_cr = img->width_cr * img->height_cr;
img->PicWidthInMbs = img->width/MB_BLOCK_SIZE;
img->FrameHeightInMbs = img->height/MB_BLOCK_SIZE;
img->FrameSizeInMbs = img->PicWidthInMbs * img->FrameHeightInMbs;
img->PicHeightInMapUnits = ( active_sps->frame_mbs_only_flag ? img->FrameHeightInMbs : img->FrameHeightInMbs/2 );
if(((img->mb_data) = (Macroblock *) calloc(img->FrameSizeInMbs,sizeof(Macroblock))) == NULL)
no_mem_exit("init_img: img->mb_data");
if(input->UseConstrainedIntraPred)
{
if(((img->intra_block) = (int*)calloc(img->FrameSizeInMbs,sizeof(int))) == NULL)
no_mem_exit("init_img: img->intra_block");
}
if (input->CtxAdptLagrangeMult == 1)
{
if ((mb16x16_cost_frame = (double*)calloc(img->FrameSizeInMbs, sizeof(double))) == NULL)
{
no_mem_exit("init mb16x16_cost_frame");
}
}
get_mem2D((byte***)&(img->ipredmode), img->height_blk, img->width_blk); //need two extra rows at right and bottom
get_mem2D((byte***)&(img->ipredmode8x8), img->height_blk, img->width_blk); // help storage for ipredmode 8x8, inserted by YV
memset(&img->ipredmode[0][0],-1, img->height_blk * img->width_blk *sizeof(char));
memset(&img->ipredmode8x8[0][0],-1, img->height_blk * img->width_blk *sizeof(char));
get_mem2D((byte***)&(rddata_top_frame_mb.ipredmode), img->height_blk, img->width_blk);
if(input->MbInterlace)
{
get_mem2D((byte***)&(rddata_bot_frame_mb.ipredmode), img->height_blk, img->width_blk);
get_mem2D((byte***)&(rddata_top_field_mb.ipredmode), img->height_blk, img->width_blk);
get_mem2D((byte***)&(rddata_bot_field_mb.ipredmode), img->height_blk, img->width_blk);
}
// CAVLC mem
get_mem3Dint(&(img->nz_coeff), img->FrameSizeInMbs, 4, 4+img->num_blk8x8_uv);
get_mem2Ddb_offset(&(img->lambda_md), 10, 52 + img->bitdepth_luma_qp_scale,img->bitdepth_luma_qp_scale);
get_mem3Ddb_offset (&(img->lambda_me), 10, 52 + img->bitdepth_luma_qp_scale, 3, img->bitdepth_luma_qp_scale);
get_mem3Dint_offset(&(img->lambda_mf), 10, 52 + img->bitdepth_luma_qp_scale, 3, img->bitdepth_luma_qp_scale);
if (input->CtxAdptLagrangeMult == 1)
{
get_mem2Ddb_offset(&(img->lambda_mf_factor), 10, 52 + img->bitdepth_luma_qp_scale,img->bitdepth_luma_qp_scale);
}
//get_mem2Ddouble(&(img->lambda_md), 10, 52 + img->bitdepth_luma_qp_scale);
CAVLC_init();
img->GopLevels = (input->successive_Bframe) ? 1 : 0;
img->mb_y_upd=0;
RandomIntraInit (img->PicWidthInMbs, img->FrameHeightInMbs, input->RandomIntraMBRefresh);
InitSEIMessages(); // Tian Dong (Sept 2002)
// Initialize filtering parameters. If sending parameters, the offsets are
// multiplied by 2 since inputs are taken in "div 2" format.
// If not sending parameters, all fields are cleared
if (input->LFSendParameters)
{
input->LFAlphaC0Offset <<= 1;
input->LFBetaOffset <<= 1;
}
else
{
input->LFDisableIdc = 0;
input->LFAlphaC0Offset = 0;
input->LFBetaOffset = 0;
}
}
/*!
***********************************************************************
* \brief
* Free the Image structures
* \par Input:
* Image Parameters struct img_par *img
***********************************************************************
*/
void free_img ()
{
CloseSEIMessages(); // Tian Dong (Sept 2002)
free_mem_mv (img->pred_mv);
free_mem_mv (img->all_mv);
if (input->BiPredMotionEstimation)
{
free_mem_mv (img->bipred_mv1);
free_mem_mv (img->bipred_mv2);
}
free_mem_ACcoeff (img->cofAC);
free_mem_DCcoeff (img->cofDC);
if (input->AdaptiveRounding)
{
free_mem3Dint(img->fadjust4x4, 4);
free_mem3Dint(img->fadjust8x8, 3);
free_mem4Dint(img->fadjust4x4Cr, 4, 2);
free_mem4Dint(img->fadjust8x8Cr, 1, 2);
}
if(input->MbInterlace)
{
free_mem_mv (rddata_top_frame_mb.pred_mv);
free_mem_mv (rddata_top_frame_mb.all_mv);
free_mem_mv (rddata_bot_frame_mb.pred_mv);
free_mem_mv (rddata_bot_frame_mb.all_mv);
free_mem_ACcoeff (rddata_top_frame_mb.cofAC);
free_mem_DCcoeff (rddata_top_frame_mb.cofDC);
free_mem_ACcoeff (rddata_bot_frame_mb.cofAC);
free_mem_DCcoeff (rddata_bot_frame_mb.cofDC);
if ( input->MbInterlace != FRAME_MB_PAIR_CODING )
{
free_mem_mv (rddata_top_field_mb.pred_mv);
free_mem_mv (rddata_top_field_mb.all_mv);
free_mem_mv (rddata_bot_field_mb.pred_mv);
free_mem_mv (rddata_bot_field_mb.all_mv);
free_mem_ACcoeff (rddata_top_field_mb.cofAC);
free_mem_DCcoeff (rddata_top_field_mb.cofDC);
free_mem_ACcoeff (rddata_bot_field_mb.cofAC);
free_mem_DCcoeff (rddata_bot_field_mb.cofDC);
}
}
if(img->max_imgpel_value > img->max_imgpel_value_uv)
free (img->quad-(img->max_imgpel_value + 1));
else
free (img->quad-(img->max_imgpel_value_uv + 1));
if(input->MbInterlace)
{
free_mem2D((byte**)rddata_bot_frame_mb.ipredmode);
free_mem2D((byte**)rddata_top_field_mb.ipredmode);
free_mem2D((byte**)rddata_bot_field_mb.ipredmode);
}
}
/*!
************************************************************************
* \brief
* Allocates the picture structure along with its dependent
* data structures
* \return
* Pointer to a Picture
************************************************************************
*/
Picture *malloc_picture()
{
Picture *pic;
if ((pic = calloc (1, sizeof (Picture))) == NULL) no_mem_exit ("malloc_picture: Picture structure");
//! Note: slice structures are allocated as needed in code_a_picture
return pic;
}
/*!
************************************************************************
* \brief
* Frees a picture
* \param
* pic: POinter to a Picture to be freed
************************************************************************
*/
void free_picture(Picture *pic)
{
if (pic != NULL)
{
free_slice_list(pic);
free (pic);
}
}
/*!
************************************************************************
* \brief
* Reports frame statistical data to a stats file
************************************************************************
*/
void report_frame_statistic()
{
FILE *p_stat_frm = NULL;
static int64 last_mode_use[NUM_PIC_TYPE][MAXMODE];
static int last_b8_mode_0[NUM_PIC_TYPE][2];
static int last_mode_chroma_use[4];
static int64 last_bit_ctr_n = 0;
int i;
char name[20];
int bitcounter;
#ifndef WIN32
time_t now;
struct tm *l_time;
char string[1000];
#else
char timebuf[128];
#endif
// write to log file
if ((p_stat_frm=fopen("stat_frame.dat","r"))==0) // check if file exist
{
if ((p_stat_frm=fopen("stat_frame.dat","a"))==NULL) // append new statistic at the end
{
snprintf(errortext, ET_SIZE, "Error open file %s \n","stat_frame.dat.dat");
error(errortext, 500);
}
else // Create header for new log file
{
fprintf(p_stat_frm," --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \n");
fprintf(p_stat_frm,"| Encoder statistics. This file is generated during first encoding session, new sessions will be appended |\n");
fprintf(p_stat_frm," --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \n");
}
}
else
{
fclose (p_stat_frm);
if ((p_stat_frm=fopen("stat_frame.dat","a"))==NULL) // File exist,just open for appending
{
snprintf(errortext, ET_SIZE, "Error open file %s \n","stat_frame.dat.dat");
error(errortext, 500);
}
}
if (frame_statistic_start)
{
fprintf(p_stat_frm,"| ver | Date | Time | Sequence |Frm | QP |P/MbInt| Bits | SNRY | SNRU | SNRV | I4 | I8 | I16 | IC0 | IC1 | IC2 | IC3 | PI4 | PI8 | PI16 | P0 | P1 | P2 | P3 | P1*8*| P1*4*| P2*8*| P2*4*| P3*8*| P3*4*| P8 | P8:4 | P4*8*| P4*4*| P8:5 | P8:6 | P8:7 | BI4 | BI8 | BI16 | B0 | B1 | B2 | B3 | B0*8*| B0*4*| B1*8*| B1*4*| B2*8*| B2*4*| B3*8*| B3*4*| B8 | B8:0 |B80*8*|B80*4*| B8:4 | B4*8*| B4*4*| B8:5 | B8:6 | B8:7 |\n");
fprintf(p_stat_frm," ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \n");
}
//report
fprintf(p_stat_frm,"|%4s/%s", VERSION, EXT_VERSION);
#ifdef WIN32
_strdate( timebuf );
fprintf(p_stat_frm,"| %1.5s |",timebuf );
_strtime( timebuf);
fprintf(p_stat_frm," % 1.5s |",timebuf);
#else
now = time ((time_t *) NULL); // Get the system time and put it into 'now' as 'calender time'
time (&now);
l_time = localtime (&now);
strftime (string, sizeof string, "%d-%b-%Y", l_time);
fprintf(p_stat_frm,"| %1.5s |",string );
strftime (string, sizeof string, "%H:%M:%S", l_time);
fprintf(p_stat_frm," %1.5s |",string );
#endif
for (i=0;i<20;i++)
name[i]=input->infile[i + imax(0,(int) (strlen(input->infile)-20))]; // write last part of path, max 20 chars
fprintf(p_stat_frm,"%20.20s|",name);
fprintf(p_stat_frm,"%3d |",frame_no);
fprintf(p_stat_frm,"%3d |",img->qp);
fprintf(p_stat_frm," %d/%d |",input->PicInterlace, input->MbInterlace);
if (img->number == 0 && img->frame_num == 0)
{
bitcounter = (int) stats->bit_ctr_I;
}
else
{
bitcounter = (int) (stats->bit_ctr_n - last_bit_ctr_n);
last_bit_ctr_n = stats->bit_ctr_n;
}
//report bitrate
fprintf(p_stat_frm, " %9d|", bitcounter);
//report snr's
fprintf(p_stat_frm, " %2.4f| %2.4f| %2.4f|", snr->snr_y, snr->snr_u, snr->snr_v);
//report modes
//I-Modes
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[I_SLICE][I4MB] - last_mode_use[I_SLICE][I4MB]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[I_SLICE][I8MB] - last_mode_use[I_SLICE][I8MB]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[I_SLICE][I16MB] - last_mode_use[I_SLICE][I16MB]);
//chroma intra mode
fprintf(p_stat_frm, " %5d|",stats->intra_chroma_mode[0] - last_mode_chroma_use[0]);
fprintf(p_stat_frm, " %5d|",stats->intra_chroma_mode[1] - last_mode_chroma_use[1]);
fprintf(p_stat_frm, " %5d|",stats->intra_chroma_mode[2] - last_mode_chroma_use[2]);
fprintf(p_stat_frm, " %5d|",stats->intra_chroma_mode[3] - last_mode_chroma_use[3]);
//P-Modes
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[P_SLICE][I4MB] - last_mode_use[P_SLICE][I4MB]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[P_SLICE][I8MB] - last_mode_use[P_SLICE][I8MB]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[P_SLICE][I16MB] - last_mode_use[P_SLICE][I16MB]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[P_SLICE][0 ] - last_mode_use[P_SLICE][0 ]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[P_SLICE][1 ] - last_mode_use[P_SLICE][1 ]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[P_SLICE][2 ] - last_mode_use[P_SLICE][2 ]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[P_SLICE][3 ] - last_mode_use[P_SLICE][3 ]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_8x8[0][1]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_4x4[0][1]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_8x8[0][2]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_4x4[0][2]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_8x8[0][3]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_4x4[0][3]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[P_SLICE][P8x8] - last_mode_use[P_SLICE][P8x8]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[P_SLICE][4 ] - last_mode_use[P_SLICE][4 ]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_8x8[0][4]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_4x4[0][4]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[P_SLICE][5 ] - last_mode_use[P_SLICE][5 ]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[P_SLICE][6 ] - last_mode_use[P_SLICE][6 ]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[P_SLICE][7 ] - last_mode_use[P_SLICE][7 ]);
//B-Modes
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[B_SLICE][I4MB] - last_mode_use[B_SLICE][I4MB]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[B_SLICE][I8MB] - last_mode_use[B_SLICE][I8MB]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[B_SLICE][I16MB] - last_mode_use[B_SLICE][I16MB]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[B_SLICE][0 ] - last_mode_use[B_SLICE][0 ]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[B_SLICE][1 ] - last_mode_use[B_SLICE][1 ]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[B_SLICE][2 ] - last_mode_use[B_SLICE][2 ]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[B_SLICE][3 ] - last_mode_use[B_SLICE][3 ]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_8x8[1][0]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_4x4[1][0]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_8x8[1][1]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_4x4[1][1]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_8x8[1][2]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_4x4[1][2]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_8x8[1][3]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_4x4[1][3]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[B_SLICE][P8x8] - last_mode_use[B_SLICE][P8x8]);
fprintf(p_stat_frm, " %d|",(stats->b8_mode_0_use [B_SLICE][0]+stats->b8_mode_0_use [B_SLICE][1]) - (last_b8_mode_0[B_SLICE][0]+last_b8_mode_0[B_SLICE][1]));
fprintf(p_stat_frm, " %5d|",stats->b8_mode_0_use [B_SLICE][1] - last_b8_mode_0[B_SLICE][1]);
fprintf(p_stat_frm, " %5d|",stats->b8_mode_0_use [B_SLICE][0] - last_b8_mode_0[B_SLICE][0]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[B_SLICE][4 ] - last_mode_use[B_SLICE][4 ]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_8x8[1][4]);
fprintf(p_stat_frm, " %5d|",stats->mode_use_transform_4x4[1][4]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[B_SLICE][5 ] - last_mode_use[B_SLICE][5 ]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[B_SLICE][6 ] - last_mode_use[B_SLICE][6 ]);
fprintf(p_stat_frm, " %5" FORMAT_OFF_T "|",stats->mode_use[B_SLICE][7 ] - last_mode_use[B_SLICE][7 ]);
fprintf(p_stat_frm, "\n");
//save the last results
memcpy(last_mode_use[I_SLICE],stats->mode_use[I_SLICE], MAXMODE * sizeof(int64));
memcpy(last_mode_use[P_SLICE],stats->mode_use[P_SLICE], MAXMODE * sizeof(int64));
memcpy(last_mode_use[B_SLICE],stats->mode_use[B_SLICE], MAXMODE * sizeof(int64));
memset(stats->mode_use_transform_8x8,0, 2 * MAXMODE * sizeof(int));
memset(stats->mode_use_transform_4x4,0, 2 * MAXMODE * sizeof(int));
memcpy(last_b8_mode_0[B_SLICE],stats->b8_mode_0_use[B_SLICE], 2 * sizeof(int));
memcpy(last_mode_chroma_use,stats->intra_chroma_mode, 4 * sizeof(int));
frame_statistic_start = 0;
fclose(p_stat_frm);
}
/*!
************************************************************************
* \brief
* Reports the gathered information to appropriate outputs
* \par Input:
* struct inp_par *inp, \n
* struct img_par *img, \n
* struct stat_par *stats, \n
* struct stat_par *stats \n
*
* \par Output:
* None
************************************************************************
*/
void report()
{
int64 bit_use[NUM_PIC_TYPE][2] ;
int i,j;
char name[30];
int64 total_bits;
float frame_rate;
double mean_motion_info_bit_use[2] = {0.0};
#ifndef WIN32
time_t now;
struct tm *l_time;
char string[1000];
#else
char timebuf[128];
#endif
bit_use[I_SLICE][0] = frame_ctr[I_SLICE];
bit_use[P_SLICE][0] = imax(frame_ctr[P_SLICE] + frame_ctr[SP_SLICE],1);
bit_use[B_SLICE][0] = frame_ctr[B_SLICE];
// Accumulate bit usage for inter and intra frames
for (j=0;j<NUM_PIC_TYPE;j++)
{
bit_use[j][1] = 0;
}
for (j=0;j<NUM_PIC_TYPE;j++)
{
for(i=0; i<MAXMODE; i++)
bit_use[j][1] += stats->bit_use_mode[j][i];
bit_use[j][1]+=stats->bit_use_header[j];
bit_use[j][1]+=stats->bit_use_mb_type[j];
bit_use[j][1]+=stats->tmp_bit_use_cbp[j];
bit_use[j][1]+=stats->bit_use_coeffY[j];
bit_use[j][1]+=stats->bit_use_coeffC[j];
bit_use[j][1]+=stats->bit_use_delta_quant[j];
bit_use[j][1]+=stats->bit_use_stuffingBits[j];
}
frame_rate = (img->framerate *(float)(stats->successive_Bframe + 1)) / (float) (input->jumpd+1);
//! Currently adding NVB bits on P rate. Maybe additional stats info should be created instead and added in log file
stats->bitrate_I = (stats->bit_ctr_I)*(frame_rate)/(float) (input->no_frames + frame_ctr[B_SLICE]);
stats->bitrate_P = (stats->bit_ctr_P)*(frame_rate)/(float) (input->no_frames + frame_ctr[B_SLICE]);
stats->bitrate_B = (stats->bit_ctr_B)*(frame_rate)/(float) (input->no_frames + frame_ctr[B_SLICE]);
fprintf(stdout,"-------------------------------------------------------------------------------\n");
if (input->Verbose != 0)
{
fprintf(stdout, " Freq. for encoded bitstream : %1.0f\n",img->framerate/(float)(input->jumpd+1));
for (i=0; i<3; i++)
{
fprintf(stdout," ME Metric for Refinement Level %1d : %s\n",i,DistortionType[input->MEErrorMetric[i]]);
}
fprintf(stdout," Mode Decision Metric : %s\n",DistortionType[input->ModeDecisionMetric]);
switch ( input->ChromaMEEnable )
{
case 1:
fprintf(stdout," Motion Estimation for components : YCbCr\n");
break;
default:
fprintf(stdout," Motion Estimation for components : Y\n");
break;
}
fprintf(stdout, " Image format : %dx%d\n",input->img_width,input->img_height);
if(input->intra_upd)
fprintf(stdout," Error robustness : On\n");
else
fprintf(stdout," Error robustness : Off\n");
fprintf(stdout, " Search range : %d\n",input->search_range);
fprintf(stdout, " Total number of references : %d\n",input->num_ref_frames);
fprintf(stdout, " References for P slices : %d\n",input->P_List0_refs? input->P_List0_refs:input->num_ref_frames);
if(stats->successive_Bframe != 0)
{
fprintf(stdout," List0 references for B slices : %d\n",input->B_List0_refs? input->B_List0_refs:input->num_ref_frames);
fprintf(stdout," List1 references for B slices : %d\n",input->B_List1_refs? input->B_List1_refs:input->num_ref_frames);
}
// B pictures
fprintf(stdout, " Sequence type :" );
if(stats->successive_Bframe>0 && input->HierarchicalCoding)
{
fprintf(stdout, " Hierarchy (QP: I %d, P %d, B %d) \n",
input->qp0, input->qpN, input->qpB);
}
else if(stats->successive_Bframe>0)
{
char seqtype[80];
int i,j;
strcpy (seqtype,"I");
for (j=0;j<2;j++)
{
for (i=0;i<stats->successive_Bframe;i++)
{
if (input->BRefPictures)
strncat(seqtype,"-RB", imax(0, (int) (79-strlen(seqtype))));
else
strncat(seqtype,"-B", imax(0, (int) (79-strlen(seqtype))));
}
strncat(seqtype,"-P", imax(0, (int) (79-strlen(seqtype))));
}
if (input->BRefPictures)
fprintf(stdout, " %s (QP: I %d, P %d, RB %d) \n", seqtype,input->qp0, input->qpN, iClip3(0,51,input->qpB+input->qpBRSOffset));
else
fprintf(stdout, " %s (QP: I %d, P %d, B %d) \n", seqtype,input->qp0, input->qpN, input->qpB);
}
else if(stats->successive_Bframe==0 && input->sp_periodicity==0) fprintf(stdout, " IPPP (QP: I %d, P %d) \n", input->qp0, input->qpN);
else fprintf(stdout, " I-P-P-SP-P (QP: I %d, P %d, SP (%d, %d)) \n", input->qp0, input->qpN, input->qpsp, input->qpsp_pred);
// report on entropy coding method
if (input->symbol_mode == UVLC)
fprintf(stdout," Entropy coding method : CAVLC\n");
else
fprintf(stdout," Entropy coding method : CABAC\n");
fprintf(stdout, " Profile/Level IDC : (%d,%d)\n",input->ProfileIDC,input->LevelIDC);
if (input->SearchMode==UM_HEX)
fprintf(stdout, " Motion Estimation Scheme : HEX\n");
else if (input->SearchMode==UM_HEX_SIMPLE)
fprintf(stdout, " Motion Estimation Scheme : SHEX\n");
else if (input->SearchMode == EPZS)
{
fprintf(stdout, " Motion Estimation Scheme : EPZS\n");
EPZSOutputStats(stdout, 0);
}
else if (input->SearchMode == FAST_FULL_SEARCH)
fprintf(stdout, " Motion Estimation Scheme : Fast Full Search\n");
else
fprintf(stdout, " Motion Estimation Scheme : Full Search\n");
#ifdef _FULL_SEARCH_RANGE_
if (input->full_search == 2)
fprintf(stdout," Search range restrictions : none\n");
else if (input->full_search == 1)
fprintf(stdout," Search range restrictions : older reference frames\n");
else
fprintf(stdout," Search range restrictions : smaller blocks and older reference frames\n");
#endif
if (input->rdopt)
fprintf(stdout," RD-optimized mode decision : used\n");
else
fprintf(stdout," RD-optimized mode decision : not used\n");
switch(input->partition_mode)
{
case PAR_DP_1:
fprintf(stdout," Data Partitioning Mode : 1 partition \n");
break;
case PAR_DP_3:
fprintf(stdout," Data Partitioning Mode : 3 partitions \n");
break;
default:
fprintf(stdout," Data Partitioning Mode : not supported\n");
break;
}
switch(input->of_mode)
{
case PAR_OF_ANNEXB:
fprintf(stdout," Output File Format : H.264 Bit Stream File Format \n");
break;
case PAR_OF_RTP:
fprintf(stdout," Output File Format : RTP Packet File Format \n");
break;
default:
fprintf(stdout," Output File Format : not supported\n");
break;
}
}
fprintf(stdout,"------------------ Average data all frames -----------------------------------\n");
if (input->Verbose != 0)
{
int impix = input->img_height * input->img_width;
int impix_cr = input->img_height_cr * input->img_width_cr;
unsigned int max_pix_value_sqd = img->max_imgpel_value * img->max_imgpel_value;
unsigned int max_pix_value_sqd_uv = img->max_imgpel_value_uv * img->max_imgpel_value_uv;
float csnr_y = (float) (10 * log10 (max_pix_value_sqd *
(double)((double) impix / (snr->msse_y == 0.0? 1.0 : snr->msse_y))));
float csnr_u = (float) (10 * log10 (max_pix_value_sqd_uv *
(double)((double) impix_cr / (snr->msse_u == 0.0? 1.0 : snr->msse_u))));
float csnr_v = (float) (10 * log10 (max_pix_value_sqd_uv *
(double)((double) impix_cr / (snr->msse_v == 0.0? 1.0 : snr->msse_v))));
fprintf(stdout," PSNR Y(dB) : %5.2f\n",snr->snr_ya);
fprintf(stdout," PSNR U(dB) : %5.2f\n",snr->snr_ua);
fprintf(stdout," PSNR V(dB) : %5.2f\n",snr->snr_va);
fprintf(stdout," cSNR Y(dB) : %5.2f (%5.2f)\n",csnr_y,snr->msse_y/impix);
fprintf(stdout," cSNR U(dB) : %5.2f (%5.2f)\n",csnr_u,snr->msse_u/impix_cr);
fprintf(stdout," cSNR V(dB) : %5.2f (%5.2f)\n",csnr_v,snr->msse_v/impix_cr);
}
if(frame_ctr[B_SLICE]!=0)
{
fprintf(stdout, " Total bits : %" FORMAT_OFF_T " (I %" FORMAT_OFF_T ", P %" FORMAT_OFF_T ", B %" FORMAT_OFF_T " NVB %d) \n",
total_bits=stats->bit_ctr_P + stats->bit_ctr_I + stats->bit_ctr_B + stats->bit_ctr_parametersets,
stats->bit_ctr_I, stats->bit_ctr_P, stats->bit_ctr_B, stats->bit_ctr_parametersets);
frame_rate = (img->framerate *(float)(stats->successive_Bframe + 1)) / (float) (input->jumpd+1);
// stats->bitrate= ((float) total_bits * frame_rate)/((float) (input->no_frames + frame_ctr[B_SLICE]));
stats->bitrate= ((float) total_bits * frame_rate)/((float)(frame_ctr[I_SLICE] + frame_ctr[P_SLICE] + frame_ctr[B_SLICE]));
fprintf(stdout, " Bit rate (kbit/s) @ %2.2f Hz : %5.2f\n", frame_rate, stats->bitrate/1000);
}
else if (input->sp_periodicity==0)
{
fprintf(stdout, " Total bits : %" FORMAT_OFF_T " (I %" FORMAT_OFF_T ", P %" FORMAT_OFF_T ", NVB %d) \n",
total_bits=stats->bit_ctr_P + stats->bit_ctr_I + stats->bit_ctr_parametersets, stats->bit_ctr_I, stats->bit_ctr_P, stats->bit_ctr_parametersets);
frame_rate = img->framerate / ( (float) (input->jumpd + 1) );
stats->bitrate= ((float) total_bits * frame_rate)/((float) input->no_frames );
fprintf(stdout, " Bit rate (kbit/s) @ %2.2f Hz : %5.2f\n", frame_rate, stats->bitrate/1000);
}
else
{
fprintf(stdout, " Total bits : %" FORMAT_OFF_T " (I %" FORMAT_OFF_T ", P %" FORMAT_OFF_T ", NVB %d) \n",
total_bits=stats->bit_ctr_P + stats->bit_ctr_I + stats->bit_ctr_parametersets, stats->bit_ctr_I, stats->bit_ctr_P, stats->bit_ctr_parametersets);
frame_rate = img->framerate / ( (float) (input->jumpd + 1) );
stats->bitrate= ((float) total_bits * frame_rate)/((float) input->no_frames );
fprintf(stdout, " Bit rate (kbit/s) @ %2.2f Hz : %5.2f\n", frame_rate, stats->bitrate/1000);
}
fprintf(stdout, " Bits to avoid Startcode Emulation : %d \n", stats->bit_ctr_emulationprevention);
fprintf(stdout, " Bits for parameter sets : %d \n", stats->bit_ctr_parametersets);
fprintf(stdout,"-------------------------------------------------------------------------------\n");
fprintf(stdout,"Exit JM %s encoder ver %s ", JM, VERSION);
fprintf(stdout,"\n");
// status file
if ((p_stat=fopen("stats.dat","wt"))==0)
{
snprintf(errortext, ET_SIZE, "Error open file %s", "stats.dat");
error(errortext, 500);
}
fprintf(p_stat," -------------------------------------------------------------- \n");
fprintf(p_stat," This file contains statistics for the last encoded sequence \n");
fprintf(p_stat," -------------------------------------------------------------- \n");
fprintf(p_stat, " Sequence : %s\n",input->infile);
fprintf(p_stat, " No.of coded pictures : %4d\n",input->no_frames+frame_ctr[B_SLICE]);
fprintf(p_stat, " Freq. for encoded bitstream : %4.0f\n",frame_rate);
fprintf(p_stat, " I Slice Bitrate(kb/s) : %6.2f\n", stats->bitrate_I/1000);
fprintf(p_stat, " P Slice Bitrate(kb/s) : %6.2f\n", stats->bitrate_P/1000);
// B pictures
if(stats->successive_Bframe != 0)
fprintf(p_stat, " B Slice Bitrate(kb/s) : %6.2f\n", stats->bitrate_B/1000);
fprintf(p_stat, " Total Bitrate(kb/s) : %6.2f\n", stats->bitrate/1000);
for (i=0; i<3; i++)
{
fprintf(p_stat," ME Metric for Refinement Level %1d : %s\n",i,DistortionType[input->MEErrorMetric[i]]);
}
fprintf(p_stat," Mode Decision Metric : %s\n",DistortionType[input->ModeDecisionMetric]);
switch ( input->ChromaMEEnable )
{
case 1:
fprintf(p_stat," Motion Estimation for components : YCbCr\n");
break;
default:
fprintf(p_stat," Motion Estimation for components : Y\n");
break;
}
fprintf(p_stat, " Image format : %dx%d\n",input->img_width,input->img_height);
if(input->intra_upd)
fprintf(p_stat," Error robustness : On\n");
else
fprintf(p_stat," Error robustness : Off\n");
fprintf(p_stat, " Search range : %d\n",input->search_range);
fprintf(p_stat, " Total number of references : %d\n",input->num_ref_frames);
fprintf(p_stat, " References for P slices : %d\n",input->P_List0_refs? input->P_List0_refs:input->num_ref_frames);
if(stats->successive_Bframe != 0)
{
fprintf(p_stat, " List0 refs for B slices : %d\n",input->B_List0_refs? input->B_List0_refs:input->num_ref_frames);
fprintf(p_stat, " List1 refs for B slices : %d\n",input->B_List1_refs? input->B_List1_refs:input->num_ref_frames);
}
if (input->symbol_mode == UVLC)
fprintf(p_stat, " Entropy coding method : CAVLC\n");
else
fprintf(p_stat, " Entropy coding method : CABAC\n");
fprintf(p_stat, " Profile/Level IDC : (%d,%d)\n",input->ProfileIDC,input->LevelIDC);
if(input->MbInterlace)
fprintf(p_stat, " MB Field Coding : On \n");
if (input->SearchMode == EPZS)
EPZSOutputStats(p_stat, 1);
#ifdef _FULL_SEARCH_RANGE_
if (input->full_search == 2)
fprintf(p_stat," Search range restrictions : none\n");
else if (input->full_search == 1)
fprintf(p_stat," Search range restrictions : older reference frames\n");
else
fprintf(p_stat," Search range restrictions : smaller blocks and older reference frames\n");
#endif
if (input->rdopt)
fprintf(p_stat," RD-optimized mode decision : used\n");
else
fprintf(p_stat," RD-optimized mode decision : not used\n");
fprintf(p_stat," ---------------------|----------------|---------------|\n");
fprintf(p_stat," Item | Intra | All frames |\n");
fprintf(p_stat," ---------------------|----------------|---------------|\n");
fprintf(p_stat," SNR Y(dB) |");
fprintf(p_stat," %5.2f |",snr->snr_y1);
fprintf(p_stat," %5.2f |\n",snr->snr_ya);
fprintf(p_stat," SNR U/V (dB) |");
fprintf(p_stat," %5.2f/%5.2f |",snr->snr_u1,snr->snr_v1);
fprintf(p_stat," %5.2f/%5.2f |\n",snr->snr_ua,snr->snr_va);
// QUANT.
fprintf(p_stat," Average quant |");
fprintf(p_stat," %5d |",iabs(input->qp0));
fprintf(p_stat," %5.2f |\n",(float)stats->quant1/dmax(1.0,(float)stats->quant0));
fprintf(p_stat,"\n ---------------------|----------------|---------------|---------------|\n");
fprintf(p_stat," SNR | I | P | B |\n");
fprintf(p_stat," ---------------------|----------------|---------------|---------------|\n");
fprintf(p_stat," SNR Y(dB) | %5.3f | %5.3f | %5.3f |\n",
snr->snr_yt[I_SLICE],snr->snr_yt[P_SLICE],snr->snr_yt[B_SLICE]);
fprintf(p_stat," SNR U(dB) | %5.3f | %5.3f | %5.3f |\n",
snr->snr_ut[I_SLICE],snr->snr_ut[P_SLICE],snr->snr_ut[B_SLICE]);
fprintf(p_stat," SNR V(dB) | %5.3f | %5.3f | %5.3f |\n",
snr->snr_vt[I_SLICE],snr->snr_vt[P_SLICE],snr->snr_vt[B_SLICE]);
// MODE
fprintf(p_stat,"\n ---------------------|----------------|\n");
fprintf(p_stat," Intra | Mode used |\n");
fprintf(p_stat," ---------------------|----------------|\n");
fprintf(p_stat," Mode 0 intra 4x4 | %5" FORMAT_OFF_T " |\n",stats->mode_use[I_SLICE][I4MB ]);
fprintf(p_stat," Mode 1 intra 8x8 | %5" FORMAT_OFF_T " |\n",stats->mode_use[I_SLICE][I8MB ]);
fprintf(p_stat," Mode 2+ intra 16x16 | %5" FORMAT_OFF_T " |\n",stats->mode_use[I_SLICE][I16MB]);
fprintf(p_stat," Mode intra IPCM | %5" FORMAT_OFF_T " |\n",stats->mode_use[I_SLICE][IPCM ]);
fprintf(p_stat,"\n ---------------------|----------------|-----------------|\n");
fprintf(p_stat," Inter | Mode used | MotionInfo bits |\n");
fprintf(p_stat," ---------------------|----------------|-----------------|");
fprintf(p_stat,"\n Mode 0 (copy) | %5" FORMAT_OFF_T " | %8.2f |",stats->mode_use[P_SLICE][0 ],(double)stats->bit_use_mode[P_SLICE][0 ]/(double)bit_use[P_SLICE][0]);
fprintf(p_stat,"\n Mode 1 (16x16) | %5" FORMAT_OFF_T " | %8.2f |",stats->mode_use[P_SLICE][1 ],(double)stats->bit_use_mode[P_SLICE][1 ]/(double)bit_use[P_SLICE][0]);
fprintf(p_stat,"\n Mode 2 (16x8) | %5" FORMAT_OFF_T " | %8.2f |",stats->mode_use[P_SLICE][2 ],(double)stats->bit_use_mode[P_SLICE][2 ]/(double)bit_use[P_SLICE][0]);
fprintf(p_stat,"\n Mode 3 (8x16) | %5" FORMAT_OFF_T " | %8.2f |",stats->mode_use[P_SLICE][3 ],(double)stats->bit_use_mode[P_SLICE][3 ]/(double)bit_use[P_SLICE][0]);
fprintf(p_stat,"\n Mode 4 (8x8) | %5" FORMAT_OFF_T " | %8.2f |",stats->mode_use[P_SLICE][P8x8],(double)stats->bit_use_mode[P_SLICE][P8x8]/(double)bit_use[P_SLICE][0]);
fprintf(p_stat,"\n Mode 5 intra 4x4 | %5" FORMAT_OFF_T " |-----------------|",stats->mode_use[P_SLICE][I4MB]);
fprintf(p_stat,"\n Mode 6 intra 8x8 | %5" FORMAT_OFF_T " |",stats->mode_use[P_SLICE][I8MB]);
fprintf(p_stat,"\n Mode 7+ intra 16x16 | %5" FORMAT_OFF_T " |",stats->mode_use[P_SLICE][I16MB]);
fprintf(p_stat,"\n Mode intra IPCM | %5" FORMAT_OFF_T " |",stats->mode_use[P_SLICE][IPCM ]);
mean_motion_info_bit_use[0] = (double)(stats->bit_use_mode[P_SLICE][0] + stats->bit_use_mode[P_SLICE][1] + stats->bit_use_mode[P_SLICE][2]
+ stats->bit_use_mode[P_SLICE][3] + stats->bit_use_mode[P_SLICE][P8x8])/(double) bit_use[P_SLICE][0];
// B pictures
if(stats->successive_Bframe!=0 && frame_ctr[B_SLICE]!=0)
{
fprintf(p_stat,"\n\n ---------------------|----------------|-----------------|\n");
fprintf(p_stat," B frame | Mode used | MotionInfo bits |\n");
fprintf(p_stat," ---------------------|----------------|-----------------|");
fprintf(p_stat,"\n Mode 0 (copy) | %5" FORMAT_OFF_T " | %8.2f |",stats->mode_use[B_SLICE][0 ],(double)stats->bit_use_mode[B_SLICE][0 ]/(double)frame_ctr[B_SLICE]);
fprintf(p_stat,"\n Mode 1 (16x16) | %5" FORMAT_OFF_T " | %8.2f |",stats->mode_use[B_SLICE][1 ],(double)stats->bit_use_mode[B_SLICE][1 ]/(double)frame_ctr[B_SLICE]);
fprintf(p_stat,"\n Mode 2 (16x8) | %5" FORMAT_OFF_T " | %8.2f |",stats->mode_use[B_SLICE][2 ],(double)stats->bit_use_mode[B_SLICE][2 ]/(double)frame_ctr[B_SLICE]);
fprintf(p_stat,"\n Mode 3 (8x16) | %5" FORMAT_OFF_T " | %8.2f |",stats->mode_use[B_SLICE][3 ],(double)stats->bit_use_mode[B_SLICE][3 ]/(double)frame_ctr[B_SLICE]);
fprintf(p_stat,"\n Mode 4 (8x8) | %5" FORMAT_OFF_T " | %8.2f |",stats->mode_use[B_SLICE][P8x8],(double)stats->bit_use_mode[B_SLICE][P8x8]/(double)frame_ctr[B_SLICE]);
fprintf(p_stat,"\n Mode 5 intra 4x4 | %5" FORMAT_OFF_T " |-----------------|",stats->mode_use[B_SLICE][I4MB]);
fprintf(p_stat,"\n Mode 6 intra 8x8 | %5" FORMAT_OFF_T " |",stats->mode_use[B_SLICE][I8MB]);
fprintf(p_stat,"\n Mode 7+ intra 16x16 | %5" FORMAT_OFF_T " |",stats->mode_use[B_SLICE][I16MB]);
fprintf(p_stat,"\n Mode intra IPCM | %5" FORMAT_OFF_T " |",stats->mode_use[B_SLICE][IPCM ]);
mean_motion_info_bit_use[1] = (double)(stats->bit_use_mode[B_SLICE][0] + stats->bit_use_mode[B_SLICE][1] + stats->bit_use_mode[B_SLICE][2]
+ stats->bit_use_mode[B_SLICE][3] + stats->bit_use_mode[B_SLICE][P8x8])/(double) frame_ctr[B_SLICE];
}
fprintf(p_stat,"\n\n ---------------------|----------------|----------------|----------------|\n");
fprintf(p_stat," Bit usage: | Intra | Inter | B frame |\n");
fprintf(p_stat," ---------------------|----------------|----------------|----------------|\n");
fprintf(p_stat," Header |");
fprintf(p_stat," %10.2f |",(float) stats->bit_use_header[I_SLICE]/bit_use[I_SLICE][0]);
fprintf(p_stat," %10.2f |",(float) stats->bit_use_header[P_SLICE]/bit_use[P_SLICE][0]);
if(stats->successive_Bframe!=0 && frame_ctr[B_SLICE]!=0)
fprintf(p_stat," %10.2f |",(float) stats->bit_use_header[B_SLICE]/frame_ctr[B_SLICE]);
else fprintf(p_stat," %10.2f |", 0.);
fprintf(p_stat,"\n");
fprintf(p_stat," Mode |");
fprintf(p_stat," %10.2f |",(float)stats->bit_use_mb_type[I_SLICE]/bit_use[I_SLICE][0]);
fprintf(p_stat," %10.2f |",(float)stats->bit_use_mb_type[P_SLICE]/bit_use[P_SLICE][0]);
if(stats->successive_Bframe!=0 && frame_ctr[B_SLICE]!=0)
fprintf(p_stat," %10.2f |",(float)stats->bit_use_mb_type[B_SLICE]/frame_ctr[B_SLICE]);
else fprintf(p_stat," %10.2f |", 0.);
fprintf(p_stat,"\n");
fprintf(p_stat," Motion Info |");
fprintf(p_stat," ./. |");
fprintf(p_stat," %10.2f |",mean_motion_info_bit_use[0]);
if(stats->successive_Bframe!=0 && frame_ctr[B_SLICE]!=0)
fprintf(p_stat," %10.2f |",mean_motion_info_bit_use[1]);
else fprintf(p_stat," %10.2f |", 0.);
fprintf(p_stat,"\n");
fprintf(p_stat," CBP Y/C |");
fprintf(p_stat," %10.2f |", (float)stats->tmp_bit_use_cbp[I_SLICE]/bit_use[I_SLICE][0]);
fprintf(p_stat," %10.2f |", (float)stats->tmp_bit_use_cbp[P_SLICE]/bit_use[P_SLICE][0]);
if(stats->successive_Bframe!=0 && bit_use[B_SLICE][0]!=0)
fprintf(p_stat," %10.2f |", (float)stats->tmp_bit_use_cbp[B_SLICE]/bit_use[B_SLICE][0]);
else fprintf(p_stat," %10.2f |", 0.);
fprintf(p_stat,"\n");
if(stats->successive_Bframe!=0 && frame_ctr[B_SLICE]!=0)
fprintf(p_stat," Coeffs. Y | %10.2f | %10.2f | %10.2f |\n",
(float)stats->bit_use_coeffY[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_coeffY[P_SLICE]/bit_use[P_SLICE][0], (float)stats->bit_use_coeffY[B_SLICE]/frame_ctr[B_SLICE]);
else
fprintf(p_stat," Coeffs. Y | %10.2f | %10.2f | %10.2f |\n",
(float)stats->bit_use_coeffY[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_coeffY[P_SLICE]/(float)bit_use[P_SLICE][0], 0.);
if(stats->successive_Bframe!=0 && frame_ctr[B_SLICE]!=0)
fprintf(p_stat," Coeffs. C | %10.2f | %10.2f | %10.2f |\n",
(float)stats->bit_use_coeffC[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_coeffC[P_SLICE]/bit_use[P_SLICE][0], (float)stats->bit_use_coeffC[B_SLICE]/frame_ctr[B_SLICE]);
else
fprintf(p_stat," Coeffs. C | %10.2f | %10.2f | %10.2f |\n",
(float)stats->bit_use_coeffC[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_coeffC[P_SLICE]/bit_use[P_SLICE][0], 0.);
if(stats->successive_Bframe!=0 && frame_ctr[B_SLICE]!=0)
fprintf(p_stat," Delta quant | %10.2f | %10.2f | %10.2f |\n",
(float)stats->bit_use_delta_quant[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_delta_quant[P_SLICE]/bit_use[P_SLICE][0], (float)stats->bit_use_delta_quant[B_SLICE]/frame_ctr[B_SLICE]);
else
fprintf(p_stat," Delta quant | %10.2f | %10.2f | %10.2f |\n",
(float)stats->bit_use_delta_quant[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_delta_quant[P_SLICE]/bit_use[P_SLICE][0], 0.);
if(stats->successive_Bframe!=0 && frame_ctr[B_SLICE]!=0)
fprintf(p_stat," Stuffing Bits | %10.2f | %10.2f | %10.2f |\n",
(float)stats->bit_use_stuffingBits[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_stuffingBits[P_SLICE]/bit_use[P_SLICE][0], (float)stats->bit_use_stuffingBits[B_SLICE]/frame_ctr[B_SLICE]);
else
fprintf(p_stat," Stuffing Bits | %10.2f | %10.2f | %10.2f |\n",
(float)stats->bit_use_stuffingBits[I_SLICE]/bit_use[I_SLICE][0], (float)stats->bit_use_stuffingBits[P_SLICE]/bit_use[P_SLICE][0], 0.);
fprintf(p_stat," ---------------------|----------------|----------------|----------------|\n");
fprintf(p_stat," average bits/frame |");
fprintf(p_stat," %10.2f |", (float) bit_use[I_SLICE][1]/(float) bit_use[I_SLICE][0] );
fprintf(p_stat," %10.2f |", (float) bit_use[P_SLICE][1]/(float) bit_use[P_SLICE][0] );
if(stats->successive_Bframe!=0 && frame_ctr[B_SLICE]!=0)
fprintf(p_stat," %10.2f |", (float) bit_use[B_SLICE][1]/ (float) frame_ctr[B_SLICE] );
else fprintf(p_stat," %10.2f |", 0.);
fprintf(p_stat,"\n");
fprintf(p_stat," ---------------------|----------------|----------------|----------------|\n");
fclose(p_stat);
// write to log file
if ((p_log=fopen("log.dat","r"))==0) // check if file exist
{
if ((p_log=fopen("log.dat","a"))==NULL) // append new statistic at the end
{
snprintf(errortext, ET_SIZE, "Error open file %s \n","log.dat");
error(errortext, 500);
}
else // Create header for new log file
{
fprintf(p_log," ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ \n");
fprintf(p_log,"| Encoder statistics. This file is generated during first encoding session, new sessions will be appended |\n");
fprintf(p_log," ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ \n");
fprintf(p_log,"| ver | Date | Time | Sequence | #Img |P/MbInt| QPI| QPP| QPB| Format |Iperiod| #B | FMES | Hdmd | S.R |#Ref | Freq |Coding|RD-opt|Intra upd|8x8Tr| SNRY 1| SNRU 1| SNRV 1| SNRY N| SNRU N| SNRV N|#Bitr I|#Bitr P|#Bitr B|#Bitr IPB| Total Time | Me Time |\n");
fprintf(p_log," ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ \n");
}
}
else
{
fclose (p_log);
if ((p_log=fopen("log.dat","a"))==NULL) // File exist,just open for appending
{
snprintf(errortext, ET_SIZE, "Error open file %s \n","log.dat");
error(errortext, 500);
}
}
fprintf(p_log,"|%s/%-4s", VERSION, EXT_VERSION);
#ifdef WIN32
_strdate( timebuf );
fprintf(p_log,"| %1.5s |",timebuf );
_strtime( timebuf);
fprintf(p_log," % 1.5s |",timebuf);
#else
now = time ((time_t *) NULL); // Get the system time and put it into 'now' as 'calender time'
time (&now);
l_time = localtime (&now);
strftime (string, sizeof string, "%d-%b-%Y", l_time);
fprintf(p_log,"| %1.5s |",string );
strftime (string, sizeof string, "%H:%M:%S", l_time);
fprintf(p_log," %1.5s |",string );
#endif
for (i=0;i<30;i++)
name[i]=input->infile[i + imax(0,((int) strlen(input->infile))-30)]; // write last part of path, max 20 chars
fprintf(p_log,"%30.30s|",name);
fprintf(p_log,"%5d |",input->no_frames);
fprintf(p_log," %d/%d |",input->PicInterlace, input->MbInterlace);
fprintf(p_log," %-3d|",input->qp0);
fprintf(p_log," %-3d|",input->qpN);
fprintf(p_log," %-3d|",input->qpB);
fprintf(p_log,"%4dx%-4d|",input->img_width,input->img_height);
fprintf(p_log," %3d |",input->intra_period);
fprintf(p_log,"%3d |",stats->successive_Bframe);
if (input->SearchMode == UM_HEX)
fprintf(p_log," HEX |");
else if (input->SearchMode == UM_HEX_SIMPLE)
fprintf(p_log," SHEX |");
else if (input->SearchMode == EPZS)
fprintf(p_log," EPZS |");
else if (input->SearchMode == FAST_FULL_SEARCH)
fprintf(p_log," FFS |");
else
fprintf(p_log," FS |");
fprintf(p_log," %1d%1d%1d |", input->MEErrorMetric[F_PEL], input->MEErrorMetric[H_PEL], input->MEErrorMetric[Q_PEL]);
fprintf(p_log," %3d |",input->search_range );
fprintf(p_log," %2d |",input->num_ref_frames);
fprintf(p_log," %5.2f|",(img->framerate *(float) (stats->successive_Bframe + 1)) / (float)(input->jumpd+1));
if (input->symbol_mode == UVLC)
fprintf(p_log," CAVLC|");
else
fprintf(p_log," CABAC|");
fprintf(p_log," %d |",input->rdopt);
if (input->intra_upd==1)
fprintf(p_log," ON |");
else
fprintf(p_log," OFF |");
fprintf(p_log," %d |",input->Transform8x8Mode);
fprintf(p_log,"%7.3f|",snr->snr_y1);
fprintf(p_log,"%7.3f|",snr->snr_u1);
fprintf(p_log,"%7.3f|",snr->snr_v1);
fprintf(p_log,"%7.3f|",snr->snr_ya);
fprintf(p_log,"%7.3f|",snr->snr_ua);
fprintf(p_log,"%7.3f|",snr->snr_va);
/*
fprintf(p_log,"%-5.3f|",snr->snr_yt[I_SLICE]);
fprintf(p_log,"%-5.3f|",snr->snr_ut[I_SLICE]);
fprintf(p_log,"%-5.3f|",snr->snr_vt[I_SLICE]);
fprintf(p_log,"%-5.3f|",snr->snr_yt[P_SLICE]);
fprintf(p_log,"%-5.3f|",snr->snr_ut[P_SLICE]);
fprintf(p_log,"%-5.3f|",snr->snr_vt[P_SLICE]);
fprintf(p_log,"%-5.3f|",snr->snr_yt[B_SLICE]);
fprintf(p_log,"%-5.3f|",snr->snr_ut[B_SLICE]);
fprintf(p_log,"%-5.3f|",snr->snr_vt[B_SLICE]);
*/
fprintf(p_log,"%7.0f|",stats->bitrate_I);
fprintf(p_log,"%7.0f|",stats->bitrate_P);
fprintf(p_log,"%7.0f|",stats->bitrate_B);
fprintf(p_log,"%9.0f|",stats->bitrate);
fprintf(p_log," %12d |", (int)tot_time);
fprintf(p_log," %12d |", (int)me_tot_time);
fprintf(p_log,"\n");
fclose(p_log);
p_log=fopen("data.txt","a");
if(stats->successive_Bframe != 0 && frame_ctr[B_SLICE] != 0) // B picture used
{
fprintf(p_log, "%3d %2d %2d %2.2f %2.2f %2.2f %5" FORMAT_OFF_T " "
"%2.2f %2.2f %2.2f %5d "
"%2.2f %2.2f %2.2f %5" FORMAT_OFF_T " %5" FORMAT_OFF_T " %.3f\n",
input->no_frames, input->qp0, input->qpN,
snr->snr_y1,
snr->snr_u1,
snr->snr_v1,
stats->bit_ctr_I,
0.0,
0.0,
0.0,
0,
snr->snr_ya,
snr->snr_ua,
snr->snr_va,
(stats->bit_ctr_I+stats->bit_ctr)/(input->no_frames+frame_ctr[B_SLICE]),
stats->bit_ctr_B/frame_ctr[B_SLICE],
(double)0.001*tot_time/(input->no_frames+frame_ctr[B_SLICE]));
}
else
{
if (input->no_frames!=0)
fprintf(p_log, "%3d %2d %2d %2.2f %2.2f %2.2f %5" FORMAT_OFF_T " "
"%2.2f %2.2f %2.2f %5d "
"%2.2f %2.2f %2.2f %5" FORMAT_OFF_T " %5d %.3f\n",
input->no_frames, input->qp0, input->qpN,
snr->snr_y1,
snr->snr_u1,
snr->snr_v1,
stats->bit_ctr_I,
0.0,
0.0,
0.0,
0,
snr->snr_ya,
snr->snr_ua,
snr->snr_va,
(stats->bit_ctr_I+stats->bit_ctr)/input->no_frames,
0,
(double)0.001*tot_time/input->no_frames);
}
fclose(p_log);
if (input->ReportFrameStats)
{
if ((p_log=fopen("stat_frame.dat","a"))==NULL) // append new statistic at the end
{
snprintf(errortext, ET_SIZE, "Error open file %s \n","stat_frame.dat.dat");
// error(errortext, 500);
}
else
{
fprintf(p_log," --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \n");
fclose(p_log);
}
}
}
/*!
************************************************************************
* \brief
* Prints the header of the protocol.
* \par Input:
* struct inp_par *inp
* \par Output:
* none
************************************************************************
*/
void information_init(void)
{
char yuv_types[4][10]= {"YUV 4:0:0","YUV 4:2:0","YUV 4:2:2","YUV 4:4:4"};
if (input->Verbose == 0 || input->Verbose == 1)
printf("------------------------------- JM %s %s --------------------------------\n",VERSION, EXT_VERSION);
else
printf("------------------------------- JM %s %s ------------------------------------------\n",VERSION, EXT_VERSION);
printf(" Input YUV file : %s \n",mybasename(input->infile));
printf(" Output H.264 bitstream : %s \n",input->outfile);
if (p_dec != -1)
printf(" Output YUV file : %s \n",input->ReconFile);
printf(" YUV Format : %s \n", &yuv_types[img->yuv_format][0]);//img->yuv_format==YUV422?"YUV 4:2:2":(img->yuv_format==YUV444)?"YUV 4:4:4":"YUV 4:2:0");
printf(" Frames to be encoded I-P/B : %d/%d\n", input->no_frames, (input->successive_Bframe*(input->no_frames-1)));
printf(" PicInterlace / MbInterlace : %d/%d\n", input->PicInterlace, input->MbInterlace);
printf(" Transform8x8Mode : %d\n", input->Transform8x8Mode);
switch (input->Verbose)
{
case 1:
printf("-------------------------------------------------------------------------------\n");
printf(" Frame Bit/pic QP SnrY SnrU SnrV Time(ms) MET(ms) Frm/Fld Ref \n");
printf("-------------------------------------------------------------------------------\n");
break;
case 2:
printf("---------------------------------------------------------------------------------------------\n");
printf(" Frame Bit/pic WP QP SnrY SnrU SnrV Time(ms) MET(ms) Frm/Fld I D L0 L1 RDP Ref\n");
printf("---------------------------------------------------------------------------------------------\n");
break;
case 0:
default:
printf("-------------------------------------------------------------------------------\n");
printf("\nEncoding. Please Wait.\n\n");
break;
}
}
/*!
************************************************************************
* \brief
* memory allocation for original picture buffers
************************************************************************
*/
int init_orig_buffers(void)
{
int memory_size = 0;
// allocate memory for reference frame buffers: imgY_org_frm, imgUV_org_frm
memory_size += get_mem2Dpel(&imgY_org_frm, img->height, img->width);
if (img->yuv_format != YUV400)
memory_size += get_mem3Dpel(&imgUV_org_frm, 2, img->height_cr, img->width_cr);
if(!active_sps->frame_mbs_only_flag)
{
// allocate memory for reference frame buffers: imgY_org, imgUV_org
init_top_bot_planes(imgY_org_frm, img->height, img->width, &imgY_org_top, &imgY_org_bot);
if (img->yuv_format != YUV400)
{
if(((imgUV_org_top) = (imgpel***)calloc(2,sizeof(imgpel**))) == NULL)
no_mem_exit("init_global_buffers: imgUV_org_top");
if(((imgUV_org_bot) = (imgpel***)calloc(2,sizeof(imgpel**))) == NULL)
no_mem_exit("init_global_buffers: imgUV_org_bot");
memory_size += 4*(sizeof(imgpel**));
memory_size += init_top_bot_planes(imgUV_org_frm[0], img->height_cr, img->width_cr, &(imgUV_org_top[0]), &(imgUV_org_bot[0]));
memory_size += init_top_bot_planes(imgUV_org_frm[1], img->height_cr, img->width_cr, &(imgUV_org_top[1]), &(imgUV_org_bot[1]));
}
}
return memory_size;
}
/*!
************************************************************************
* \brief
* Dynamic memory allocation of frame size related global buffers
* buffers are defined in global.h, allocated memory must be freed in
* void free_global_buffers()
* \par Input:
* Input Parameters struct inp_par *inp, \n
* Image Parameters struct img_par *img
* \return Number of allocated bytes
************************************************************************
*/
int init_global_buffers(void)
{
int j,memory_size=0;
#ifdef _ADAPT_LAST_GROUP_
extern int *last_P_no_frm;
extern int *last_P_no_fld;
if ((last_P_no_frm = (int*)malloc(2*img->max_num_references*sizeof(int))) == NULL)
no_mem_exit("init_global_buffers: last_P_no");
if(!active_sps->frame_mbs_only_flag)
if ((last_P_no_fld = (int*)malloc(4*img->max_num_references*sizeof(int))) == NULL)
no_mem_exit("init_global_buffers: last_P_no");
#endif
memory_size += init_orig_buffers();
memory_size += get_mem2Dint(&PicPos,img->FrameSizeInMbs + 1,2);
for (j=0;j< (int) img->FrameSizeInMbs + 1;j++)
{
PicPos[j][0] = (j % img->PicWidthInMbs);
PicPos[j][1] = (j / img->PicWidthInMbs);
}
if (input->WeightedPrediction || input->WeightedBiprediction || input->GenerateMultiplePPS)
{
// Currently only use up to 20 references. Need to use different indicator such as maximum num of references in list
memory_size += get_mem3Dint(&wp_weight,6,MAX_REFERENCE_PICTURES,3);
memory_size += get_mem3Dint(&wp_offset,6,MAX_REFERENCE_PICTURES,3);
memory_size += get_mem4Dint(&wbp_weight, 6, MAX_REFERENCE_PICTURES, MAX_REFERENCE_PICTURES, 3);
}
// allocate memory for reference frames of each block: refFrArr
if(input->successive_Bframe!=0 || input->BRefPictures> 0)
{
memory_size += get_mem3D((byte ****)(void*)(&direct_ref_idx), 2, img->height_blk, img->width_blk);
memory_size += get_mem2D((byte ***)(void*)&direct_pdir, img->height_blk, img->width_blk);
}
if (input->rdopt==3)
{
memory_size += get_mem2Dint(&decs->resY, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
if ((decs->decref = (imgpel****) calloc(input->NoOfDecoders,sizeof(imgpel***))) == NULL)
no_mem_exit("init_global_buffers: decref");
for (j=0 ; j<input->NoOfDecoders; j++)
{
memory_size += get_mem3Dpel(&decs->decref[j], img->max_num_references+1, img->height, img->width);
}
memory_size += get_mem2Dpel(&decs->RefBlock, BLOCK_SIZE,BLOCK_SIZE);
memory_size += get_mem3Dpel(&decs->decY, input->NoOfDecoders, img->height, img->width);
memory_size += get_mem3Dpel(&decs->decY_best, input->NoOfDecoders, img->height, img->width);
memory_size += get_mem2D(&decs->status_map, img->FrameHeightInMbs, img->PicWidthInMbs);
memory_size += get_mem2D(&decs->dec_mb_mode,img->FrameHeightInMbs, img->PicWidthInMbs);
}
if (input->RestrictRef)
{
memory_size += get_mem2D(&pixel_map, img->height,img->width);
memory_size += get_mem2D(&refresh_map, img->height/8,img->width/8);
}
if(!active_sps->frame_mbs_only_flag)
{
memory_size += get_mem2Dpel(&imgY_com, img->height, img->width);
if (img->yuv_format != YUV400)
{
memory_size += get_mem3Dpel(&imgUV_com, 2, img->height_cr, img->width_cr);
}
}
// allocate and set memory relating to motion estimation
if (input->SearchMode == UM_HEX)
{
memory_size += UMHEX_get_mem();
}
else if (input->SearchMode == UM_HEX_SIMPLE)
{
smpUMHEX_init();
memory_size += smpUMHEX_get_mem();
}
else if (input->SearchMode == EPZS)
memory_size += EPZSInit();
if (input->RCEnable)
{
generic_alloc( &generic_RC );
rc_alloc( &quadratic_RC );
// RDPictureDecision
if ( input->RDPictureDecision || input->MbInterlace == ADAPTIVE_CODING )
{
// INIT
generic_alloc( &generic_RC_init );
rc_alloc( &quadratic_RC_init );
// BEST
generic_alloc( &generic_RC_best );
rc_alloc( &quadratic_RC_best );
}
}
if(input->redundant_pic_flag)
{
memory_size += get_mem2Dpel(&imgY_tmp, img->height, input->img_width);
memory_size += get_mem2Dpel(&imgUV_tmp[0], input->img_height/2, input->img_width/2);
memory_size += get_mem2Dpel(&imgUV_tmp[1], input->img_height/2, input->img_width/2);
}
memory_size += get_mem2Dint (&imgY_sub_tmp, img->height_padded, img->width_padded);
img_padded_size_x = (img->width + 2 * IMG_PAD_SIZE);
img_cr_padded_size_x = (img->width_cr + 2 * img_pad_size_uv_x);
return (memory_size);
}
/*!
************************************************************************
* \brief
* Free allocated memory of original picture buffers
************************************************************************
*/
void free_orig_planes(void)
{
free_mem2Dpel(imgY_org_frm); // free ref frame buffers
if (img->yuv_format != YUV400)
free_mem3Dpel(imgUV_org_frm, 2);
if(!active_sps->frame_mbs_only_flag)
{
free_top_bot_planes(imgY_org_top, imgY_org_bot);
if (img->yuv_format != YUV400)
{
free_top_bot_planes(imgUV_org_top[0], imgUV_org_bot[0]);
free_top_bot_planes(imgUV_org_top[1], imgUV_org_bot[1]);
free (imgUV_org_top);
free (imgUV_org_bot);
}
}
}
/*!
************************************************************************
* \brief
* Free allocated memory of frame size related global buffers
* buffers are defined in global.h, allocated memory is allocated in
* int get_mem4global_buffers()
* \par Input:
* Input Parameters struct inp_par *inp, \n
* Image Parameters struct img_par *img
* \par Output:
* none
************************************************************************
*/
void free_global_buffers(void)
{
int i,j;
#ifdef _ADAPT_LAST_GROUP_
extern int *last_P_no_frm;
extern int *last_P_no_fld;
free (last_P_no_frm);
free (last_P_no_fld);
#endif
free_orig_planes();
// free lookup memory which helps avoid divides with PicWidthInMbs
free_mem2Dint(PicPos);
// Free Qmatrices and offsets
free_QMatrix();
free_QOffsets();
if (input->WeightedPrediction || input->WeightedBiprediction || input->GenerateMultiplePPS)
{
free_mem3Dint(wp_weight,6);
free_mem3Dint(wp_offset,6);
free_mem4Dint(wbp_weight,6,MAX_REFERENCE_PICTURES);
}
if(stats->successive_Bframe!=0 || input->BRefPictures> 0)
{
free_mem3D((byte ***)direct_ref_idx,2);
free_mem2D((byte **) direct_pdir);
} // end if B frame
if (imgY_sub_tmp) // free temp quarter pel frame buffers
{
free_mem2Dint (imgY_sub_tmp);
imgY_sub_tmp=NULL;
}
// free mem, allocated in init_img()
// free intra pred mode buffer for blocks
free_mem2D((byte**)img->ipredmode);
free_mem2D((byte**)img->ipredmode8x8);
free(img->mb_data);
free_mem2D((byte**)rddata_top_frame_mb.ipredmode);
if(input->UseConstrainedIntraPred)
{
free (img->intra_block);
}
if (input->CtxAdptLagrangeMult == 1)
{
free(mb16x16_cost_frame);
}
if (input->rdopt==3)
{
free(decs->resY[0]);
free(decs->resY);
free(decs->RefBlock[0]);
free(decs->RefBlock);
for (j=0; j<input->NoOfDecoders; j++)
{
free(decs->decY[j][0]);
free(decs->decY[j]);
free(decs->decY_best[j][0]);
free(decs->decY_best[j]);
for (i=0; i<img->max_num_references+1; i++)
{
free(decs->decref[j][i][0]);
free(decs->decref[j][i]);
}
free(decs->decref[j]);
}
free(decs->decY);
free(decs->decY_best);
free(decs->decref);
free(decs->status_map[0]);
free(decs->status_map);
free(decs->dec_mb_mode[0]);
free(decs->dec_mb_mode);
}
if (input->RestrictRef)
{
free(pixel_map[0]);
free(pixel_map);
free(refresh_map[0]);
free(refresh_map);
}
if(!active_sps->frame_mbs_only_flag)
{
free_mem2Dpel(imgY_com);
if (img->yuv_format != YUV400)
{
free_mem3Dpel(imgUV_com,2);
}
}
free_mem3Dint(img->nz_coeff, img->FrameSizeInMbs);
free_mem2Ddb_offset (img->lambda_md, img->bitdepth_luma_qp_scale);
free_mem3Ddb_offset (img->lambda_me, 10, 52 + img->bitdepth_luma_qp_scale, img->bitdepth_luma_qp_scale);
free_mem3Dint_offset(img->lambda_mf, 10, 52 + img->bitdepth_luma_qp_scale, img->bitdepth_luma_qp_scale);
if (input->CtxAdptLagrangeMult == 1)
{
free_mem2Ddb_offset(img->lambda_mf_factor,img->bitdepth_luma_qp_scale);
}
if(input->SearchMode == UM_HEX)
{
UMHEX_free_mem();
}
else if (input->SearchMode == UM_HEX_SIMPLE)
{
smpUMHEX_free_mem();
}
else if (input->SearchMode == EPZS)
{
EPZSDelete();
}
if (input->RCEnable)
{
generic_free( &generic_RC );
rc_free( &quadratic_RC );
// RDPictureDecision
if ( input->RDPictureDecision || input->MbInterlace == ADAPTIVE_CODING )
{
// INIT
generic_free( &generic_RC_init );
rc_free( &quadratic_RC_init );
// BEST
generic_free( &generic_RC_best );
rc_free( &quadratic_RC_best );
}
}
if(input->redundant_pic_flag)
{
free_mem2Dpel(imgY_tmp);
free_mem2Dpel(imgUV_tmp[0]);
free_mem2Dpel(imgUV_tmp[1]);
}
}
/*!
************************************************************************
* \brief
* Allocate memory for mv
* \par Input:
* Image Parameters struct img_par *img \n
* int****** mv
* \return memory size in bytes
************************************************************************
*/
int get_mem_mv (short ******* mv)
{
int i, j, k, l, m;
if ((*mv = (short******)calloc(4,sizeof(short*****))) == NULL)
no_mem_exit ("get_mem_mv: mv");
for (i=0; i<4; i++)
{
if (((*mv)[i] = (short*****)calloc(4,sizeof(short****))) == NULL)
no_mem_exit ("get_mem_mv: mv");
for (j=0; j<4; j++)
{
if (((*mv)[i][j] = (short****)calloc(2,sizeof(short***))) == NULL)
no_mem_exit ("get_mem_mv: mv");
for (k=0; k<2; k++)
{
if (((*mv)[i][j][k] = (short***)calloc(img->max_num_references,sizeof(short**))) == NULL)
no_mem_exit ("get_mem_mv: mv");
for (l=0; l<img->max_num_references; l++)
{
if (((*mv)[i][j][k][l] = (short**)calloc(9,sizeof(short*))) == NULL)
no_mem_exit ("get_mem_mv: mv");
if (((*mv)[i][j][k][l][0] = (short*)calloc(2*9,sizeof(short))) == NULL)
no_mem_exit ("get_mem_mv: mv");
for (m=1; m<9; m++)
(*mv)[i][j][k][l][m] = (*mv)[i][j][k][l][m - 1] + 2;
}
}
}
}
return 4*4*img->max_num_references*9*2*sizeof(short);
}
/*!
************************************************************************
* \brief
* Free memory from mv
* \par Input:
* int****** mv
************************************************************************
*/
void free_mem_mv (short****** mv)
{
int i, j, k, l;
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
for (k=0; k<2; k++)
{
for (l=0; l<img->max_num_references; l++)
{
free (mv[i][j][k][l][0]);
free (mv[i][j][k][l]);
}
free (mv[i][j][k]);
}
free (mv[i][j]);
}
free (mv[i]);
}
free (mv);
}
/*!
************************************************************************
* \brief
* Allocate memory for AC coefficients
************************************************************************
*/
int get_mem_ACcoeff (int***** cofAC)
{
int i, j, k;
int num_blk8x8 = 4 + img->num_blk8x8_uv;
if ((*cofAC = (int****)calloc (num_blk8x8, sizeof(int***))) == NULL) no_mem_exit ("get_mem_ACcoeff: cofAC");
for (k=0; k<num_blk8x8; k++)
{
if (((*cofAC)[k] = (int***)calloc (4, sizeof(int**))) == NULL) no_mem_exit ("get_mem_ACcoeff: cofAC");
for (j=0; j<4; j++)
{
if (((*cofAC)[k][j] = (int**)calloc (2, sizeof(int*))) == NULL) no_mem_exit ("get_mem_ACcoeff: cofAC");
for (i=0; i<2; i++)
{
if (((*cofAC)[k][j][i] = (int*)calloc (65, sizeof(int))) == NULL) no_mem_exit ("get_mem_ACcoeff: cofAC"); // 18->65 for ABT
}
}
}
return num_blk8x8*4*2*65*sizeof(int);// 18->65 for ABT
}
/*!
************************************************************************
* \brief
* Allocate memory for DC coefficients
************************************************************************
*/
int get_mem_DCcoeff (int**** cofDC)
{
int j, k;
if ((*cofDC = (int***)calloc (3, sizeof(int**))) == NULL) no_mem_exit ("get_mem_DCcoeff: cofDC");
for (k=0; k<3; k++)
{
if (((*cofDC)[k] = (int**)calloc (2, sizeof(int*))) == NULL) no_mem_exit ("get_mem_DCcoeff: cofDC");
for (j=0; j<2; j++)
{
if (((*cofDC)[k][j] = (int*)calloc (65, sizeof(int))) == NULL) no_mem_exit ("get_mem_DCcoeff: cofDC"); // 18->65 for ABT
}
}
return 3*2*65*sizeof(int); // 18->65 for ABT
}
/*!
************************************************************************
* \brief
* Free memory of AC coefficients
************************************************************************
*/
void free_mem_ACcoeff (int**** cofAC)
{
int i, j, k;
for (k=0; k<4+img->num_blk8x8_uv; k++)
{
for (i=0; i<4; i++)
{
for (j=0; j<2; j++)
{
free (cofAC[k][i][j]);
}
free (cofAC[k][i]);
}
free (cofAC[k]);
}
free (cofAC);
}
/*!
************************************************************************
* \brief
* Free memory of DC coefficients
************************************************************************
*/
void free_mem_DCcoeff (int*** cofDC)
{
int i, j;
for (j=0; j<3; j++)
{
for (i=0; i<2; i++)
{
free (cofDC[j][i]);
}
free (cofDC[j]);
}
free (cofDC);
}
/*!
************************************************************************
* \brief
* form frame picture from two field pictures
************************************************************************
*/
void combine_field(void)
{
int i;
for (i=0; i<img->height / 2; i++)
{
memcpy(imgY_com[i*2], enc_top_picture->imgY[i], img->width*sizeof(imgpel)); // top field
memcpy(imgY_com[i*2 + 1], enc_bottom_picture->imgY[i], img->width*sizeof(imgpel)); // bottom field
}
if (img->yuv_format != YUV400)
{
for (i=0; i<img->height_cr / 2; i++)
{
memcpy(imgUV_com[0][i*2], enc_top_picture->imgUV[0][i], img->width_cr*sizeof(imgpel));
memcpy(imgUV_com[0][i*2 + 1], enc_bottom_picture->imgUV[0][i], img->width_cr*sizeof(imgpel));
memcpy(imgUV_com[1][i*2], enc_top_picture->imgUV[1][i], img->width_cr*sizeof(imgpel));
memcpy(imgUV_com[1][i*2 + 1], enc_bottom_picture->imgUV[1][i], img->width_cr*sizeof(imgpel));
}
}
}
/*!
************************************************************************
* \brief
* RD decision of frame and field coding
************************************************************************
*/
int decide_fld_frame(float snr_frame_Y, float snr_field_Y, int bit_field, int bit_frame, double lambda_picture)
{
double cost_frame, cost_field;
cost_frame = bit_frame * lambda_picture + snr_frame_Y;
cost_field = bit_field * lambda_picture + snr_field_Y;
if (cost_field > cost_frame)
return (0);
else
return (1);
}
/*!
************************************************************************
* \brief
* Do some initialization work for encoding the 2nd IGOP
************************************************************************
*/
void process_2nd_IGOP(void)
{
Boolean FirstIGOPFinished = FALSE;
if ( img->number == input->no_frames-1 )
FirstIGOPFinished = TRUE;
if (input->NumFrameIn2ndIGOP==0) return;
if (!FirstIGOPFinished || In2ndIGOP) return;
In2ndIGOP = TRUE;
// img->number = -1;
start_frame_no_in_this_IGOP = input->no_frames;
start_tr_in_this_IGOP = (input->no_frames-1)*(input->jumpd+1) +1;
input->no_frames = input->no_frames + input->NumFrameIn2ndIGOP;
/* reset_buffers();
frm->picbuf_short[0]->used=0;
frm->picbuf_short[0]->picID=-1;
frm->picbuf_short[0]->lt_picID=-1;
frm->short_used = 0; */
}
/*!
************************************************************************
* \brief
* Set the image type for I,P and SP pictures (not B!)
************************************************************************
*/
void SetImgType(void)
{
int intra_refresh = input->intra_period == 0 ? (IMG_NUMBER == 0) : ((IMG_NUMBER%input->intra_period) == 0);
if (intra_refresh)
{
img->type = I_SLICE; // set image type for first image to I-frame
}
else
{
img->type = input->sp_periodicity && ((IMG_NUMBER % input->sp_periodicity) ==0) ? SP_SLICE : ((input->BRefPictures == 2) ? B_SLICE : P_SLICE);
}
}
void SetLevelIndices(void)
{
switch(active_sps->level_idc)
{
case 9:
img->LevelIndex=1;
break;
case 10:
img->LevelIndex=0;
break;
case 11:
if ((active_sps->profile_idc < FREXT_HP)&&(active_sps->constrained_set3_flag == 0))
img->LevelIndex=2;
else
img->LevelIndex=1;
break;
case 12:
img->LevelIndex=3;
break;
case 13:
img->LevelIndex=4;
break;
case 20:
img->LevelIndex=5;
break;
case 21:
img->LevelIndex=6;
break;
case 22:
img->LevelIndex=7;
break;
case 30:
img->LevelIndex=8;
break;
case 31:
img->LevelIndex=9;
break;
case 32:
img->LevelIndex=10;
break;
case 40:
img->LevelIndex=11;
break;
case 41:
img->LevelIndex=12;
break;
case 42:
if (active_sps->profile_idc <= 88)
img->LevelIndex=13;
else
img->LevelIndex=14;
break;
case 50:
img->LevelIndex=15;
break;
case 51:
img->LevelIndex=16;
break;
default:
fprintf ( stderr, "Warning: unknown LevelIDC, using maximum level 5.1 \n" );
img->LevelIndex=16;
break;
}
}
/*!
************************************************************************
* \brief
* initialize key frames and corresponding redundant frames.
************************************************************************
*/
void Init_redundant_frame()
{
if(input->redundant_pic_flag)
{
if(input->successive_Bframe)
{
error("B frame not supported when redundant picture used!",100);
}
if(input->PicInterlace)
{
error("Interlace not supported when redundant picture used!",100);
}
if(input->num_ref_frames<input->PrimaryGOPLength)
{
error("NumberReferenceFrames must be no less than PrimaryGOPLength",100);
}
if((1<<input->NumRedundantHierarchy)>input->PrimaryGOPLength)
{
error("PrimaryGOPLength must be greater than 2^NumRedundantHeirarchy",100);
}
if(input->Verbose!=1)
{
error("Redundant slices not supported when Verbose!=1",100);
}
}
key_frame = 0;
redundant_coding = 0;
img->redundant_pic_cnt = 0;
frameNuminGOP = img->number % input->PrimaryGOPLength;
if(img->number == 0)
{
frameNuminGOP = -1;
}
}
/*!
************************************************************************
* \brief
* allocate redundant frames in a primary GOP.
************************************************************************
*/
void Set_redundant_frame()
{
int GOPlength = input->PrimaryGOPLength;
//start frame of GOP
if(frameNuminGOP == 0)
{
redundant_coding = 0;
key_frame = 1;
redundant_ref_idx = GOPlength;
}
//1/2 position
if(input->NumRedundantHierarchy>0)
{
if(frameNuminGOP == GOPlength/2)
{
redundant_coding = 0;
key_frame = 1;
redundant_ref_idx = GOPlength/2;
}
}
//1/4, 3/4 position
if(input->NumRedundantHierarchy>1)
{
if(frameNuminGOP == GOPlength/4 || frameNuminGOP == GOPlength*3/4)
{
redundant_coding = 0;
key_frame = 1;
redundant_ref_idx = GOPlength/4;
}
}
//1/8, 3/8, 5/8, 7/8 position
if(input->NumRedundantHierarchy>2)
{
if(frameNuminGOP == GOPlength/8 || frameNuminGOP == GOPlength*3/8
|| frameNuminGOP == GOPlength*5/8 || frameNuminGOP == GOPlength*7/8)
{
redundant_coding = 0;
key_frame = 1;
redundant_ref_idx = GOPlength/8;
}
}
//1/16, 3/16, 5/16, 7/16, 9/16, 11/16, 13/16 position
if(input->NumRedundantHierarchy>3)
{
if(frameNuminGOP == GOPlength/16 || frameNuminGOP == GOPlength*3/16
|| frameNuminGOP == GOPlength*5/16 || frameNuminGOP == GOPlength*7/16
|| frameNuminGOP == GOPlength*9/16 || frameNuminGOP == GOPlength*11/16
|| frameNuminGOP == GOPlength*13/16)
{
redundant_coding = 0;
key_frame = 1;
redundant_ref_idx = GOPlength/16;
}
}
}
/*!
************************************************************************
* \brief
* encode on redundant frame.
************************************************************************
*/
void encode_one_redundant_frame()
{
key_frame = 0;
redundant_coding = 1;
img->redundant_pic_cnt = 1;
if(img->type == I_SLICE)
{
img->type = P_SLICE;
}
encode_one_frame();
}
/*!
************************************************************************
* \brief
* Setup Chroma MC Variables
************************************************************************
*/
void chroma_mc_setup(void)
{
// initialize global variables used for chroma interpolation and buffering
if ( img->yuv_format == YUV420 )
{
img_pad_size_uv_x = IMG_PAD_SIZE >> 1;
img_pad_size_uv_y = IMG_PAD_SIZE >> 1;
chroma_mask_mv_y = 7;
chroma_mask_mv_x = 7;
chroma_shift_x = 3;
chroma_shift_y = 3;
}
else if ( img->yuv_format == YUV422 )
{
img_pad_size_uv_x = IMG_PAD_SIZE >> 1;
img_pad_size_uv_y = IMG_PAD_SIZE;
chroma_mask_mv_y = 3;
chroma_mask_mv_x = 7;
chroma_shift_y = 2;
chroma_shift_x = 3;
}
else
{ // YUV444
img_pad_size_uv_x = IMG_PAD_SIZE;
img_pad_size_uv_y = IMG_PAD_SIZE;
chroma_mask_mv_y = 3;
chroma_mask_mv_x = 3;
chroma_shift_y = 2;
chroma_shift_x = 2;
}
shift_cr_y = chroma_shift_y - 2;
shift_cr_x = chroma_shift_x - 1;
}