📄 hrd.c
字号:
/*!
*************************************************************************************
* \file
* HRD.h
* \brief
* Hypothesis Reference Decoder
*************************************************************************************
*/
#include <stdlib.h>
#include <stdio.h>
#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;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -