www.pudn.com > avs-m3.rar > hrd.c
/*! ************************************************************************************* * \file * HRD.h * \brief * Hypothesis Reference Decoder ************************************************************************************* */ #include#include #include "HRD.h" #include "vlc.h" #include "memalloc.h" unsigned int seq_parameter_set_id; unsigned int cpb_dpb_cnt_minus1; unsigned int *cpb_underflow_allowable_flag; unsigned int *bit_rate_value_minus1_lsb; unsigned int *bit_rate_value_minus1_msb; unsigned int *cpb_size_value_minus1_lsb; unsigned int *cpb_size_value_minus1_msb; unsigned int *dpb_size_value_minus1_lsb; unsigned int *dpb_size_value_minus1_msb; unsigned int *initial_cpb_removal_delay_lsb; unsigned int *initial_cpb_removal_delay_msb; unsigned int *initial_cpb_removal_delay; unsigned int *initial_dpb_output_delay_lsb; unsigned int *initial_dpb_output_delay_msb; unsigned int *initial_dpb_output_delay; unsigned int *Bit_Buffer; unsigned int *ROT; struct DecodedPictureBuffer dpb; struct FrameBuffer outframe; struct FrameBuffer decframe; unsigned int outputtimer; int pre_picture_distance; /*! ************************************************************************************* * \brief : * to get unsigned long word from a file. * \param : * FILE *fp : File should be opened to read in binary format. * \return : * unsigned long double word ************************************************************************************* */ unsigned long GetBigDoubleWord(FILE *fp) { register unsigned int dw; dw = (unsigned int) (fgetc(fp) & 0xFF); dw = ((unsigned int) (fgetc(fp) & 0xFF)) | (dw << 0x08); dw = ((unsigned int) (fgetc(fp) & 0xFF)) | (dw << 0x08); dw = ((unsigned int) (fgetc(fp) & 0xFF)) | (dw << 0x08); return(dw); } /*! ************************************************************************************* * \brief : * Calculates if decoder leaky bucket parameters meets HRD constraints specified by encoder * Failure if LeakyBucketParam file is missing or if it does not have the correct number of entries ************************************************************************************* */ void calc_buffer(struct inp_par *inp) { unsigned int NumberLeakyBuckets, *Rmin, *Bmin, *Fmin; float B_interp, F_interp; unsigned int iBucket; float dnr, frac1, frac2; unsigned int R_decoder, B_decoder, F_decoder; FILE *outf; unsigned int *InitCpbDelay; if ((outf=fopen(inp->LeakyBucketParamFile,"rb"))==NULL) { printf("Error open file %s \n", inp->LeakyBucketParamFile); exit(0); return; } NumberLeakyBuckets = GetBigDoubleWord(outf); printf(" Number Leaky Buckets: %8ld \n", NumberLeakyBuckets); Rmin = calloc(sizeof(unsigned int), NumberLeakyBuckets); Bmin = calloc(sizeof(unsigned int), NumberLeakyBuckets); Fmin = calloc(sizeof(unsigned int), NumberLeakyBuckets); InitCpbDelay = calloc(sizeof(unsigned int), NumberLeakyBuckets);; printf(" BitRate(b/s) CbpSize(b) InitCbpDelay(1/90000 s)\n"); for(iBucket =0; iBucket < NumberLeakyBuckets; iBucket++) { Rmin[iBucket] = GetBigDoubleWord(outf); Bmin[iBucket] = GetBigDoubleWord(outf); Fmin[iBucket] = GetBigDoubleWord(outf); InitCpbDelay[iBucket] = (unsigned int)( ((float)Fmin[iBucket] / Rmin[iBucket]) * 90000 + 0.5 ); printf("%10d %10d %10d\n", Rmin[iBucket], Bmin[iBucket], InitCpbDelay[iBucket]); } fclose(outf); R_decoder = inp->R_decoder; F_decoder = inp->F_decoder; B_decoder = inp->B_decoder; for( iBucket =0; iBucket < NumberLeakyBuckets; iBucket++) { if(R_decoder < Rmin[iBucket]) { break; } } printf("\n"); if(iBucket > 0 ) { if(iBucket < NumberLeakyBuckets) { dnr = (float) (Rmin[iBucket] - Rmin[iBucket-1]); frac1 = (float) (R_decoder - Rmin[iBucket-1]); frac2 = (float) (Rmin[iBucket] - R_decoder); B_interp = (float) (Bmin[iBucket] * frac1 + Bmin[iBucket-1] * frac2) /dnr; F_interp = (float) (Fmin[iBucket] * frac1 + Fmin[iBucket-1] * frac2) /dnr; } else { B_interp = (float) Bmin[iBucket-1]; F_interp = (float) Fmin[iBucket-1]; } printf(" Min.buffer %8.2f Decoder buffer size %ld \n Minimum Delay %8.2f DecoderDelay %ld \n", B_interp, B_decoder, F_interp, F_decoder); if(B_decoder > B_interp && F_decoder > F_interp) { printf(" HRD Compliant \n"); } else { printf(" HRD Non Compliant \n"); } } else { printf(" Decoder Rate is too small; HRD cannot be verified \n"); } free(Rmin); free(Bmin); free(Fmin); free(InitCpbDelay); return; } /*! ************************************************************************************* * \brief : * allocate memeory for hrd variables ************************************************************************************* */ void init_hrd(int NumberLeakyBuckets) { cpb_underflow_allowable_flag = calloc(NumberLeakyBuckets, sizeof(int)); bit_rate_value_minus1_lsb = calloc(NumberLeakyBuckets, sizeof(int)); bit_rate_value_minus1_msb = calloc(NumberLeakyBuckets, sizeof(int)); cpb_size_value_minus1_lsb = calloc(NumberLeakyBuckets, sizeof(int)); cpb_size_value_minus1_msb = calloc(NumberLeakyBuckets, sizeof(int)); dpb_size_value_minus1_lsb = calloc(NumberLeakyBuckets, sizeof(int)); dpb_size_value_minus1_msb = calloc(NumberLeakyBuckets, sizeof(int)); initial_cpb_removal_delay_lsb = calloc(NumberLeakyBuckets, sizeof(int)); initial_cpb_removal_delay_msb = calloc(NumberLeakyBuckets, sizeof(int)); initial_cpb_removal_delay = calloc(NumberLeakyBuckets, sizeof(int)); initial_dpb_output_delay_lsb = calloc(NumberLeakyBuckets, sizeof(int)); initial_dpb_output_delay_msb = calloc(NumberLeakyBuckets, sizeof(int)); initial_dpb_output_delay = calloc(NumberLeakyBuckets, sizeof(int)); } /*! ************************************************************************************* * \brief : * ************************************************************************************* */ void end_hrd() { if (cpb_underflow_allowable_flag) free(cpb_underflow_allowable_flag); if (bit_rate_value_minus1_lsb) free(bit_rate_value_minus1_lsb); if (bit_rate_value_minus1_msb) free(bit_rate_value_minus1_msb); if (cpb_size_value_minus1_lsb) free(cpb_size_value_minus1_lsb); if (cpb_size_value_minus1_msb) free(cpb_size_value_minus1_msb); if (dpb_size_value_minus1_lsb) free(dpb_size_value_minus1_lsb); if (dpb_size_value_minus1_msb) { free(dpb_size_value_minus1_msb); } if (initial_cpb_removal_delay_lsb) { free(initial_cpb_removal_delay_lsb); } if (initial_cpb_removal_delay_msb) { free(initial_cpb_removal_delay_msb); } if (initial_cpb_removal_delay) { free(initial_cpb_removal_delay); } if (initial_dpb_output_delay_lsb) { free(initial_dpb_output_delay_lsb); } if (initial_dpb_output_delay_msb) { free(initial_dpb_output_delay_msb); } if (initial_dpb_output_delay) { free(initial_dpb_output_delay); } } /*! ************************************************************************************* * \brief : * allocate memory for DPB and related variables ************************************************************************************* */ void init_dpb() { unsigned int i; outputtimer = 0; dpb.size = 3; // the max number of reference frame is 2, so I set 3 to dpb.size. dpb.used_size = 0; dpb.fb = (struct FrameBuffer **)calloc(dpb.size, sizeof (struct FrameBuffer *)); for (i = 0; i < dpb.size; i++) { dpb.fb[i] = (struct FrameBuffer *)calloc(1, sizeof (struct FrameBuffer)); } for (i = 0; i < dpb.size; i++) { get_mem2D(&(dpb.fb[i]->imgY), pgImage->height, pgImage->width); get_mem3D(&(dpb.fb[i]->imgUV), 2, pgImage->height/2, pgImage->width/2); } ROT = calloc(MAX_FRAME_NUM, sizeof (int)); for (i = 0; i < MAX_FRAME_NUM; i++) { ROT[i] = 0; } get_mem2D(&(outframe.imgY), pgImage->height, pgImage->width); get_mem3D(&(outframe.imgUV), 2, pgImage->height / 2, pgImage->width / 2); get_mem2D(&(decframe.imgY), pgImage->height, pgImage->width); get_mem3D(&(decframe.imgUV), 2, pgImage->height / 2, pgImage->width / 2); } /*! ************************************************************************************* * \brief : * free DPB and related variables ************************************************************************************* */ void free_dpb() { unsigned int i; for (i = 0; i < dpb.size; i++) { free_mem2D (dpb.fb[i]->imgY); free_mem3D (dpb.fb[i]->imgUV, 2); free(dpb.fb[i]); } free(dpb.fb); free_mem2D(outframe.imgY); free_mem3D(outframe.imgUV, 2); free_mem2D(decframe.imgY); free_mem3D(decframe.imgUV, 2); free(ROT); } /*! ************************************************************************************* * \brief : * insert the decoded picture into DPB ************************************************************************************* */ void Insert_OneFrame_Into_DPB(struct FrameBuffer *pDecFrame) { int i, j; struct FrameBuffer *p; if (dpb.used_size == dpb.size) { printf("Decoded Picture Buffer Overflow, decoded failed\n"); exit(0); } if (dpb.used_size > 0) { p = dpb.fb[dpb.used_size]; for (i = dpb.used_size; i > 0; i--) { dpb.fb[i] = dpb.fb[i - 1]; } dpb.fb[0] = p; } for (j = 0; j < pgImage->height; j++) { for (i = 0; i < pgImage->width; i++) { dpb.fb[0]->imgY[j][i] = pDecFrame->imgY[j][i]; } } for (j = 0; j < pgImage->height / 2; j++) { for (i = 0; i < pgImage->width / 2; i++) { dpb.fb[0]->imgUV[0][j][i] = pDecFrame->imgUV[0][j][i]; dpb.fb[0]->imgUV[1][j][i] = pDecFrame->imgUV[1][j][i]; } } dpb.fb[0]->frmnum = pDecFrame->frmnum; dpb.fb[0]->outputted = pDecFrame->outputted; dpb.fb[0]->rotvalue = pDecFrame->rotvalue; dpb.fb[0]->used_for_ref = pDecFrame->used_for_ref; dpb.fb[0]->number_of_bytes=pDecFrame->number_of_bytes; dpb.used_size++; } /*! ************************************************************************************* * \brief : * output some frames which are to be displayed from DPB ************************************************************************************* */ void Output_Frame_From_DPB(unsigned int timer) { unsigned int rotvalue = 0; int i, x, y; for (i = dpb.used_size - 1; i >= 0; i--) { rotvalue = dpb.fb[i]->rotvalue; if (timer >= rotvalue) { dpb.fb[i]->outputted = 1; for (y = 0; y < pgImage->height; y++) { for (x = 0; x < pgImage->width; x++) { outframe.imgY[y][x] = dpb.fb[i]->imgY[y][x]; } } for (y = 0; y < pgImage->height / 2; y++) { for (x = 0; x < pgImage->width / 2; x++) { outframe.imgUV[0][y][x] = dpb.fb[i]->imgUV[0][y][x]; outframe.imgUV[1][y][x] = dpb.fb[i]->imgUV[1][y][x]; } } } } } /*! ************************************************************************************* * \brief : * remove one frame from DPB ************************************************************************************* */ void Remove_OneFrame_From_DPB(int num) { unsigned int i; for (i = num; i < dpb.used_size - 1; i++) { dpb.fb[i] = dpb.fb[i + 1]; } dpb.used_size--; } /*! ************************************************************************************* * \brief : * remove some frames from DPB ************************************************************************************* */ int Remove_Frame_From_DPB() { int i; int ret = 0; for (i = dpb.used_size - 1; i >= 0; i--) { if (dpb.fb[i]->outputted && !dpb.fb[i]->used_for_ref) { Remove_OneFrame_From_DPB(i); ret++; } } return ret; } /*! ************************************************************************************* * \brief : * store the decoded picture into DPB and update some information ************************************************************************************* */ void Store_OneFrame_Into_DPB(struct FrameBuffer *pDecFrame) { int ret; if (dpb.used_size == dpb.size) { ret = 0; ret = Remove_Frame_From_DPB(); if (ret == 0) { printf("Decoded Picture Buffer Overflow, decoded failed\n"); exit(0); } } Insert_OneFrame_Into_DPB(pDecFrame); Output_Frame_From_DPB(outputtimer); Remove_Frame_From_DPB(); } /*! ************************************************************************************* * \brief : * update the information which indicates wheather frames are used as reference frame ************************************************************************************* */ void UpdateRefFrameBufFlag() { unsigned int i, j; int count = 0; for (i = 0; i < dpb.used_size; i++) { if (dpb.fb[i]->used_for_ref) { count++; } if (count == 2) // the max reference frame number in AVS_M is 2. { break; } } for (j = i + 1; j < dpb.used_size; j++) { dpb.fb[j]->used_for_ref = 0; } }