您的位置:首页 > 其它

x264 帧由显示顺序到编码顺序的调整过程 框架

2013-04-12 16:10 357 查看
typedef struct x264_lookahead_t
{
volatile uint8_t              b_exit_thread;
uint8_t                       b_thread_active;
uint8_t                       b_analyse_keyframe;
int                           i_last_keyframe;
int                           i_slicetype_length;
x264_frame_t                  *last_nonb;
x264_pthread_t                thread_handle;
x264_sync_frame_list_t        ifbuf;

x264_sync_frame_list_t        next;
x264_sync_frame_list_t        ofbuf;

} x264_lookahead_t_f;

//
void frame_buffer()
{
x264_picture_t pic;
cli_opt_t *opt;
x264_t* handle;
int64_t last_dts;

//step1
pic.i_type = X264_TYPE_AUTO;

Encode_frame_fred( handle, opt->hout, &pic, &last_dts );
}

int Encode_frame_fred( x264_t *h, hnd_t hout, x264_picture_t *pic, int64_t *last_dts )
{
x264_picture_t pic_out;
x264_nal_t *nal;
int i_nal;
int i_frame_size = 0;

i_frame_size = x264_encoder_encode_fred( h, &nal, &i_nal, pic, &pic_out );

FAIL_IF_ERROR( i_frame_size < 0, "x264_encoder_encode failed\n" );

if( i_frame_size )
{
i_frame_size = output.write_frame( hout, nal[0].p_payload, i_frame_size, &pic_out );
*last_dts = pic_out.i_dts;
}

return i_frame_size;
}

int x264_encoder_encode_fred( x264_t *h,
x264_nal_t **pp_nal, int *pi_nal,
x264_picture_t *pic_in,
x264_picture_t *pic_out )
{
x264_t *thread_current, *thread_prev, *thread_oldest;
int i_nal_type, i_nal_ref_idc, i_global_qp;
int overhead = NALU_OVERHEAD;

// ok to call this before encoding any frames, since the initial values of fdec have b_kept_as_ref=0
if( x264_reference_update( h ) )
return -1;

h->fdec->i_lines_completed = -1;

/* no data out */
*pi_nal = 0;
*pp_nal = NULL;

/* ------------------- Setup new frame from picture -------------------- */
if( pic_in != NULL )
{
/* 1: Copy the picture to a frame and move it to a buffer */
x264_frame_t *fenc = x264_frame_pop_unused( h, 0 );
if( !fenc )
return -1;

//move input to fenc
if( x264_frame_copy_picture( h, fenc, pic_in ) < 0 )
return -1;

if( h->param.i_width != 16 * h->mb.i_mb_width ||
h->param.i_height != 16 * h->mb.i_mb_height )
x264_frame_expand_border_mod16( h, fenc );

fenc->i_frame = h->frames.i_input++;

if( h->frames.b_have_lowres )
x264_frame_init_lowres( h, fenc );

//step2  move fenc to lookahead->next
x264_lookahead_put_frame( h, fenc );

//waiting for B
if( h->frames.i_input <= h->frames.i_delay + 1 - h->i_thread_frames )
{
/* Nothing yet to encode, waiting for filling of buffers */
pic_out->i_type = X264_TYPE_AUTO;
return 0;
}
}
else
{
/* signal kills for lookahead thread */
x264_pthread_mutex_lock( &h->lookahead->ifbuf.mutex );
h->lookahead->b_exit_thread = 1;
x264_pthread_cond_broadcast( &h->lookahead->ifbuf.cv_fill );
x264_pthread_mutex_unlock( &h->lookahead->ifbuf.mutex );
}

h->i_frame++;

///step3 pump data to current[], on needs
if( !h->frames.current[0] )
x264_lookahead_get_frames_fred( h );

if( !h->frames.current[0] )
return x264_encoder_frame_end( thread_oldest, thread_current, pp_nal, pi_nal, pic_out );

//step4 Get frame to be encoded from current[0]
h->fenc = x264_frame_shift( h->frames.current );

}

void x264_lookahead_get_frames_fred( x264_t *h )
{
//step3.1   decide frame type and reorder frame to encode order
x264_slicetype_decide_fred( h );

//step 3.2  move frames from lookahead->next  to    lookahead->ofbuf
// next.list[0] must be I Idr or P
x264_lookahead_shift( &h->lookahead->ofbuf, &h->lookahead->next, h->lookahead->next.list[0]->i_bframes + 1 );

//step 3.3  move frames  from lookahead->ofbuf  to   h->frames.current
x264_lookahead_encoder_shift( h );
}

void x264_slicetype_decide_fred( x264_t *h )
{
x264_frame_t *frames[X264_BFRAME_MAX+2];
x264_frame_t *frm;
int bframes;
int brefs;

// step 3.1.1 set frame type ; eg list[] = {b b b b ...P/I};  i b b b p-idr
for( bframes = 0, brefs = 0;; bframes++ )
{
frm = h->lookahead->next.list[bframes];

if( frm->i_type == X264_TYPE_KEYFRAME )
frm->i_type = h->param.i_open_gop ? X264_TYPE_I : X264_TYPE_IDR;

/* force set I or Idr because Limit GOP size */
if( (!h->param.b_intra_refresh || frm->i_frame == 0) && frm->i_frame - h->lookahead->i_last_keyframe >= h->param.i_keyint_max )
{
if( frm->i_type == X264_TYPE_AUTO || frm->i_type == X264_TYPE_I )
frm->i_type = h->param.i_open_gop && h->lookahead->i_last_keyframe >= 0 ? X264_TYPE_I : X264_TYPE_IDR;

int warn = frm->i_type != X264_TYPE_IDR;
if( warn && h->param.i_open_gop )
warn &= frm->i_type != X264_TYPE_I;

if( warn )
x264_log( h, X264_LOG_WARNING, "specified frame type (%d) at %d is not compatible with keyframe interval\n", frm->i_type, frm->i_frame );
}

if( frm->i_type == X264_TYPE_I && frm->i_frame - h->lookahead->i_last_keyframe >= h->param.i_keyint_min )
{
if( h->param.i_open_gop )
{
h->lookahead->i_last_keyframe = frm->i_frame; // Use display order

frm->b_keyframe = 1;
}
else
frm->i_type = X264_TYPE_IDR;
}

//current is idr, prev frame must be p
if( frm->i_type == X264_TYPE_IDR )
{
/* Close GOP */
h->lookahead->i_last_keyframe = frm->i_frame;
frm->b_keyframe = 1;

if( bframes > 0 )
{
bframes--;
h->lookahead->next.list[bframes]->i_type = X264_TYPE_P;
}
}

//.....连续B帧数量到达最大B帧要求  或者已经遍历完next中所有帧,则设置P帧;
if( bframes == h->param.i_bframe ||
!h->lookahead->next.list[bframes+1] )
{
if( frm->i_type == X264_TYPE_AUTO || IS_X264_TYPE_B( frm->i_type ) )
frm->i_type = X264_TYPE_P;
}

if( frm->i_type == X264_TYPE_AUTO )
frm->i_type = X264_TYPE_B;
else if( !IS_X264_TYPE_B( frm->i_type ) ) // fred normal is P, or I or IDR
break;

}

if( bframes )
h->lookahead->next.list[bframes-1]->b_last_minigop_bframe = 1;

h->lookahead->next.list[bframes]->i_bframes = bframes;//p or i or idr

//step 3.1.2 reorder to pbbbb
if( bframes )
{
int idx_list[] = { brefs+1, 1 };//two type, count separately

//
for( int i = 0; i < bframes; i++ )
{
int idx = idx_list[ h->lookahead->next.list[i]->i_type == X264_TYPE_BREF ]++;
frames[idx] = h->lookahead->next.list[i];
frames[idx]->i_reordered_pts = h->lookahead->next.list[idx]->i_pts;
}

frames[0] = h->lookahead->next.list[bframes];
frames[0]->i_reordered_pts = h->lookahead->next.list[0]->i_pts;

memcpy( h->lookahead->next.list, frames, (bframes+1) * sizeof(x264_frame_t*) );
}

}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: