📄 encoder.c
字号:
h->frame_next[i] = NULL;
h->frame_unused[i] = NULL;
}
h->frame_next[X264_BFRAME_MAX] = NULL;
h->frame_unused[X264_BFRAME_MAX]= NULL;
for( i = 0; i < h->param.i_bframe+1; i++ )
{
h->frame_unused[i] = x264_frame_new( h );
}
h->mb = x264_macroblocks_new( h->sps->i_mb_width, h->sps->i_mb_height );
// reference frame (2 for B frame) and current one
for( i = 0; i < h->param.i_frame_reference+2; i++ )
{
h->freference[i] = x264_frame_new( h );
}
h->fdec = h->freference[0];
h->i_ref0 = 0;
h->i_ref1 = 0;
/* init cabac adaptive model */
x264_cabac_model_init( &h->cabac );
/* init predict_XxX */
x264_predict_16x16_init( h->predict_16x16 );
x264_predict_8x8_init( h->predict_8x8 );
x264_predict_4x4_init( h->predict_4x4 );
x264_pixel_init( &h->pixf );
x264_dct_init( &h->dctf );
x264_mc_init( h->mc );
x264_me_init( me );
h->me = me[h->param.i_me];
/* rate control */
h->rc = x264_ratecontrol_new( &h->param );
return h;
}
/****************************************************************************
* x264_nal_encode:
****************************************************************************/
int x264_nal_encode( unsigned char *p_data, int *pi_data, int b_annexeb, x264_nal_t *nal )
{
uint8_t *dst = p_data;
uint8_t *src = nal->p_payload;
uint8_t *end = &nal->p_payload[nal->i_payload];
int i_count = 0;
/* FIXME this code doesn't check overflow */
if( b_annexeb )
{
/* long nal start code (we always use long ones)*/
*dst++ = 0x00;
*dst++ = 0x00;
*dst++ = 0x00;
*dst++ = 0x01;
}
/* nal header */
*dst++ = ( 0x00 << 7 ) | ( nal->i_ref_idc << 5 ) | nal->i_type;
while( src < end )
{
if( i_count == 2 && *src <= 0x03 )
{
*dst++ = 0x03;
i_count = 0;
}
if( *src == 0 )
{
i_count++;
}
else
{
i_count = 0;
}
*dst++ = *src++;
}
*pi_data = dst - (uint8_t*)p_data;
return *pi_data;
}
/* internal usage */
static void x264_nal_start( x264_t *h, int i_type, int i_ref_idc )
{
x264_nal_t *nal = &h->nal[h->i_nal];
nal->i_ref_idc = i_ref_idc;
nal->i_type = i_type;
bs_align_0( &h->bs ); /* not needed */
nal->i_payload= 0;
nal->p_payload= &h->p_bitstream[bs_pos( &h->bs) / 8];
}
static void x264_nal_end( x264_t *h )
{
x264_nal_t *nal = &h->nal[h->i_nal];
bs_align_0( &h->bs ); /* not needed */
nal->i_payload = &h->p_bitstream[bs_pos( &h->bs) / 8] - nal->p_payload;
h->i_nal++;
}
/****************************************************************************
* x264_encoder_headers:
****************************************************************************/
int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal)
{
/* init bitstream context */
h->i_nal = 0;
bs_init( &h->bs, h->p_bitstream, h->i_bitstream );
/* Put SPS and PPS */
if( h->i_frame == 0 )
{
/* generate sequence parameters */
x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST );
x264_sps_write( &h->bs, h->sps );
x264_nal_end( h );
/* generate picture parameters */
x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST );
x264_pps_write( &h->bs, h->pps );
x264_nal_end( h );
}
/* now set output*/
*pi_nal = h->i_nal;
*pp_nal = &h->nal[0];
return 0;
}
static void x264_encoder_frame_put( x264_frame_t *buffer[X264_BFRAME_MAX], x264_frame_t *frame )
{
int i;
/* put the frame in buffer */
for( i = 0; buffer[i] != NULL; i++ )
{
if( i >= X264_BFRAME_MAX )
{
fprintf( stderr, "not enough room\n" );
return;
}
}
buffer[i] = frame;
}
static x264_frame_t *x264_encoder_frame_put_from_picture( x264_t *h, x264_frame_t *buffer[X264_BFRAME_MAX], x264_picture_t *picture )
{
int i;
x264_frame_t *frame;
/* get an unused bframe */
frame = h->frame_unused[0];
for( i = 0; i < X264_BFRAME_MAX; i++ )
{
h->frame_unused[i] = h->frame_unused[i+1];
}
h->frame_unused[X264_BFRAME_MAX] = NULL;
/* copy the picture in it */
x264_frame_copy_picture( frame, picture );
/* put the frame in buffer */
x264_encoder_frame_put( buffer, frame );
buffer[i] = frame;
return frame;
}
static x264_frame_t *x264_encoder_frame_get( x264_frame_t *buffer[X264_BFRAME_MAX])
{
int i;
x264_frame_t *frame = buffer[0];
for( i = 0; i < X264_BFRAME_MAX-1; i++ )
{
buffer[i] = buffer[i+1];
}
buffer[X264_BFRAME_MAX-1] = NULL;
return frame;
}
static int64_t i_mtime_analyse = 0;
static int64_t i_mtime_encode = 0;
static int64_t i_mtime_write = 0;
static int64_t i_mtime_filter = 0;
#define TIMER_START( d ) \
{ \
int64_t d##start = x264_mdate();
#define TIMER_STOP( d ) \
d += x264_mdate() - d##start;\
}
/****************************************************************************
* x264_encoder_encode:
* XXX: i_poc : is the poc of the current given picture
* i_frame : is the number of the frame being coded
* ex: type frame poc
* I 0 2*0
* P 1 2*3
* B 2 2*1
* B 3 2*2
* P 4 2*6
* B 5 2*4
* B 6 2*5
****************************************************************************/
//static x264_frame_t * recon_temp;
int x264_encoder_encode( x264_t *h,
x264_nal_t **pp_nal, int *pi_nal,
x264_picture_t *pic)
{
x264_picture_t picture_tmp;
x264_frame_t *frame_psnr = h->fdec; /* just to kept the current decoded frame for psnr calculation */
int i_nal_type;
int i_nal_ref_idc;
int i_slice_type;
int mb_xy;
int i;
int i_skip;
int b_ok;
float psnr_y, psnr_u, psnr_v;
/* no data out */
*pp_nal = NULL;
*pi_nal = 0;
/* ------------------- Select slice type and frame --------------------- */
if( h->i_frame % (h->param.i_iframe * h->param.i_idrframe) == 0 )
{
i_nal_type = NAL_SLICE_IDR;
i_nal_ref_idc = NAL_PRIORITY_HIGHEST;
i_slice_type = SLICE_TYPE_I;
/* we encode the given frame */
h->picture = pic;
/* null poc */
h->i_poc = 0;
h->fdec->i_poc = 0;
/* null frame */
h->i_frame_num = 0;
/* reset ref pictures */
for( i = 1; i < h->param.i_frame_reference+2; i++ )
{
h->freference[i]->i_poc = -1;
}
h->freference[0]->i_poc = 0;
}
else
{
/* TODO detect scene changes and switch to I slice */
if( h->param.i_bframe > 0 )
{
x264_frame_t *frame;
// TODO avoid always doing x264_encoder_frame_put_from_picture */
// TODO implement adaptive B frame patern (not fixed one)*/
// put the current picture in frame_next */
frame = x264_encoder_frame_put_from_picture( h, h->frame_next, pic );
frame->i_poc = h->i_poc;
// get the frame to be encoded */
if( h->bframe_current[0] )
{
frame = x264_encoder_frame_get( h->bframe_current );
i_slice_type = SLICE_TYPE_B;
}
else if( h->frame_next[h->param.i_bframe] == NULL )
{
// not enough b-frame yet */
frame = NULL;
i_slice_type = -1;
}
else
{
int i_mod = h->i_frame % h->param.i_iframe;
if( i_mod == 0 )
{
i_slice_type = SLICE_TYPE_I;
frame = x264_encoder_frame_get( h->frame_next );
}
else
{
int i;
for( i = 0; i < h->param.i_bframe; i++ )
{
h->bframe_current[i] = x264_encoder_frame_get( h->frame_next );
}
frame = x264_encoder_frame_get( h->frame_next );
i_slice_type = SLICE_TYPE_P;
}
}
if( frame )
{
h->picture = &picture_tmp;
for( i = 0; i < frame->i_plane; i++ )
{
h->picture->i_stride[i] = frame->i_stride[i];
h->picture->plane[i] = frame->plane[i];
}
h->fdec->i_poc = frame->i_poc;
x264_encoder_frame_put( h->frame_unused, frame ); /* it's ok to do it now */
}
else
{
h->picture = NULL;
}
}
else
{
i_slice_type = h->i_frame % h->param.i_iframe == 0 ? SLICE_TYPE_I : SLICE_TYPE_P;
/* we encode the given frame */
h->picture = pic;
h->fdec->i_poc = h->i_poc; /* low delay */
}
i_nal_type = NAL_SLICE;
if( i_slice_type == SLICE_TYPE_I || i_slice_type == SLICE_TYPE_P )
{
i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/
}
else /* if( i_slice_type == SLICE_TYPE_B ) */
{
i_nal_ref_idc = NAL_PRIORITY_DISPOSABLE;
}
}
/* increase poc */
h->i_poc += 2;
if( h->picture == NULL )
{
/* waiting for filling bframe buffer */
return 0;
}
/* increase frame num but only once for B frame */
if( i_slice_type != SLICE_TYPE_B || h->sh.i_type != SLICE_TYPE_B )
{
h->i_frame_num++;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -