//canok 20210804
#include <stdint.h>
#include <stdio.h>
#include <sys/time.h>
#include <x264.h>
#define FAIL_IF_ERROR( cond, ... )\
do\
{\
if( cond )\
{\
fprintf( stderr, __VA_ARGS__ );\
goto fail;\
}\
} while( 0 )
int64_t getNowUs(){
struct timeval tv;
gettimeofday(&tv, 0);
return (int64_t)tv.tv_sec * 1000000 + (int64_t)tv.tv_usec;
}
int main( int argc, char **argv )
{/
int width, height;
x264_param_t param;
x264_picture_t pic;
x264_picture_t pic_out;
x264_t *h;
int i_frame = 0;
int out_frame=0;
int i_frame_size;
x264_nal_t *nal;
int i_nal;
//FAIL_IF_ERROR( !(argc > 1), "Example usage: example 352x288 <input.yuv >output.h264\n" );
if(argc !=3){
printf("usage: my_encoder WxH inputfile.yuv\n");
return -1;
}
FILE *fp_in=fopen(argv[2],"r");
if(fp_in==NULL){
printf("[%s%d] fopen err:%s\n",__FUNCTION__,__LINE__,argv[2]);
return -1;
}
FILE *fp_out=fopen("out.h264","w+");
if(fp_out==NULL){
printf("[%s%d] fopen err:out.h264 \n",__FUNCTION__,__LINE__);
return -1;
}
FAIL_IF_ERROR( 2 != sscanf( argv[1], "%dx%d", &width, &height ), "resolution not specified or incorrect\n" );
/* Get default params for preset/tuning */
#if 0
if( x264_param_default_preset( ¶m, "medium", NULL ) < 0 )
goto fail;
#else
//设置到最快
//具体参数可以看base.c::param_apply_preset
//zerolatency不延迟这个设置之后,就进一帧出一帧了,不延迟
//char speed[][16]={"ultrafast","superfast","veryfast","faster","fast","medium","slow","slower","veryslow","placebo"};
if( x264_param_default_preset( ¶m, "ultrafast", "zerolatency" ) < 0 )
//if( x264_param_default_preset( ¶m, "ultrafast", NULL ) < 0 )
goto fail;
#endif
/* Configure non-default params */
param.i_bitdepth = 8;
param.i_csp = X264_CSP_I420;//颜色空间
param.i_width = width;
param.i_height = height;
param.b_vfr_input = 0; //设置为1将控制时间戳?
param.b_repeat_headers = 1; //在每一个I帧前面加上sps pps
param.b_annexb = 1;//每一个帧携带启始码00 00 00 01,如果设置为0,则不添加00 00 00 01,而是存储这一帧的数据大小值。(占4个字节)
param.i_bframe =0; // 不使用B帧/* how many b-frame between 2 references pictures */
param.i_keyint_min = 25;
param.i_keyint_max = 35; //gop
param.rc.b_mb_tree = 0;//实时编码是强烈建议为0
//f_rf_constant 设置 33 数据速率 972kbps 图像质量还行,设置20 数据速率 2501kbps ,设置30 数据速率1520kbps
param.rc.f_rf_constant = 25;
param.rc.f_rf_constant_max = 45;
/* Apply profile restrictions. */
if( x264_param_apply_profile( ¶m, "high" ) < 0 )
goto fail;
if( x264_picture_alloc( &pic, param.i_csp, param.i_width, param.i_height ) < 0 )
goto fail;
#undef fail
#define fail fail2
h = x264_encoder_open( ¶m );
if( !h )
goto fail;
#undef fail
#define fail fail3
int luma_size = width * height;
int chroma_size = luma_size / 4;
/* Encode frames */
for( ;; i_frame++ )
{
/* Read input frame */
if( fread( pic.img.plane[0], 1, luma_size, fp_in ) != (unsigned)luma_size )
break;
if( fread( pic.img.plane[1], 1, chroma_size, fp_in ) != (unsigned)chroma_size )
break;
if( fread( pic.img.plane[2], 1, chroma_size, fp_in ) != (unsigned)chroma_size )
break;
pic.i_pts = i_frame;
int64_t t1=getNowUs();
printf("[%s%d]in:%d %ld\n",__FUNCTION__,__LINE__,i_frame, t1);
i_frame_size = x264_encoder_encode( h, &nal, &i_nal, &pic, &pic_out );
if( i_frame_size < 0 )
goto fail;
else if( i_frame_size )
{
int64_t t2=getNowUs();
printf("[%s%d]out:%d %ld\n",__FUNCTION__,__LINE__,out_frame, t2);
//SLICE_TYPE_P SLICE_TYPE_B SLICE_TYPE_I
//nal->i_type nal_unit_type_e
/*enum sei_payload_type_e
{
SEI_BUFFERING_PERIOD = 0,
SEI_PIC_TIMING = 1,
SEI_PAN_SCAN_RECT = 2,
SEI_FILLER = 3,
SEI_USER_DATA_REGISTERED = 4,
SEI_USER_DATA_UNREGISTERED = 5,
SEI_RECOVERY_POINT = 6,
SEI_DEC_REF_PIC_MARKING = 7,
SEI_FRAME_PACKING = 45,
SEI_ALTERNATIVE_TRANSFER = 147,
};*/
printf("[%s%d]in:%d---%dout,taketimes:%ld,nal->i_type:%d\n",__FUNCTION__,__LINE__,i_frame,out_frame,t2-t1,nal->i_type);
out_frame++;
if( !fwrite( nal->p_payload, i_frame_size, 1, fp_out ) )
goto fail;
}
}
/* Flush delayed frames */
//设置 "zerolatency" 之后就不会有delayed_frames了。
while( x264_encoder_delayed_frames( h ) )
{
i_frame_size = x264_encoder_encode( h, &nal, &i_nal, NULL, &pic_out );
if( i_frame_size < 0 )
goto fail;
else if( i_frame_size )
{
int64_t t2=getNowUs();
printf("[%s%d]out-delayframe:%d %ld\n",__FUNCTION__,__LINE__,out_frame, t2);
out_frame++;
if( !fwrite( nal->p_payload, i_frame_size, 1, fp_out ) )
goto fail;
}
}
x264_encoder_close( h );
x264_picture_clean( &pic );
return 0;
#undef fail
fail3:
x264_encoder_close( h );
fail2:
x264_picture_clean( &pic );
fail:
fclose(fp_in);
fclose(fp_out);
return -1;
}