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; 
    } 
}