{
y4m_hnd_t *h = handle;
int i_frame_total = 0;
- uint64_t init_pos = ftell( h->fh );
- if( !fseek( h->fh, 0, SEEK_END ) )
+ if( x264_is_regular_file( h->fh ) )
{
+ uint64_t init_pos = ftell( h->fh );
+ fseek( h->fh, 0, SEEK_END );
uint64_t i_size = ftell( h->fh );
fseek( h->fh, init_pos, SEEK_SET );
i_frame_total = (int)((i_size - h->seq_header_len) /
return i_frame_total;
}
-static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
+static int read_frame_internal( x264_picture_t *p_pic, y4m_hnd_t *h )
{
- y4m_hnd_t *h = handle;
int slen = strlen( Y4M_FRAME_MAGIC );
int i = 0;
char header[16];
- if( i_frame != h->next_frame )
- {
- if( fseek( h->fh, (uint64_t)i_frame*(3*(h->width*h->height)/2+h->frame_header_len)
- + h->seq_header_len, SEEK_SET ) )
- return -1;
- }
-
/* Read frame header - without terminating '\n' */
if( fread( header, 1, slen, h->fh ) != slen )
return -1;
}
h->frame_header_len = i+slen+1;
- if( fread( p_pic->img.plane[0], 1, h->width*h->height, h->fh ) <= 0
- || fread( p_pic->img.plane[1], 1, h->width * h->height / 4, h->fh ) <= 0
- || fread( p_pic->img.plane[2], 1, h->width * h->height / 4, h->fh ) <= 0 )
+ if( fread( p_pic->img.plane[0], h->width * h->height, 1, h->fh ) <= 0
+ || fread( p_pic->img.plane[1], h->width * h->height / 4, 1, h->fh ) <= 0
+ || fread( p_pic->img.plane[2], h->width * h->height / 4, 1, h->fh ) <= 0 )
return -1;
- h->next_frame = i_frame+1;
+ return 0;
+}
+static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
+{
+ y4m_hnd_t *h = handle;
+
+ if( i_frame > h->next_frame )
+ {
+ if( x264_is_regular_file( h->fh ) )
+ fseek( h->fh, (uint64_t)i_frame*(3*(h->width*h->height)/2+h->frame_header_len)
+ + h->seq_header_len, SEEK_SET );
+ else
+ while( i_frame > h->next_frame )
+ {
+ if( read_frame_internal( p_pic, h ) )
+ return -1;
+ h->next_frame++;
+ }
+ }
+
+ if( read_frame_internal( p_pic, h ) )
+ return -1;
+
+ h->next_frame = i_frame+1;
return 0;
}
cli_input_t input;
static cli_output_t output;
+/* i/o modules that work with pipes (and fifos) */
+static const char * const stdin_format_names[] = { "yuv", "y4m", 0 };
+static const char * const stdout_format_names[] = { "raw", "mkv", 0 };
+
static void Help( x264_param_t *defaults, int longhelp );
static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt );
static int Encode( x264_param_t *param, cli_opt_t *opt );
H0( "Input/Output:\n" );
H0( "\n" );
H0( " -o, --output Specify output file\n" );
+ H1( " --stdout Specify stdout format [\"%s\"]\n"
+ " - raw, mkv\n", stdout_format_names[0] );
+ H1( " --stdin Specify stdin format [\"%s\"]\n"
+ " - yuv, y4m\n", stdin_format_names[0] );
H0( " --sar width:height Specify Sample Aspect Ratio\n" );
H0( " --fps <float|rational> Specify framerate\n" );
H0( " --seek <integer> First frame to encode\n" );
#define OPT_SLOWFIRSTPASS 267
#define OPT_FULLHELP 268
#define OPT_FPS 269
+#define OPT_STDOUT_FORMAT 270
+#define OPT_STDIN_FORMAT 271
static char short_options[] = "8A:B:b:f:hI:i:m:o:p:q:r:t:Vvw";
static struct option long_options[] =
{ "frames", required_argument, NULL, OPT_FRAMES },
{ "seek", required_argument, NULL, OPT_SEEK },
{ "output", required_argument, NULL, 'o' },
+ { "stdout", required_argument, NULL, OPT_STDOUT_FORMAT },
+ { "stdin", required_argument, NULL, OPT_STDIN_FORMAT },
{ "analyse", required_argument, NULL, 0 },
{ "partitions", required_argument, NULL, 'A' },
{ "direct", required_argument, NULL, 0 },
{0, 0, 0, 0}
};
+static int select_output( char *filename, const char *pipe_format )
+{
+ char *ext = filename + strlen( filename ) - 1;
+ while( *ext != '.' && ext > filename )
+ ext--;
+
+ if( !strcasecmp( ext, ".mp4" ) )
+ {
+#ifdef MP4_OUTPUT
+ output = mp4_output;
+#else
+ fprintf( stderr, "x264 [error]: not compiled with MP4 output support\n" );
+ return -1;
+#endif
+ }
+ else if( !strcasecmp( ext, ".mkv" ) || (!strcmp( filename, "-" ) && !strcasecmp( pipe_format, "mkv" )) )
+ output = mkv_output;
+ else
+ output = raw_output;
+ return 0;
+}
+
+static int select_input( char *filename, char *resolution, const char *pipe_format, x264_param_t *param )
+{
+ char *psz = filename + strlen( filename ) - 1;
+ while( psz > filename && *psz != '.' )
+ psz--;
+
+ if( !strcasecmp( psz, ".avi" ) || !strcasecmp( psz, ".avs" ) )
+ {
+#ifdef AVIS_INPUT
+ input = avis_input;
+#else
+ fprintf( stderr, "x264 [error]: not compiled with AVIS input support\n" );
+ return -1;
+#endif
+ }
+ else if( !strcasecmp( psz, ".y4m" ) || (!strcmp( filename, "-" ) && !strcasecmp( pipe_format, "y4m" )) )
+ input = y4m_input;
+ else // yuv
+ {
+ if( !resolution )
+ {
+ /* try to parse the file name */
+ for( 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]: %dx%d (given by file name) @ %.2f fps\n", param->i_width,
+ param->i_height, (double)param->i_fps_num / param->i_fps_den );
+ break;
+ }
+ }
+ else
+ {
+ sscanf( resolution, "%ux%u", ¶m->i_width, ¶m->i_height );
+ if( param->i_log_level >= X264_LOG_INFO )
+ fprintf( stderr, "x264 [info]: %dx%d @ %.2f fps\n", param->i_width, param->i_height,
+ (double)param->i_fps_num / param->i_fps_den );
+ }
+ if( !param->i_width || !param->i_height )
+ {
+ fprintf( stderr, "x264 [error]: Rawyuv input requires a resolution.\n" );
+ return -1;
+ }
+ input = yuv_input;
+ }
+
+ return 0;
+}
+
/*****************************************************************************
* Parse:
*****************************************************************************/
static int Parse( int argc, char **argv,
x264_param_t *param, cli_opt_t *opt )
{
- char *psz_filename = NULL;
+ char *input_filename = NULL;
+ const char *stdin_format = stdin_format_names[0];
+ char *output_filename = NULL;
+ const char *stdout_format = stdout_format_names[0];
x264_param_t defaults = *param;
- char *psz;
char *profile = NULL;
- int b_avis = 0;
- int b_y4m = 0;
int b_thread_input = 0;
int b_turbo = 1;
int b_pass1 = 0;
int b_user_ref = 0;
int b_user_fps = 0;
+ int i;
memset( opt, 0, sizeof(cli_opt_t) );
opt->b_progress = 1;
- /* Default i/o modules */
- input = yuv_input;
- output = raw_output;
-
/* Presets are applied before all other options. */
for( optind = 0;; )
{
opt->i_seek = atoi( optarg );
break;
case 'o':
- if( !strncasecmp(optarg + strlen(optarg) - 4, ".mp4", 4) )
+ output_filename = optarg;
+ break;
+ case OPT_STDOUT_FORMAT:
+ for( i = 0; stdout_format_names[i] && strcasecmp( stdout_format_names[i], optarg ); )
+ i++;
+ if( !stdout_format_names[i] )
{
-#ifdef MP4_OUTPUT
- output = mp4_output;
-#else
- fprintf( stderr, "x264 [error]: not compiled with MP4 output support\n" );
+ fprintf( stderr, "x264 [error]: invalid stdout format `%s'\n", optarg );
return -1;
-#endif
}
- else if( !strncasecmp(optarg + strlen(optarg) - 4, ".mkv", 4) )
- output = mkv_output;
- if( !strcmp(optarg, "-") )
- opt->hout = stdout;
- else if( output.open_file( optarg, &opt->hout ) )
+ stdout_format = optarg;
+ break;
+ case OPT_STDIN_FORMAT:
+ for( i = 0; stdin_format_names[i] && strcasecmp( stdin_format_names[i], optarg ); )
+ i++;
+ if( !stdin_format_names[i] )
{
- fprintf( stderr, "x264 [error]: can't open output file `%s'\n", optarg );
+ fprintf( stderr, "x264 [error]: invalid stdin format `%s'\n", optarg );
return -1;
}
+ stdin_format = optarg;
break;
case OPT_QPFILE:
opt->qpfile = fopen( optarg, "rb" );
fprintf( stderr, "x264 [error]: can't open `%s'\n", optarg );
return -1;
}
+ else if( !x264_is_regular_file( opt->qpfile ) )
+ {
+ fprintf( stderr, "x264 [error]: qpfile incompatible with non-regular file `%s'\n", optarg );
+ fclose( opt->qpfile );
+ return -1;
+ }
break;
case OPT_THREAD_INPUT:
b_thread_input = 1;
}
/* Get the file name */
- if( optind > argc - 1 || !opt->hout )
+ if( optind > argc - 1 || !output_filename )
{
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;
+ input_filename = argv[optind++];
- if( !(b_avis || b_y4m) ) // raw yuv
+ if( select_output( output_filename, stdout_format ) )
+ return -1;
+ if( output.open_file( output_filename, &opt->hout ) )
{
- 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]: %dx%d (given by file name) @ %.2f fps\n", param->i_width, param->i_height, (double)param->i_fps_num / (double)param->i_fps_den);
- break;
- }
- }
- }
- else
- {
- sscanf( argv[optind++], "%ux%u", ¶m->i_width, ¶m->i_height );
- if( param->i_log_level >= X264_LOG_INFO )
- fprintf( stderr, "x264 [info]: %dx%d @ %.2f fps\n", param->i_width, param->i_height, (double)param->i_fps_num / (double)param->i_fps_den);
- }
+ fprintf( stderr, "x264 [error]: could not open output file `%s'\n", output_filename );
+ return -1;
}
- if( !(b_avis || b_y4m) && ( !param->i_width || !param->i_height ) )
- {
- fprintf( stderr, "x264 [error]: Rawyuv input requires a resolution.\n" );
+ if( select_input( input_filename, optind < argc ? argv[optind++] : NULL, stdin_format, param ) )
return -1;
- }
- /* open the input */
{
int i_fps_num = param->i_fps_num;
int i_fps_den = param->i_fps_den;
- if( b_avis )
- {
-#ifdef AVIS_INPUT
- input = avis_input;
-#else
- fprintf( stderr, "x264 [error]: not compiled with AVIS input support\n" );
- return -1;
-#endif
- }
- if( b_y4m )
- input = y4m_input;
- if( input.open_file( psz_filename, &opt->hin, param ) )
+ if( input.open_file( input_filename, &opt->hin, param ) )
{
- fprintf( stderr, "x264 [error]: could not open input file '%s'\n", psz_filename );
+ fprintf( stderr, "x264 [error]: could not open input file `%s'\n", input_filename );
return -1;
}
/* Restore the user's frame rate if fps has been explicitly set on the commandline. */
{
pic->i_type = X264_TYPE_AUTO;
pic->i_qpplus1 = 0;
- fseek( opt->qpfile , file_pos , SEEK_SET );
+ fseek( opt->qpfile, file_pos, SEEK_SET );
break;
}
if( num < i_frame && ret == 3 )
opt->b_progress &= param->i_log_level < X264_LOG_DEBUG;
i_frame_total = input.get_frame_total( opt->hin );
- i_frame_total -= opt->i_seek;
+ i_frame_total = X264_MAX( i_frame_total - opt->i_seek, 0 );
if( ( i_frame_total == 0 || param->i_frame_total < i_frame_total )
&& param->i_frame_total > 0 )
i_frame_total = param->i_frame_total;