📄 x264.c
字号:
int i;
if( long_options_index < 0 )
{
for( i = 0; long_options[i].name; i++ )
if( long_options[i].val == c )
{
long_options_index = i;
break;
}
if( long_options_index < 0 )
{
/* getopt_long already printed an error message */
return -1;
}
}
b_error |= x264_param_parse( param, long_options[long_options_index].name, optarg ? optarg : "true" );
}
}
if( b_error )
{
const char *name = long_options_index > 0 ? long_options[long_options_index].name : argv[optind-2];
fprintf( stderr, "x264 [error]: invalid argument: %s = %s\n", name, optarg );
return -1;
}
}
/* Get the file name */
if( optind > argc - 1 || !opt->hout )
{
fprintf( stderr, "x264 [error]: No %s file. Run x264 --help for a list of options.\n",
optind > argc - 1 ? "input" : "output" );
return -1;
}
psz_filename = argv[optind++];
/* check demuxer type */
psz = psz_filename + strlen(psz_filename) - 1;
while( psz > psz_filename && *psz != '.' )
psz--;
if( !strncasecmp( psz, ".avi", 4 ) || !strncasecmp( psz, ".avs", 4 ) )
b_avis = 1;
if( !strncasecmp( psz, ".y4m", 4 ) )
b_y4m = 1;
if( !(b_avis || b_y4m) ) // raw yuv
{
if( optind > argc - 1 )
{
/* try to parse the file name */
for( psz = psz_filename; *psz; psz++ )
{
if( *psz >= '0' && *psz <= '9'
&& sscanf( psz, "%ux%u", ¶m->i_width, ¶m->i_height ) == 2 )
{
if( param->i_log_level >= X264_LOG_INFO )
fprintf( stderr, "x264 [info]: file name gives %dx%d\n", param->i_width, param->i_height );
break;
}
}
}
else
{
sscanf( argv[optind++], "%ux%u", ¶m->i_width, ¶m->i_height );
}
}
if( !(b_avis || b_y4m) && ( !param->i_width || !param->i_height ) )
{
fprintf( stderr, "x264 [error]: Rawyuv input requires a resolution.\n" );
return -1;
}
/* open the input */
{
if( b_avis )
{
#ifdef AVIS_INPUT
p_open_infile = open_file_avis;
p_get_frame_total = get_frame_total_avis;
p_read_frame = read_frame_avis;
p_close_infile = close_file_avis;
#else
fprintf( stderr, "x264 [error]: not compiled with AVIS input support\n" );
return -1;
#endif
}
if ( b_y4m )
{
p_open_infile = open_file_y4m;
p_get_frame_total = get_frame_total_y4m;
p_read_frame = read_frame_y4m;
p_close_infile = close_file_y4m;
}
if( p_open_infile( psz_filename, &opt->hin, param ) )
{
fprintf( stderr, "x264 [error]: could not open input file '%s'\n", psz_filename );
return -1;
}
}
#ifdef HAVE_PTHREAD
if( b_thread_input || param->i_threads > 1 )
{
if( open_file_thread( NULL, &opt->hin, param ) )
{
fprintf( stderr, "x264 [warning]: threaded input failed\n" );
}
else
{
p_open_infile = open_file_thread;
p_get_frame_total = get_frame_total_thread;
p_read_frame = read_frame_thread;
p_close_infile = close_file_thread;
}
}
#endif
return 0;
}
static void parse_qpfile( cli_opt_t *opt, x264_picture_t *pic, int i_frame )
{
int num = -1, qp;
char type;
while( num < i_frame )
{
int ret = fscanf( opt->qpfile, "%d %c %d\n", &num, &type, &qp );
if( num < i_frame )
continue;
pic->i_qpplus1 = qp+1;
if ( type == 'I' ) pic->i_type = X264_TYPE_IDR;
else if( type == 'i' ) pic->i_type = X264_TYPE_I;
else if( type == 'P' ) pic->i_type = X264_TYPE_P;
else if( type == 'B' ) pic->i_type = X264_TYPE_BREF;
else if( type == 'b' ) pic->i_type = X264_TYPE_B;
else ret = 0;
if( ret != 3 || qp < 0 || qp > 51 || num > i_frame )
{
fprintf( stderr, "x264 [error]: can't parse qpfile for frame %d\n", i_frame );
fclose( opt->qpfile );
opt->qpfile = NULL;
pic->i_type = X264_TYPE_AUTO;
pic->i_qpplus1 = 0;
break;
}
}
}
/*****************************************************************************
* Decode:
*****************************************************************************/
static int Encode_frame( x264_t *h, hnd_t hout, x264_picture_t *pic )
{
x264_picture_t pic_out;
x264_nal_t *nal;
int i_nal, i;
int i_file = 0;
if( x264_encoder_encode( h, &nal, &i_nal, pic, &pic_out ) < 0 )
{
fprintf( stderr, "x264 [error]: x264_encoder_encode failed\n" );
}
for( i = 0; i < i_nal; i++ )
{
int i_size;
int i_data;
i_data = DATA_MAX;
if( ( i_size = x264_nal_encode( data, &i_data, 1, &nal[i] ) ) > 0 )
{
i_file += p_write_nalu( hout, data, i_size );
}
else if( i_size < 0 )
{
fprintf( stderr, "x264 [error]: need to increase buffer size (size=%d)\n", -i_size );
}
}
if (i_nal)
p_set_eop( hout, &pic_out );
return i_file;
}
/*****************************************************************************
* Encode:
*****************************************************************************/
static int Encode( x264_param_t *param, cli_opt_t *opt )
{
x264_t *h;
x264_picture_t pic;
int i_frame, i_frame_total;
int64_t i_start, i_end;
int64_t i_file;
int i_frame_size;
int i_progress;
i_frame_total = p_get_frame_total( opt->hin );
i_frame_total -= opt->i_seek;
if( ( i_frame_total == 0 || param->i_frame_total < i_frame_total )
&& param->i_frame_total > 0 )
i_frame_total = param->i_frame_total;
param->i_frame_total = i_frame_total;
if( ( h = x264_encoder_open( param ) ) == NULL )
{
fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" );
p_close_infile( opt->hin );
p_close_outfile( opt->hout );
return -1;
}
if( p_set_outfile_param( opt->hout, param ) )
{
fprintf( stderr, "x264 [error]: can't set outfile param\n" );
p_close_infile( opt->hin );
p_close_outfile( opt->hout );
return -1;
}
/* Create a new pic */
x264_picture_alloc( &pic, X264_CSP_I420, param->i_width, param->i_height );
i_start = x264_mdate();
/* Encode frames */
for( i_frame = 0, i_file = 0, i_progress = 0;
b_ctrl_c == 0 && (i_frame < i_frame_total || i_frame_total == 0); )
{
if( p_read_frame( &pic, opt->hin, i_frame + opt->i_seek ) )
break;
pic.i_pts = (int64_t)i_frame * param->i_fps_den;
if( opt->qpfile )
parse_qpfile( opt, &pic, i_frame + opt->i_seek );
else
{
/* Do not force any parameters */
pic.i_type = X264_TYPE_AUTO;
pic.i_qpplus1 = 0;
}
i_file += Encode_frame( h, opt->hout, &pic );
i_frame++;
/* update status line (up to 1000 times per input file) */
if( opt->b_progress && param->i_log_level < X264_LOG_DEBUG &&
( i_frame_total ? i_frame * 1000 / i_frame_total > i_progress
: i_frame % 10 == 0 ) )
{
int64_t i_elapsed = x264_mdate() - i_start;
double fps = i_elapsed > 0 ? i_frame * 1000000. / i_elapsed : 0;
if( i_frame_total )
{
int eta = (int)(i_elapsed * (i_frame_total - i_frame) / ((int64_t)i_frame * 1000000));
i_progress = i_frame * 1000 / i_frame_total;
fprintf( stderr, "encoded frames: %d/%d (%.1f%%), %.2f fps, eta %d:%02d:%02d \r",
i_frame, i_frame_total, (float)i_progress / 10, fps,
eta/3600, (eta/60)%60, eta%60 );
}
else
fprintf( stderr, "encoded frames: %d, %.2f fps \r", i_frame, fps );
fflush( stderr ); // needed in windows
}
}
/* Flush delayed B-frames */
do {
i_file +=
i_frame_size = Encode_frame( h, opt->hout, NULL );
} while( i_frame_size );
i_end = x264_mdate();
x264_picture_clean( &pic );
x264_encoder_close( h );
fprintf( stderr, "\n" );
if( b_ctrl_c )
fprintf( stderr, "aborted at input frame %d\n", opt->i_seek + i_frame );
p_close_infile( opt->hin );
p_close_outfile( opt->hout );
if( i_frame > 0 )
{
double fps = (double)i_frame * (double)1000000 /
(double)( i_end - i_start );
fprintf( stderr, "encoded %d frames, %.2f fps, %.2f kb/s\n", i_frame, fps,
(double) i_file * 8 * param->i_fps_num /
( (double) param->i_fps_den * i_frame * 1000 ) );
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -