]> git.sesse.net Git - x264/blob - x264.c
* all: Patches by Loren Merritt:
[x264] / x264.c
1 /*****************************************************************************
2  * x264: h264 encoder/decoder testing program.
3  *****************************************************************************
4  * Copyright (C) 2003 Laurent Aimar
5  * $Id: x264.c,v 1.1 2004/06/03 19:24:12 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #include <math.h>
29
30 #include <signal.h>
31 #define _GNU_SOURCE
32 #include <getopt.h>
33
34 #ifdef _MSC_VER
35 #include <io.h>     /* _setmode() */
36 #include <fcntl.h>  /* _O_BINARY */
37 #endif
38
39 #include "core/common.h"
40 #include "x264.h"
41
42 #define DATA_MAX 3000000
43 uint8_t data[DATA_MAX];
44
45 /* Ctrl-C handler */
46 static int     i_ctrl_c = 0;
47 static void    SigIntHandler( int a )
48 {
49     i_ctrl_c = 1;
50 }
51
52 static void Help( void );
53 static int  Parse( int argc, char **argv, x264_param_t  *param, FILE **p_fin, FILE **p_fout, int *pb_decompress );
54 static int  Encode( x264_param_t  *param, FILE *fyuv,  FILE *fout );
55 static int  Decode( x264_param_t  *param, FILE *fh26l, FILE *fout );
56
57 /****************************************************************************
58  * main:
59  ****************************************************************************/
60 int main( int argc, char **argv )
61 {
62     x264_param_t param;
63
64     FILE    *fout;
65     FILE    *fin;
66
67     int     b_decompress;
68     int     i_ret;
69
70 #ifdef _MSC_VER
71     _setmode(_fileno(stdin), _O_BINARY);    /* thanks to Marcos Morais <morais at dee.ufcg.edu.br> */
72     _setmode(_fileno(stdout), _O_BINARY);
73 #endif
74
75     x264_param_default( &param );
76
77     /* Parse command line */
78     if( Parse( argc, argv, &param, &fin, &fout, &b_decompress ) < 0 )
79     {
80         return -1;
81     }
82
83     /* Control-C handler */
84     signal( SIGINT, SigIntHandler );
85
86     if( b_decompress )
87         i_ret = Decode( &param, fin, fout );
88     else
89         i_ret = Encode( &param, fin, fout );
90
91     return i_ret;
92 }
93
94 /*****************************************************************************
95  * Help:
96  *****************************************************************************/
97 static void Help( void )
98 {
99     fprintf( stderr,
100              "x264 build:0x%4.4x\n"
101              "Syntax: x264 [options] [-o out.h26l] in.yuv widthxheigh\n"
102              "\n"
103              "  -h, --help                  Print this help\n"
104              "\n"
105              "  -I, --idrframe <integer>    Each 'number' I frames are IDR frames\n"
106              "  -i, --iframe <integer>      Frequency of I frames\n"
107              "  -b, --bframe <integer>      Number of B-frames between I and P\n"
108              "\n"
109              "  -c, --cabac                 Enable CABAC\n"
110              "  -r, --ref <integer>         Number of references\n"
111              "  -n, --nf                    Disable loop filter\n"
112              "  -f, --filter <alpha:beta>   Loop filter AplhaCO and Beta parameters\n"
113              "\n"
114              "  -q, --qp <integer>          Set QP\n"
115              "  -B, --bitrate <integer>     Set bitrate\n"
116              "      --qpmin <integer>       Set min QP\n"
117              "      --qpmax <integer>       Set max QP\n"
118              "      --qpstep <integer>      Set max QP step\n"
119              "      --rcsens <integer>      RC sensitivity\n"
120              "      --rcbuf <integer>       Size of VBV buffer\n"
121              "      --rcinitbuf <integer>   Initial VBV buffer occupancy\n"
122              "      --ipratio <float>       QP factor between I and P\n"
123              "      --pbratio <float>       QP factor between P and B\n"
124              "\n"
125              "  -p, --pass <1|2>            Enable 2 pass ratecontrol\n"
126              "      --stats <string>        Filename for 2 pass stats\n"
127              "      --rceq <string>         Ratecontrol equation\n"
128              "      --qcomp <float>         0.0 => CBR, 1.0 => CQP, 0.6 => default\n"
129              "\n"
130
131              "  -A, --analyse <string>      Analyse options:\n"
132              "                                  - i4x4\n"
133              "                                  - psub16x16,psub8x8\n"
134              "                                  - none, all\n"
135              "      --subme <integer>       Subpixel motion estimation quality\n"
136              "\n"
137              "  -s, --sar width:height      Specify Sample Aspect Ratio\n"
138              "  -o, --output                Specify output file\n"
139              "\n"
140              "      --no-asm                Disable any CPU optims\n"
141              "      --no-psnr               Disable PSNR computaion\n"
142              "      --quiet                 Quiet Mode\n"
143              "\n",
144             X264_BUILD
145            );
146 }
147
148 /*****************************************************************************
149  * Parse:
150  *****************************************************************************/
151 static int  Parse( int argc, char **argv,
152                    x264_param_t  *param,
153                    FILE **p_fin, FILE **p_fout, int *pb_decompress )
154 {
155     char *psz_filename = NULL;
156
157     /* Default output */
158     *p_fout = stdout;
159     *p_fin  = stdin;
160     *pb_decompress = 0;
161
162     /* Parse command line options */
163     opterr = 0; // no error message
164     for( ;; )
165     {
166         int long_options_index;
167 #define OPT_QPMIN 256
168 #define OPT_QPMAX 257
169 #define OPT_QPSTEP 258
170 #define OPT_RCSENS 259
171 #define OPT_IPRATIO 260
172 #define OPT_PBRATIO 261
173 #define OPT_RCBUF 262
174 #define OPT_RCIBUF 263
175 #define OPT_RCSTATS 264
176 #define OPT_RCEQ 265
177 #define OPT_QCOMP 266
178 #define OPT_NOPSNR 267
179 #define OPT_QUIET 268
180 #define OPT_SUBME 269
181
182         static struct option long_options[] =
183         {
184             { "help",    no_argument,       NULL, 'h' },
185             { "bitrate", required_argument, NULL, 'B' },
186             { "bframe",  required_argument, NULL, 'b' },
187             { "iframe",  required_argument, NULL, 'i' },
188             { "idrframe",required_argument, NULL, 'I' },
189             { "nf",      no_argument,       NULL, 'n' },
190             { "filter",  required_argument, NULL, 'f' },
191             { "cabac",   no_argument,       NULL, 'c' },
192             { "qp",      required_argument, NULL, 'q' },
193             { "qpmin",   required_argument, NULL, OPT_QPMIN },
194             { "qpmax",   required_argument, NULL, OPT_QPMAX },
195             { "qpstep",  required_argument, NULL, OPT_QPSTEP },
196             { "ref",     required_argument, NULL, 'r' },
197             { "no-asm",  no_argument,       NULL, 'C' },
198             { "sar",     required_argument, NULL, 's' },
199             { "output",  required_argument, NULL, 'o' },
200             { "analyse", required_argument, NULL, 'A' },
201             { "subme",   required_argument, NULL, OPT_SUBME },
202             { "rcsens",  required_argument, NULL, OPT_RCSENS },
203             { "rcbuf",   required_argument, NULL, OPT_RCBUF },
204             { "rcinitbuf",required_argument, NULL, OPT_RCIBUF },
205             { "ipratio", required_argument, NULL, OPT_IPRATIO },
206             { "pbratio", required_argument, NULL, OPT_PBRATIO },
207             { "pass",    required_argument, NULL, 'p' },
208             { "stats",   required_argument, NULL, OPT_RCSTATS },
209             { "rceq",    required_argument, NULL, OPT_RCEQ },
210             { "qcomp",   required_argument, NULL, OPT_QCOMP },
211             { "no-psnr", no_argument,       NULL, OPT_NOPSNR },
212             { "quiet",   no_argument,       NULL, OPT_QUIET },
213             {0, 0, 0, 0}
214         };
215
216         int c;
217
218         c = getopt_long( argc, argv, "hi:I:b:r:cxB:q:no:s:A:p:",
219                          long_options, &long_options_index);
220
221         if( c == -1 )
222         {
223             break;
224         }
225
226         switch( c )
227         {
228             case 'h':
229                 Help();
230                 return -1;
231
232             case 0:
233                 break;
234             case 'B':
235                 param->rc.i_bitrate = atol( optarg );
236                 param->rc.b_cbr = 1;
237                 break;
238             case 'b':
239                 param->i_bframe = atol( optarg );
240                 break;
241             case 'i':
242                 param->i_iframe = atol( optarg );
243                 break;
244             case 'I':
245                 param->i_idrframe = atol( optarg );
246                 break;
247             case 'n':
248                 param->b_deblocking_filter = 0;
249                 break;
250             case 'f':
251             {
252                 char *p = strchr( optarg, ':' );
253                 if( p )
254                 {
255                     param->i_deblocking_filter_alphac0 = atoi( optarg );
256                     param->i_deblocking_filter_beta = atoi( p );
257                 }
258                 break;
259             }
260             case 'q':
261                 param->rc.i_qp_constant = atoi( optarg );
262                 break;
263             case OPT_QPMIN:
264                 param->rc.i_qp_min = atoi( optarg );
265                 break;
266             case OPT_QPMAX:
267                 param->rc.i_qp_max = atoi( optarg );
268                 break;
269             case OPT_QPSTEP:
270                 param->rc.i_qp_step = atoi( optarg );
271                 break;
272             case 'r':
273                 param->i_frame_reference = atoi( optarg );
274                 break;
275             case 'c':
276                 param->b_cabac = 1;
277                 break;
278             case 'x':
279                 *pb_decompress = 1;
280                 break;
281             case 'C':
282                 param->cpu = 0;
283                 break;
284             case'o':
285                 if( ( *p_fout = fopen( optarg, "wb" ) ) == NULL )
286                 {
287                     fprintf( stderr, "cannot open output file `%s'\n", optarg );
288                     return -1;
289                 }
290                 break;
291             case 's':
292             {
293                 char *p = strchr( optarg, ':' );
294                 if( p )
295                 {
296                     param->vui.i_sar_width = atoi( optarg );
297                     param->vui.i_sar_height = atoi( p + 1 );
298                 }
299                 break;
300             }
301             case 'A':
302                 param->analyse.inter = 0;
303                 if( strstr( optarg, "none" ) )  param->analyse.inter = 0x000000;
304                 if( strstr( optarg, "all" ) )   param->analyse.inter = X264_ANALYSE_I4x4|X264_ANALYSE_PSUB16x16|X264_ANALYSE_PSUB8x8;
305
306                 if( strstr( optarg, "i4x4" ) )      param->analyse.inter |= X264_ANALYSE_I4x4;
307                 if( strstr( optarg, "psub16x16" ) ) param->analyse.inter |= X264_ANALYSE_PSUB16x16;
308                 if( strstr( optarg, "psub8x8" ) )   param->analyse.inter |= X264_ANALYSE_PSUB8x8;
309                 break;
310             case OPT_SUBME:
311                 param->analyse.i_subpel_refine = atoi(optarg);
312                 break;
313             case OPT_RCBUF:
314                 param->rc.i_rc_buffer_size = atoi(optarg);
315                 break;
316             case OPT_RCIBUF:
317                 param->rc.i_rc_init_buffer = atoi(optarg);
318                 break;
319             case OPT_RCSENS:
320                 param->rc.i_rc_sens = atoi(optarg);
321                 break;
322             case OPT_IPRATIO:
323                 param->rc.f_ip_factor = atof(optarg);
324                 break;
325             case OPT_PBRATIO:
326                 param->rc.f_pb_factor = atof(optarg);
327                 break;
328             case 'p':
329             {
330                 int i_pass = atoi(optarg);
331                 if( i_pass == 1 )
332                     param->rc.b_stat_write = 1;
333                 else if( i_pass == 2 )
334                     param->rc.b_stat_read = 1;
335                 else if( i_pass > 2 )   /* XXX untested */
336                     param->rc.b_stat_read =
337                     param->rc.b_stat_write = 1;
338                 break;
339             }
340             case OPT_RCSTATS:
341                 param->rc.psz_stat_in = optarg;
342                 param->rc.psz_stat_out = optarg;
343                 break;
344             case OPT_RCEQ:
345                 param->rc.psz_rc_eq = optarg;
346                break;
347             case OPT_QCOMP:
348                 param->rc.f_qcompress = atof(optarg);
349                 break;
350
351             case OPT_NOPSNR:
352                 param->analyse.b_psnr = 0;
353                 break;
354             case OPT_QUIET:
355                 param->i_log_level = X264_LOG_NONE;
356                 break;
357             default:
358                 fprintf( stderr, "unknown option (%c)\n", optopt );
359                 return -1;
360         }
361     }
362
363     /* Get the file name */
364     if( optind > argc - 1 )
365     {
366         Help();
367         return -1;
368     }
369     psz_filename = argv[optind++];
370
371     if( !(*pb_decompress) )
372     {
373         char *psz_size = NULL;
374         char *p;
375
376
377         if( optind > argc - 1 )
378         {
379             char *psz = psz_filename;
380             char *x = NULL;
381             /* try to parse the file name */
382             while( *psz )
383             {
384                 while( *psz && ( *psz < '0' || *psz > '9' ) ) psz++;
385                 x = strchr( psz, 'x' );
386                 if( !x )
387                     break;
388                 if( ( x[1] >= '0' && x[1] <= '9' ) )
389                 {
390                     psz_size = psz;
391                     break;
392                 }
393             }
394             if( psz_size == NULL )
395             {
396                 Help();
397                 return -1;
398             }
399             fprintf( stderr, "x264: file name gives %dx%d\n", atoi(psz), atoi(x+1) );
400         }
401         else
402         {
403             psz_size = argv[optind++];
404         }
405
406         param->i_width           = strtol( psz_size, &p, 0 );
407         param->i_height          = strtol( p+1, &p, 0 );
408     }
409
410     /* open the input */
411     if( !strcmp( psz_filename, "-" ) )
412     {
413         *p_fin = stdin;
414         optind++;
415     }
416     else if( ( *p_fin = fopen( psz_filename, "rb" ) ) == NULL )
417     {
418         fprintf( stderr, "could not open input file '%s'\n", psz_filename );
419         return -1;
420     }
421
422     return 0;
423 }
424
425 /*****************************************************************************
426  * Decode:
427  *****************************************************************************/
428 static int  Decode( x264_param_t  *param, FILE *fh26l, FILE *fout )
429 {
430     fprintf( stderr, "decompressor not working (help is welcome)\n" );
431     return -1;
432 #if 0
433     x264_nal_t nal;
434     int i_data;
435     int b_eof;
436
437     //param.cpu = 0;
438     if( ( h = x264_decoder_open( &param ) ) == NULL )
439     {
440         fprintf( stderr, "x264_decoder_open failed\n" );
441         return -1;
442     }
443
444     i_start = x264_mdate();
445     b_eof = 0;
446     i_frame = 0;
447     i_data  = 0;
448     nal.p_payload = malloc( DATA_MAX );
449
450     while( !i_ctrl_c )
451     {
452         uint8_t *p, *p_next, *end;
453         int i_size;
454         /* fill buffer */
455         if( i_data < DATA_MAX && !b_eof )
456         {
457             int i_read = fread( &data[i_data], 1, DATA_MAX - i_data, fh26l );
458             if( i_read <= 0 )
459             {
460                 b_eof = 1;
461             }
462             else
463             {
464                 i_data += i_read;
465             }
466         }
467
468         if( i_data < 3 )
469         {
470             break;
471         }
472
473         end = &data[i_data];
474
475         /* extract one nal */
476         p = &data[0];
477         while( p < end - 3 )
478         {
479             if( p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x01 )
480             {
481                 break;
482             }
483             p++;
484         }
485
486         if( p >= end - 3 )
487         {
488             fprintf( stderr, "garbage (i_data = %d)\n", i_data );
489             i_data = 0;
490             continue;
491         }
492
493         p_next = p + 3;
494         while( p_next < end - 3 )
495         {
496             if( p_next[0] == 0x00 && p_next[1] == 0x00 && p_next[2] == 0x01 )
497             {
498                 break;
499             }
500             p_next++;
501         }
502
503         if( p_next == end - 3 && i_data < DATA_MAX )
504         {
505             p_next = end;
506         }
507
508         /* decode this nal */
509         i_size = p_next - p - 3;
510         if( i_size <= 0 )
511         {
512             if( b_eof )
513             {
514                 break;
515             }
516             fprintf( stderr, "nal too large (FIXME) ?\n" );
517             i_data = 0;
518             continue;
519         }
520
521         x264_nal_decode( &nal, p +3, i_size );
522
523         /* decode the content of the nal */
524         x264_decoder_decode( h, &pic, &nal );
525
526         if( pic != NULL )
527         {
528             int i;
529
530             i_frame++;
531
532             for( i = 0; i < pic->i_plane;i++ )
533             {
534                 int i_line;
535                 int i_div;
536
537                 i_div = i==0 ? 1 : 2;
538                 for( i_line = 0; i_line < pic->i_height/i_div; i_line++ )
539                 {
540                     fwrite( pic->plane[i]+i_line*pic->i_stride[i], 1, pic->i_width/i_div, fout );
541                 }
542             }
543         }
544
545         memmove( &data[0], p_next, end - p_next );
546         i_data -= p_next - &data[0];
547     }
548
549     i_end = x264_mdate();
550     free( nal.p_payload );
551     fprintf( stderr, "\n" );
552
553     x264_decoder_close( h );
554
555     fclose( fh26l );
556     if( fout != stdout )
557     {
558         fclose( fout );
559     }
560     if( i_frame > 0 )
561     {
562         double fps = (double)i_frame * (double)1000000 /
563                      (double)( i_end - i_start );
564         fprintf( stderr, "decoded %d frames %ffps\n", i_frame, fps );
565     }
566 #endif
567 }
568
569 /*****************************************************************************
570  * Encode:
571  *****************************************************************************/
572 static int  Encode( x264_param_t  *param, FILE *fyuv, FILE *fout )
573 {
574     x264_t *h;
575     x264_picture_t pic;
576
577     int     i_frame, i_frame_total;
578     int64_t i_start, i_end;
579     int64_t i_file;
580
581     i_frame_total = 0;
582     if( !fseek( fyuv, 0, SEEK_END ) )
583     {
584         int64_t i_size = ftell( fyuv );
585         fseek( fyuv, 0, SEEK_SET );
586         i_frame_total = (int)(i_size / ( param->i_width * param->i_height * 3 / 2 ));
587     }
588
589     if( ( h = x264_encoder_open( param ) ) == NULL )
590     {
591         fprintf( stderr, "x264_encoder_open failed\n" );
592         return -1;
593     }
594
595     /* Create a new pic */
596     x264_picture_alloc( &pic, X264_CSP_I420, param->i_width, param->i_height );
597
598     i_start = x264_mdate();
599     for( i_frame = 0, i_file = 0; i_ctrl_c == 0 ; i_frame++ )
600     {
601         int         i_nal;
602         x264_nal_t  *nal;
603
604         int         i;
605
606         /* read a frame */
607         if( fread( pic.img.plane[0], 1, param->i_width * param->i_height, fyuv ) <= 0 ||
608             fread( pic.img.plane[1], 1, param->i_width * param->i_height / 4, fyuv ) <= 0 ||
609             fread( pic.img.plane[2], 1, param->i_width * param->i_height / 4, fyuv ) <= 0 )
610         {
611             break;
612         }
613
614         /* Do not force any parameters */
615         pic.i_type = X264_TYPE_AUTO;
616         if( x264_encoder_encode( h, &nal, &i_nal, &pic ) < 0 )
617         {
618             fprintf( stderr, "x264_encoder_encode failed\n" );
619         }
620
621         for( i = 0; i < i_nal; i++ )
622         {
623             int i_size;
624             int i_data;
625
626             i_data = DATA_MAX;
627             if( ( i_size = x264_nal_encode( data, &i_data, 1, &nal[i] ) ) > 0 )
628             {
629                 i_file += fwrite( data, 1, i_size, fout );
630             }
631             else if( i_size < 0 )
632             {
633                 fprintf( stderr,
634                          "need to increase buffer size (size=%d)\n", -i_size );
635             }
636         }
637     }
638     i_end = x264_mdate();
639     x264_picture_clean( &pic );
640     x264_encoder_close( h );
641     fprintf( stderr, "\n" );
642
643     fclose( fyuv );
644     if( fout != stdout )
645     {
646         fclose( fout );
647     }
648
649     if( i_frame > 0 )
650     {
651         double fps = (double)i_frame * (double)1000000 /
652                      (double)( i_end - i_start );
653
654         fprintf( stderr, "encoded %d frames %ffps %lld kb/s\n", i_frame, fps, i_file * 8 * 25 / i_frame / 1000 );
655     }
656
657     return 0;
658 }
659
660