📄 image.c
字号:
diff_y += img->quad[abs(imgY[j][i]-imgY_ref[j][i])];
}
}
// Chroma
diff_u=0;
diff_v=0;
for (j=0; j < img->height_cr; ++j)
{
for (i=0; i < img->width_cr; ++i)
{
diff_u += img->quad[abs(imgUV_ref[0][j][i]-imgUV[0][j][i])];
diff_v += img->quad[abs(imgUV_ref[1][j][i]-imgUV[1][j][i])];
}
}
// Collecting SNR statistics
if (diff_y != 0)
snr->snr_y=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)diff_y)); // luma snr for current frame
if (diff_u != 0)
snr->snr_u=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_u))); // chroma snr for current frame
if (diff_v != 0)
snr->snr_v=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_v))); // chroma snr for current frame
if (img->number == 0) // first
{
snr->snr_y1=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)diff_y)); // keep luma snr for first frame
snr->snr_u1=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_u))); // keep chroma snr for first frame
snr->snr_v1=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_v))); // keep chroma snr for first frame
snr->snr_ya=snr->snr_y1;
snr->snr_ua=snr->snr_u1;
snr->snr_va=snr->snr_v1;
if (diff_y == 0)
snr->snr_ya=50; // need to assign a reasonable large number so avg snr of entire sequece isn't infinite
if (diff_u == 0)
snr->snr_ua=50;
if (diff_v == 0)
snr->snr_va=50;
}
else
{
snr->snr_ya=(float)(snr->snr_ya*(img->number+Bframe_ctr)+snr->snr_y)/(img->number+Bframe_ctr+1); // average snr chroma for all frames
snr->snr_ua=(float)(snr->snr_ua*(img->number+Bframe_ctr)+snr->snr_u)/(img->number+Bframe_ctr+1); // average snr luma for all frames
snr->snr_va=(float)(snr->snr_va*(img->number+Bframe_ctr)+snr->snr_v)/(img->number+Bframe_ctr+1); // average snr luma for all frames
}
}
/*!
************************************************************************
* \brief
* Interpolation of 1/4 subpixel
************************************************************************
*/
void get_block(int ref_frame,int x_pos, int y_pos, struct img_par *img, int block[BLOCK_SIZE][BLOCK_SIZE])
{
int dx, dy;
int x, y;
int i, j;
int maxold_x,maxold_y;
int result;
int pres_x;
int pres_y;
int tmp_res[4][9];
static const int COEF[6] = {
1, -5, 20, 20, -5, 1
};
dx = x_pos&3;
dy = y_pos&3;
x_pos = (x_pos-dx)/4;
y_pos = (y_pos-dy)/4;
maxold_x = img->width-1;
maxold_y = img->height-1;
if (img->structure==FRAME && img->mb_field)
maxold_y = img->height/2 - 1;
if (dx == 0 && dy == 0) { /* fullpel position */
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = mref[ref_frame][max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i))];
}
else { /* other positions */
if (dy == 0) { /* No vertical interpolation */
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
for (result = 0, x = -2; x < 4; x++)
result += mref[ref_frame][max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i+x))]*COEF[x+2];
block[i][j] = max(0, min(255, (result+16)/32));
}
}
if ((dx&1) == 1) {
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = (block[i][j] + mref[ref_frame][max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i+dx/2))] +1 )/2;
}
}
else if (dx == 0) { /* No horizontal interpolation */
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
for (result = 0, y = -2; y < 4; y++)
result += mref[ref_frame][max(0,min(maxold_y,y_pos+j+y))][max(0,min(maxold_x,x_pos+i))]*COEF[y+2];
block[i][j] = max(0, min(255, (result+16)/32));
}
}
if ((dy&1) == 1) {
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = (block[i][j] + mref[ref_frame][max(0,min(maxold_y,y_pos+j+dy/2))][max(0,min(maxold_x,x_pos+i))] +1 )/2;
}
}
else if (dx == 2) { /* Vertical & horizontal interpolation */
for (j = -2; j < BLOCK_SIZE+3; j++) {
for (i = 0; i < BLOCK_SIZE; i++)
for (tmp_res[i][j+2] = 0, x = -2; x < 4; x++)
tmp_res[i][j+2] += mref[ref_frame][max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i+x))]*COEF[x+2];
}
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
for (result = 0, y = -2; y < 4; y++)
result += tmp_res[i][j+y+2]*COEF[y+2];
block[i][j] = max(0, min(255, (result+512)/1024));
}
}
if ((dy&1) == 1) {
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = (block[i][j] + max(0, min(255, (tmp_res[i][j+2+dy/2]+16)/32)) +1 )/2;
}
}
else if (dy == 2) { /* Horizontal & vertical interpolation */
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = -2; i < BLOCK_SIZE+3; i++)
for (tmp_res[j][i+2] = 0, y = -2; y < 4; y++)
tmp_res[j][i+2] += mref[ref_frame][max(0,min(maxold_y,y_pos+j+y))][max(0,min(maxold_x,x_pos+i))]*COEF[y+2];
}
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
for (result = 0, x = -2; x < 4; x++)
result += tmp_res[j][i+x+2]*COEF[x+2];
block[i][j] = max(0, min(255, (result+512)/1024));
}
}
if ((dx&1) == 1) {
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = (block[i][j] + max(0, min(255, (tmp_res[j][i+2+dx/2]+16)/32))+1)/2;
}
}
else { /* Diagonal interpolation */
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
pres_y = dy == 1 ? y_pos+j : y_pos+j+1;
pres_y = max(0,min(maxold_y,pres_y));
for (result = 0, x = -2; x < 4; x++)
result += mref[ref_frame][pres_y][max(0,min(maxold_x,x_pos+i+x))]*COEF[x+2];
block[i][j] = max(0, min(255, (result+16)/32));
}
}
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
pres_x = dx == 1 ? x_pos+i : x_pos+i+1;
pres_x = max(0,min(maxold_x,pres_x));
for (result = 0, y = -2; y < 4; y++)
result += mref[ref_frame][max(0,min(maxold_y,y_pos+j+y))][pres_x]*COEF[y+2];
block[i][j] = (block[i][j] + max(0, min(255, (result+16)/32)) +1 ) / 2;
}
}
}
}
}
/*!
************************************************************************
* \brief
* Reads new slice from bit_stream
************************************************************************
*/
int read_new_slice()
{
NALU_t *nalu = AllocNALU(MAX_CODED_FRAME_SIZE);
int current_header;
int ret;
int BitsUsedByHeader;
Slice *currSlice = img->currentSlice;
Bitstream *currStream;
int newframe;
// int i;
while (1)
{
if (input->FileFormat == PAR_OF_ANNEXB)
ret=GetAnnexbNALU (nalu);
else
ret=GetRTPNALU (nalu);
NALUtoRBSP(nalu);
// printf ("nalu->len %d\n", nalu->len);
if (ret < 0)
printf ("Error while getting the NALU in file format %s, exit\n", input->FileFormat==PAR_OF_ANNEXB?"Annex B":"RTP");
if (ret == 0)
{
// printf ("read_new_slice: returning %s\n", "EOS");
FreeNALU(nalu);
return EOS;
}
// Got a NALU
if (nalu->forbidden_bit)
{
printf ("Found NALU w/ forbidden_bit set, bit error? Let's try...\n");
}
switch (nalu->nal_unit_type)
{
case NALU_TYPE_SLICE:
case NALU_TYPE_IDR:
img->idr_flag = (nalu->nal_unit_type == NALU_TYPE_IDR);
img->disposable_flag = (nalu->nal_reference_idc == NALU_PRIORITY_DISPOSABLE);
currSlice->dp_mode = PAR_DP_1;
currSlice->max_part_nr = 1;
currSlice->ei_flag = 0;
currStream = currSlice->partArr[0].bitstream;
currStream->ei_flag = 0;
currStream->frame_bitoffset = currStream->read_len = 0;
memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1);
currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1);
// Some syntax of the Slice Header depends on the parameter set, which depends on
// the parameter set ID of the SLice header. Hence, read the pic_parameter_set_id
// of the slice header first, then setup the active parameter sets, and then read
// the rest of the slice header
BitsUsedByHeader = FirstPartOfSliceHeader();
UseParameterSet (currSlice->pic_parameter_set_id);
BitsUsedByHeader+= RestOfSliceHeader ();
if (img->currentSlice->structure!=0)
{
img->height /=2 ;
img->height_cr /=2;
}
// FMO stuff
FmoInit (active_pps, active_sps);
// From here on, active_sps, active_pps and the slice header are valid
// printf ("img->frame num %d, img->tr %d, img->disposable_flag %d\n", img->frame_num, img->tr, img->disposable_flag);
img->current_mb_nr = img->map_mb_nr = currSlice->start_mb_nr; //! potential interlace problem. Is map_mb_nr correct?
if (img->tr_old != img->tr)
{
newframe=1;
img->tr_old = img->tr;
}
else
newframe = 0;
if (newframe)
current_header = SOP;
else
current_header = SOS;
if(img->structure != img->structure_old)
newframe |= 1;
img->structure_old = img->structure;
//! new stuff StW
if(newframe)
current_header = SOP;
else
current_header = SOS;
if (active_pps->entropy_coding_mode == CABAC)
{
int ByteStartPosition = currStream->frame_bitoffset/8;
if (currStream->frame_bitoffset%8 != 0)
{
// printf ("Slice header ends NOT at a byte aligned position\n");
ByteStartPosition++;
}
// else
// printf ("SLice header ends at a byte aligned position\n");
// printf ("First CABAC Bytes to decode: %x %x %x %x %x\n", currStream->streamBuffer[ByteStartPosition],currStream->streamBuffer[ByteStartPosition+1],currStream->streamBuffer[ByteStartPosition+2],currStream->streamBuffer[ByteStartPosition+3],currStream->streamBuffer[ByteStartPosition+4],currStream->streamBuffer[ByteStartPosition+5]);
arideco_start_decoding (&currSlice->partArr[0].de_cabac, currStream->streamBuffer, ByteStartPosition, &currStream->read_len, img->type);
}
// printf ("read_new_slice: returning %s\n", current_header == SOP?"SOP":"SOS");
FreeNALU(nalu);
return current_header;
break;
case NALU_TYPE_DPA:
//! The state machine here should follow the same ideas as the old readSliceRTP()
//! basically:
//! work on DPA (as above)
//! read and process all following SEI/SPS/PPS/PD/Filler NALUs
//! if next video NALU is dpB,
//! then read and check whether it belongs to DPA, if yes, use it
//! else
//! ; // nothing
//! read and process all following SEI/SPS/PPS/PD/Filler NALUs
//! if next video NALU is dpC
//! then read and check whether it belongs to DPA (and DPB, if present), if yes, use it, done
//! else
//! use the DPA (and the DPB if present)
assert (0==1);
break;
case NALU_TYPE_DPB:
printf ("read_new_slice: Found unexpected NALU_TYPE_DPB, len %d\n", nalu->len);
printf ("ignoring... moving on with next NALU\n");
//! Note: one could do something smarter here, e.g. checking the Slice ID
//! in conjunction with redundant_pic_cnt to identify lost pictures
assert (0==1);
break;
case NALU_TYPE_DPC:
printf ("read_new_slice: Found NALU_TYPE_DPC, len %d\n", nalu->len);
printf ("ignoring... moving on with next NALU\n");
//! Note: one could do something smarter here, e.g. checking the Slice ID
//! in conjunction with redundant_pic_cnt to identify lost pictures
assert (0==1);
break;
case NALU_TYPE_SEI:
printf ("read_new_slice: Found NALU_TYPE_SEI, len %d\n", nalu->len);
InterpretSEIMessage(nalu->buf,nalu->len,img);
break;
case NALU_TYPE_PPS:
ProcessPPS(nalu);
break;
case NALU_TYPE_SPS:
ProcessSPS(nalu);
break;
case NALU_TYPE_PD:
printf ("read_new_slice: Found NALU_TYPE_PD, len %d\n, ignored", nalu->len);
break;
case NALU_TYPE_FILL:
printf ("read_new_slice: Found NALU_TYPE_FILL, len %d\n", nalu->len);
printf ("Skipping these filling bits, proceeding w/ next NALU\n");
break;
default:
printf ("Found NALU type %d, len %d undefined, ignore NALU, moving on\n", nalu->nal_unit_type, nalu->len);
}
}
FreeNALU(nalu);
return current_header;
}
/*!
************************************************************************
* \brief
* Initializes the parameters for a new frame
************************************************************************
*/
void init_frame(struct img_par *img, struct inp_par *inp)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -