| |
| /*! |
| *********************************************************************** |
| * \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; |
| |
| } |
| |