📄 image.c
字号:
/*!
************************************************************************
* \brief
* Find PSNR for all three components.Compare decoded frame with
* the original sequence. Read inp->jumpd frames to reflect frame skipping.
************************************************************************
*/
void find_snr(struct snr_par *snr, //!< pointer to snr parameters
StorablePicture *p, //!< picture to be compared
int *p_ref) //!< open reference YUV file
{
static const int SubWidthC [4]= { 1, 2, 2, 1};
static const int SubHeightC [4]= { 1, 2, 1, 1};
int crop_left, crop_right, crop_top, crop_bottom;
int i,j, k;
int ret;
int64 diff_comp[3] = {0};
int64 status;
int symbol_size_in_bytes = img->pic_unit_bitsize_on_disk/8;
int comp_size_x[3], comp_size_y[3];
int64 framesize_in_bytes;
unsigned int max_pix_value_sqd[3] = {iabs2(img->max_imgpel_value_comp[0]), iabs2(img->max_imgpel_value_comp[1]), iabs2(img->max_imgpel_value_comp[2])};
Boolean rgb_output = (Boolean) (active_sps->vui_seq_parameters.matrix_coefficients==0);
unsigned char *buf;
imgpel **cur_ref[3] = {imgY_ref, p->chroma_format_idc != YUV400 ? imgUV_ref[0] : NULL, p->chroma_format_idc != YUV400 ? imgUV_ref[1] : NULL};
imgpel **cur_comp[3] = {p->imgY, p->chroma_format_idc != YUV400 ? p->imgUV[0] : NULL , p->chroma_format_idc!= YUV400 ? p->imgUV[1] : NULL};
// picture error concealment
char yuv_types[4][6]= {"4:0:0","4:2:0","4:2:2","4:4:4"};
// cropping for luma
if (p->frame_cropping_flag)
{
crop_left = SubWidthC[p->chroma_format_idc] * p->frame_cropping_rect_left_offset;
crop_right = SubWidthC[p->chroma_format_idc] * p->frame_cropping_rect_right_offset;
crop_top = SubHeightC[p->chroma_format_idc]*( 2 - p->frame_mbs_only_flag ) * p->frame_cropping_rect_top_offset;
crop_bottom = SubHeightC[p->chroma_format_idc]*( 2 - p->frame_mbs_only_flag ) * p->frame_cropping_rect_bottom_offset;
}
else
{
crop_left = crop_right = crop_top = crop_bottom = 0;
}
comp_size_x[0] = p->size_x - crop_left - crop_right;
comp_size_y[0] = p->size_y - crop_top - crop_bottom;
// cropping for chroma
if (p->frame_cropping_flag)
{
crop_left = p->frame_cropping_rect_left_offset;
crop_right = p->frame_cropping_rect_right_offset;
crop_top = ( 2 - p->frame_mbs_only_flag ) * p->frame_cropping_rect_top_offset;
crop_bottom = ( 2 - p->frame_mbs_only_flag ) * p->frame_cropping_rect_bottom_offset;
}
else
{
crop_left = crop_right = crop_top = crop_bottom = 0;
}
if ((p->chroma_format_idc==YUV400) && params->write_uv)
{
comp_size_x[1] = comp_size_x[2] = (p->size_x >> 1);
comp_size_y[1] = comp_size_y[2] = (p->size_y >> 1);
}
else
{
// These could be computed once and attached to the StorablePicture structure
comp_size_x[1] = comp_size_x[2] = (p->size_x_cr - crop_left - crop_right);
comp_size_y[1] = comp_size_y[2] = (p->size_y_cr - crop_top - crop_bottom);
}
framesize_in_bytes = (((int64) comp_size_x[0] * comp_size_y[0]) + ((int64) comp_size_x[1] * comp_size_y[1] ) * 2) * symbol_size_in_bytes;
// KS: this buffer should actually be allocated only once, but this is still much faster than the previous version
buf = malloc ( comp_size_x[0] * comp_size_y[0] * symbol_size_in_bytes );
if (NULL == buf)
{
no_mem_exit("find_snr: buf");
}
status = lseek (*p_ref, framesize_in_bytes * frame_no, SEEK_SET);
if (status == -1)
{
fprintf(stderr, "Warning: Could not seek to frame number %d in reference file. Shown PSNR might be wrong.\n", frame_no);
free (buf);
return;
}
if(rgb_output)
lseek (*p_ref, framesize_in_bytes/3, SEEK_CUR);
for (k = 0; k < ((p->chroma_format_idc != YUV400) ? 3 : 1); k++)
{
if(rgb_output && k == 2)
lseek (*p_ref, -framesize_in_bytes, SEEK_CUR);
ret = read(*p_ref, buf, comp_size_x[k] * comp_size_y[k] * symbol_size_in_bytes);
if (ret != comp_size_x[k] * comp_size_y[k] * symbol_size_in_bytes)
{
printf ("Warning: could not read from reconstructed file\n");
memset (buf, 0, comp_size_x[k] * comp_size_y[k] * symbol_size_in_bytes);
close(*p_ref);
*p_ref = -1;
break;
}
buf2img(cur_ref[k], buf, comp_size_x[k], comp_size_y[k], symbol_size_in_bytes);
for (j=0; j < comp_size_y[k]; ++j)
{
for (i=0; i < comp_size_x[k]; ++i)
{
diff_comp[k] += iabs2(cur_comp[k][j][i] - cur_ref[k][j][i]);
}
}
// Collecting SNR statistics
snr->snr[k] = psnr( max_pix_value_sqd[k], comp_size_x[k] * comp_size_y[k], (float) diff_comp[k]);
if (img->number == 0) // first
{
snr->snra[k] = snr->snr[k]; // keep luma snr for first frame
}
else
{
snr->snra[k] = (float)(snr->snra[k]*(snr->frame_ctr)+snr->snr[k])/(snr->frame_ctr + 1); // average snr chroma for all frames
}
}
if(rgb_output)
lseek (*p_ref, framesize_in_bytes*2/3, SEEK_CUR);
free (buf);
// picture error concealment
if(p->concealed_pic)
{
fprintf(stdout,"%04d(P) %8d %5d %5d %7.4f %7.4f %7.4f %s %5d\n",
frame_no, p->frame_poc, p->pic_num, p->qp,
snr->snr[0], snr->snr[1], snr->snr[2], yuv_types[p->chroma_format_idc], 0);
}
}
void reorder_lists(int currSliceType, Slice * currSlice)
{
if ((currSliceType != I_SLICE)&&(currSliceType != SI_SLICE))
{
if (currSlice->ref_pic_list_reordering_flag_l0)
{
reorder_ref_pic_list(listX[0], &listXsize[0],
img->num_ref_idx_l0_active - 1,
currSlice->reordering_of_pic_nums_idc_l0,
currSlice->abs_diff_pic_num_minus1_l0,
currSlice->long_term_pic_idx_l0);
}
if (no_reference_picture == listX[0][img->num_ref_idx_l0_active-1])
{
if (non_conforming_stream)
printf("RefPicList0[ num_ref_idx_l0_active_minus1 ] is equal to 'no reference picture'\n");
else
error("RefPicList0[ num_ref_idx_l0_active_minus1 ] is equal to 'no reference picture', invalid bitstream",500);
}
// that's a definition
listXsize[0] = img->num_ref_idx_l0_active;
}
if (currSliceType == B_SLICE)
{
if (currSlice->ref_pic_list_reordering_flag_l1)
{
reorder_ref_pic_list(listX[1], &listXsize[1],
img->num_ref_idx_l1_active - 1,
currSlice->reordering_of_pic_nums_idc_l1,
currSlice->abs_diff_pic_num_minus1_l1,
currSlice->long_term_pic_idx_l1);
}
if (no_reference_picture == listX[1][img->num_ref_idx_l1_active-1])
{
if (non_conforming_stream)
printf("RefPicList1[ num_ref_idx_l1_active_minus1 ] is equal to 'no reference picture'\n");
else
error("RefPicList1[ num_ref_idx_l1_active_minus1 ] is equal to 'no reference picture', invalid bitstream",500);
}
// that's a definition
listXsize[1] = img->num_ref_idx_l1_active;
}
free_ref_pic_list_reordering_buffer(currSlice);
}
/*!
************************************************************************
* \brief
* initialize ref_pic_num array
************************************************************************
*/
void set_ref_pic_num(void)
{
int i,j;
int slice_id=img->current_slice_nr;
for (i=0;i<listXsize[LIST_0];i++)
{
dec_picture->ref_pic_num [slice_id][LIST_0][i] = listX[LIST_0][i]->poc * 2 + ((listX[LIST_0][i]->structure==BOTTOM_FIELD)?1:0) ;
dec_picture->frm_ref_pic_num [slice_id][LIST_0][i] = listX[LIST_0][i]->frame_poc * 2;
dec_picture->top_ref_pic_num [slice_id][LIST_0][i] = listX[LIST_0][i]->top_poc * 2;
dec_picture->bottom_ref_pic_num [slice_id][LIST_0][i] = listX[LIST_0][i]->bottom_poc * 2 + 1;
//printf("POCS %d %d %d %d ",listX[LIST_0][i]->frame_poc,listX[LIST_0][i]->bottom_poc,listX[LIST_0][i]->top_poc,listX[LIST_0][i]->poc);
//printf("refid %d %d %d %d\n",(int) dec_picture->frm_ref_pic_num[LIST_0][i],(int) dec_picture->top_ref_pic_num[LIST_0][i],(int) dec_picture->bottom_ref_pic_num[LIST_0][i],(int) dec_picture->ref_pic_num[LIST_0][i]);
}
for (i=0;i<listXsize[LIST_1];i++)
{
dec_picture->ref_pic_num [slice_id][LIST_1][i] = listX[LIST_1][i]->poc *2 + ((listX[LIST_1][i]->structure==BOTTOM_FIELD)?1:0);
dec_picture->frm_ref_pic_num [slice_id][LIST_1][i] = listX[LIST_1][i]->frame_poc * 2;
dec_picture->top_ref_pic_num [slice_id][LIST_1][i] = listX[LIST_1][i]->top_poc * 2;
dec_picture->bottom_ref_pic_num [slice_id][LIST_1][i] = listX[LIST_1][i]->bottom_poc * 2 + 1;
}
if (!active_sps->frame_mbs_only_flag)
{
if (img->structure==FRAME)
{
for (j=2;j<6;j++)
{
for (i=0;i<listXsize[j];i++)
{
dec_picture->ref_pic_num [slice_id][j][i] = listX[j][i]->poc * 2 + ((listX[j][i]->structure==BOTTOM_FIELD)?1:0);
dec_picture->frm_ref_pic_num [slice_id][j][i] = listX[j][i]->frame_poc * 2 ;
dec_picture->top_ref_pic_num [slice_id][j][i] = listX[j][i]->top_poc * 2 ;
dec_picture->bottom_ref_pic_num [slice_id][j][i] = listX[j][i]->bottom_poc * 2 + 1;
}
}
}
}
}
/*!
************************************************************************
* \brief
* Reads new slice from bit_stream
************************************************************************
*/
int read_new_slice(Slice *currSlice)
{
NALU_t *nalu = AllocNALU(MAX_CODED_FRAME_SIZE);
int current_header = 0;
int BitsUsedByHeader;
Bitstream *currStream;
int slice_id_a, slice_id_b, slice_id_c;
int redundant_pic_cnt_b, redundant_pic_cnt_c;
while (1)
{
if (0 == read_next_nalu(nalu))
return EOS;
process_nalu:
switch (nalu->nal_unit_type)
{
case NALU_TYPE_SLICE:
case NALU_TYPE_IDR:
if (img->recovery_point || nalu->nal_unit_type == NALU_TYPE_IDR)
{
if (img->recovery_point_found == 0)
{
if (nalu->nal_unit_type != NALU_TYPE_IDR)
{
printf("Warning: Decoding does not start with an IDR picture.\n");
non_conforming_stream = 1;
}
else
non_conforming_stream = 0;
}
img->recovery_point_found = 1;
}
if (img->recovery_point_found == 0)
break;
img->idr_flag = (nalu->nal_unit_type == NALU_TYPE_IDR);
img->nal_reference_idc = nalu->nal_reference_idc;
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(currSlice);
UseParameterSet (currSlice->pic_parameter_set_id);
BitsUsedByHeader+= RestOfSliceHeader (currSlice);
FmoInit (active_pps, active_sps);
AssignQuantParam (active_pps, active_sps);
// if primary slice is replaced with redundant slice, set the correct image type
if(img->redundant_pic_cnt && Is_primary_correct==0 && Is_redundant_correct)
{
dec_picture->slice_type=img->type;
}
if(is_new_picture(dec_picture, currSlice, &old_slice))
{
init_picture(img, currSlice, params);
current_header = SOP;
//check zero_byte if it is also the first NAL unit in the access unit
CheckZeroByteVCL(nalu);
}
else
current_header = SOS;
init_lists(img->type, img->currentSlice->structure);
reorder_lists (img->type, img->currentSlice);
if (img->structure==FRAME)
{
init_mbaff_lists();
}
// From here on, active_sps, active_pps and the slice header are valid
if (img->MbaffFrameFlag)
img->current_mb_nr = currSlice->start_mb_nr << 1;
else
img->current_mb_nr = currSlice->start_mb_nr;
if (active_pps->entropy_coding_mode_flag)
{
int ByteStartPosition = currStream->frame_bitoffset/8;
if (currStream->frame_bitoffset%8 != 0)
{
ByteStartPosition++;
}
arideco_start_decoding (&currSlice->partArr[0].de_cabac, currStream->streamBuffer, ByteStartPosition, &currStream->read_len);
}
// printf ("read_new_slice: returning %s\n", current_header == SOP?"SOP":"SOS");
FreeNALU(nalu);
img->recovery_point = 0;
return current_header;
break;
case NALU_TYPE_DPA:
// read DP_A
currSlice->dpB_NotPresent =1;
currSlice->dpC_NotPresent =1;
img->idr_flag = FALSE;
img->nal_reference_idc = nalu->nal_reference_idc;
currSlice->dp_mode = PAR_DP_3;
currSlice->max_part_nr = 3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -