📄 image.c
字号:
************************************************************************
*/
static void writeout_picture(Picture *pic)
{
int partition, slice;
Slice *currSlice;
img->currentPicture = pic;
// loop over all slices of the picture
for (slice=0; slice < pic->no_slices; slice++)
{
currSlice = pic->slices[slice];
// loop over the partitions
for (partition=0; partition < currSlice->max_part_nr; partition++)
{
// write only if the partition has content
if (currSlice->partArr[partition].bitstream->write_flag )
{
stats->bit_ctr += WriteNALU (currSlice->partArr[partition].nal_unit);
}
}
}
}
void copy_params(StorablePicture *enc_picture, seq_parameter_set_rbsp_t *active_sps)
{
enc_picture->frame_mbs_only_flag = active_sps->frame_mbs_only_flag;
enc_picture->frame_cropping_flag = active_sps->frame_cropping_flag;
enc_picture->chroma_format_idc = active_sps->chroma_format_idc;
if (active_sps->frame_cropping_flag)
{
enc_picture->frame_cropping_rect_left_offset = active_sps->frame_cropping_rect_left_offset;
enc_picture->frame_cropping_rect_right_offset = active_sps->frame_cropping_rect_right_offset;
enc_picture->frame_cropping_rect_top_offset = active_sps->frame_cropping_rect_top_offset;
enc_picture->frame_cropping_rect_bottom_offset = active_sps->frame_cropping_rect_bottom_offset;
}
else
{
enc_picture->frame_cropping_rect_left_offset = 0;
enc_picture->frame_cropping_rect_right_offset = 0;
enc_picture->frame_cropping_rect_top_offset = 0;
enc_picture->frame_cropping_rect_bottom_offset = 0;
}
}
/*!
************************************************************************
* \brief
* Prepare and allocate an encoded frame picture structure
************************************************************************
*/
static void prepare_enc_frame_picture (StorablePicture **stored_pic)
{
(*stored_pic) = alloc_storable_picture ((PictureStructure) img->structure, img->width, img->height, img->width_cr, img->height_cr);
img->ThisPOC = img->framepoc;
(*stored_pic)->poc = img->framepoc;
(*stored_pic)->top_poc = img->toppoc;
(*stored_pic)->bottom_poc = img->bottompoc;
(*stored_pic)->frame_poc = img->framepoc;
(*stored_pic)->pic_num = img->frame_num;
(*stored_pic)->frame_num = img->frame_num;
(*stored_pic)->coded_frame = 1;
(*stored_pic)->MbaffFrameFlag = img->MbaffFrameFlag = (params->MbInterlace != FRAME_CODING);
get_mb_block_pos = img->MbaffFrameFlag ? get_mb_block_pos_mbaff : get_mb_block_pos_normal;
getNeighbour = img->MbaffFrameFlag ? getAffNeighbour : getNonAffNeighbour;
enc_picture = *stored_pic;
copy_params(enc_picture, active_sps);
}
static void calc_picture_bits(Picture *frame)
{
int i, j;
Slice *thisSlice = NULL;
frame->bits_per_picture = 0;
for ( i = 0; i < frame->no_slices; i++ )
{
thisSlice = frame->slices[i];
for ( j = 0; j < thisSlice->max_part_nr; j++ )
frame->bits_per_picture += 8 * ((thisSlice->partArr[j]).bitstream)->byte_pos;
}
}
/*!
************************************************************************
* \brief
* Encodes a frame picture
************************************************************************
*/
void frame_picture (Picture *frame, int rd_pass)
{
int nplane;
img->SumFrameQP = 0;
img->structure = FRAME;
img->PicSizeInMbs = img->FrameSizeInMbs;
//set mv limits to frame type
update_mv_limits(img, FALSE);
if( IS_INDEPENDENT(params) )
{
for( nplane=0; nplane<MAX_PLANE; nplane++ )
{
prepare_enc_frame_picture( &enc_frame_picture_JV[nplane] );
}
}
else
{
prepare_enc_frame_picture( &enc_frame_picture[rd_pass] );
}
img->fld_flag = FALSE;
code_a_picture(frame);
if( IS_INDEPENDENT(params) )
{
make_frame_picture_JV();
}
calc_picture_bits(frame);
if (img->structure==FRAME)
{
find_distortion ();
frame->distortion = dist->metric[SSE];
}
}
/*!
************************************************************************
* \brief
* Encodes a field picture, consisting of top and bottom field
************************************************************************
*/
static void field_picture (Picture *top, Picture *bottom)
{
//Rate control
int old_pic_type; // picture type of top field used for rate control
int TopFieldBits;
img->SumFrameQP = 0;
//set mv limits to field type
update_mv_limits(img, TRUE);
//Rate control
old_pic_type = img->type;
img->number *= 2;
img->buf_cycle *= 2;
img->height = (params->output.height + img->auto_crop_bottom) / 2;
img->height_cr = img->height_cr_frame / 2;
img->fld_flag = TRUE;
img->PicSizeInMbs = img->FrameSizeInMbs/2;
// Top field
enc_field_picture[0] = alloc_storable_picture ((PictureStructure) img->structure, img->width, img->height, img->width_cr, img->height_cr);
enc_field_picture[0]->poc = img->toppoc;
enc_field_picture[0]->frame_poc = img->toppoc;
enc_field_picture[0]->pic_num = img->frame_num;
enc_field_picture[0]->frame_num = img->frame_num;
enc_field_picture[0]->coded_frame = 0;
enc_field_picture[0]->MbaffFrameFlag = img->MbaffFrameFlag = FALSE;
get_mb_block_pos = get_mb_block_pos_normal;
getNeighbour = getNonAffNeighbour;
img->ThisPOC = img->toppoc;
img->structure = TOP_FIELD;
enc_picture = enc_field_picture[0];
copy_params(enc_picture, active_sps);
put_buffer_top (img);
init_field (img);
if (img->type == B_SLICE) //all I- and P-frames
nextP_tr_fld--;
img->fld_flag = TRUE;
//Rate control
if(params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE)
rc_init_top_field();
code_a_picture(field_pic[0]);
enc_picture->structure = TOP_FIELD;
store_picture_in_dpb(enc_field_picture[0]);
calc_picture_bits(top);
//Rate control
TopFieldBits=top->bits_per_picture;
// Bottom field
enc_field_picture[1] = alloc_storable_picture ((PictureStructure) img->structure, img->width, img->height, img->width_cr, img->height_cr);
enc_field_picture[1]->poc=img->bottompoc;
enc_field_picture[1]->frame_poc = img->bottompoc;
enc_field_picture[1]->pic_num = img->frame_num;
enc_field_picture[1]->frame_num = img->frame_num;
enc_field_picture[1]->coded_frame = 0;
enc_field_picture[1]->MbaffFrameFlag = img->MbaffFrameFlag = FALSE;
get_mb_block_pos = get_mb_block_pos_normal;
getNeighbour = getNonAffNeighbour;
img->ThisPOC = img->bottompoc;
img->structure = BOTTOM_FIELD;
enc_picture = enc_field_picture[1];
copy_params(enc_picture, active_sps);
put_buffer_bot (img);
img->number++;
init_field (img);
if (img->type == B_SLICE) //all I- and P-frames
nextP_tr_fld++; //check once coding B field
if (img->type == I_SLICE && params->IntraBottom!=1)
set_slice_type((params->BRefPictures == 2) ? B_SLICE : P_SLICE);
img->fld_flag = TRUE;
//Rate control
if(params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE)
rc_init_bottom_field( TopFieldBits );
enc_picture->structure = BOTTOM_FIELD;
code_a_picture(field_pic[1]);
calc_picture_bits(bottom);
// the distortion for a field coded frame (consisting of top and bottom field)
// lives in the top->distortion variables, the bottom-> are dummies
distortion_fld (top);
}
/*!
************************************************************************
* \brief
* form frame picture from two field pictures
************************************************************************
*/
static void combine_field(void)
{
int i, k;
for (i = 0; i < (img->height >> 1); i++)
{
memcpy(imgY_com[i*2], enc_field_picture[0]->imgY[i], img->width*sizeof(imgpel)); // top field
memcpy(imgY_com[i*2 + 1], enc_field_picture[1]->imgY[i], img->width*sizeof(imgpel)); // bottom field
}
if (img->yuv_format != YUV400)
{
for (k = 0; k < 2; k++)
{
for (i = 0; i < (img->height_cr >> 1); i++)
{
memcpy(imgUV_com[k][i*2], enc_field_picture[0]->imgUV[k][i], img->width_cr*sizeof(imgpel));
memcpy(imgUV_com[k][i*2 + 1], enc_field_picture[1]->imgUV[k][i], img->width_cr*sizeof(imgpel));
}
}
}
}
/*!
************************************************************************
* \brief
* Distortion Field
************************************************************************
*/
static void distortion_fld (Picture *field_pic)
{
img->number /= 2;
img->buf_cycle /= 2;
img->height = (params->output.height + img->auto_crop_bottom);
img->height_cr = img->height_cr_frame;
combine_field ();
pCurImg = img_org_frm[0];
pImgOrg[0] = img_org_frm[0];
if (params->yuv_format != YUV400)
{
pImgOrg[1] = img_org_frm[1];
pImgOrg[2] = img_org_frm[2];
}
find_distortion (); // find snr from original frame picture
field_pic->distortion = dist->metric[SSE];
}
/*!
************************************************************************
* \brief
* RD decision of frame and field coding
************************************************************************
*/
static byte decide_fld_frame(float snr_frame_Y, float snr_field_Y, int bit_field, int bit_frame, double lambda_picture)
{
double cost_frame, cost_field;
cost_frame = bit_frame * lambda_picture + snr_frame_Y;
cost_field = bit_field * lambda_picture + snr_field_Y;
if (cost_field > cost_frame)
return FALSE;
else
return TRUE;
}
/*!
************************************************************************
* \brief
* Picture Structure Decision
************************************************************************
*/
static byte picture_structure_decision (Picture *frame, Picture *top, Picture *bot)
{
double lambda_picture;
int bframe = (img->type == B_SLICE);
float sse_frame, sse_field;
int bit_frame, bit_field;
lambda_picture = 0.68 * pow (2, img->bitdepth_lambda_scale + ((img->qp - SHIFT_QP) / 3.0)) * (bframe ? 1 : 1);
sse_frame = frame->distortion.value[0] + frame->distortion.value[1] + frame->distortion.value[2];
//! all distrortions of a field picture are accumulated in the top field
sse_field = top->distortion.value[0] + top->distortion.value[1] + top->distortion.value[2];
bit_field = top->bits_per_picture + bot->bits_per_picture;
bit_frame = frame->bits_per_picture;
return decide_fld_frame (sse_frame, sse_field, bit_field, bit_frame, lambda_picture);
}
/*!
************************************************************************
* \brief
* Field Mode Buffer
************************************************************************
*/
static void field_mode_buffer (ImageParameters *img, InputParameters *params)
{
put_buffer_frame (img);
}
/*!
************************************************************************
* \brief
* Frame Mode Buffer
************************************************************************
*/
static void frame_mode_buffer (ImageParameters *img, InputParameters *params)
{
put_buffer_frame (img);
if ((params->PicInterlace != FRAME_CODING)||(params->MbInterlace != FRAME_CODING))
{
img->height = img->height / 2;
img->height_cr = img->height_cr / 2;
img->number *= 2;
put_buffer_top (img);
img->number++;
put_buffer_bot (img);
img->number /= 2; // reset the img->number to field
img->height = (params->output.height + img->auto_crop_bottom);
img->height_cr = img->height_cr_frame;
put_buffer_frame (img);
}
}
/*!
************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -