regression-test.pl
上传用户:lctgjx
上传日期:2022-06-04
资源大小:8887k
文件大小:8k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. #!/bin/env perl
  2. # regression-test.pl: tests different versions of x264
  3. # by Alex Izvorski & Loren Merrit 2007
  4. # GPL
  5. $^W=1;
  6. use Getopt::Long;
  7. use File::Path;
  8. use File::Copy;
  9. use File::Basename;
  10. # prerequisites: 
  11. # - perl > 5.8.0
  12. # - svn
  13. # - net access
  14. # - linux/unix
  15. # - gcc
  16. # the following require a make testclean
  17. # - changing x264 option sets and or adding/removing option sets
  18. # - changing configure options
  19. # - changing CFLAGS or other variables that affect compilation
  20. # - a newer head revision
  21. # the following do not require a make testclean, but may cause some tests to be rerun unnecessarily:
  22. # - adding/removing input files 
  23. # - adding/removing versions
  24. @versions = ();
  25. @input_files = ();
  26. @option_sets = ();
  27. GetOptions ("version=s" => @versions,
  28.             "input=s" => @input_files,
  29.             "options=s" => @option_sets,
  30.             );
  31. # TODO check inputs
  32. # TODO some way to give make options
  33. # TODO some way to give configure options
  34. if (scalar(@versions) == 0)
  35. {
  36.     @versions = ('rHEAD', 'current');
  37. }
  38. if (scalar(@option_sets) == 0 ||
  39.     scalar(@input_files) == 0)
  40. {
  41.     print "Regression test for x264n";
  42.     print "Usage:n  perl tools/regression-test.pl --version=623 --version=624 --input=football_720x480p.yuv --input=foreman_352x288p.yuv --options='--me=dia --subme=2 --no-cabac'n";
  43.     print "Any number of versions, option sets, and input files may be given.n";
  44.     print "Versions may be any svn revision, a comma-separated list of revisions, or 'current' for the version in the current directory.n";
  45.     exit;
  46. }
  47. mkpath("test");
  48. @versions = map { split m![,s]s*! } @versions;
  49. foreach my $version (@versions)
  50. {
  51.     $version =~ s!^head$!rHEAD!i;
  52.     $version =~ s!^current$!current!i;
  53.     $version =~ s!^(d+)$!r$1!;
  54.     if (-e "test/x264-$version/x264" && ($version ne "current"))
  55.     {
  56.         print("have version: $versionn");
  57.         next;
  58.     }
  59.     print("building version: $versionn");
  60.     if ($version eq "current")
  61.     {
  62.         system("(./configure && make) &> test/build.log");
  63.         mkpath("test/x264-$version");
  64.         if (! -e "x264") { print("build failed n"); exit 1; }
  65.         copy("x264", "test/x264-$version/x264");
  66.         chmod(0755, "test/x264-$version/x264");
  67.         next;
  68.     }
  69.     system("svn checkout -$version svn://svn.videolan.org/x264/trunk/ test/x264-$version >/dev/null");
  70.     chdir("test/x264-$version");
  71.     system("(./configure && make) &> build.log");
  72.     chdir("../..");
  73.     if (! -e "test/x264-$version/x264") { print("build failed n"); exit 1; }
  74. }
  75. $any_diff = 0;
  76. foreach my $i (0 .. scalar(@option_sets)-1)
  77. {
  78.     $opt = $option_sets[$i];
  79.     print("options: $opt n");
  80.     foreach my $j (0 .. scalar(@input_files)-1)
  81.     {
  82.         my $file = $input_files[$j];
  83.         print("input file: $file n");
  84.         my $outfile = basename($file);
  85.         $outfile =~ s!.yuv$!!;
  86.         $outfile = "test/opt$i-$outfile$j";
  87.         foreach my $k (0 .. scalar(@versions)-1)
  88.         {
  89.             my $version = $versions[$k];
  90.             if (-e "$outfile-$version.log" && ($version ne "current"))
  91.             {
  92.                 print("have results for version: $versionn");
  93.             }
  94.             else
  95.             {
  96.                 print("running version: $version n");
  97.                 # verbose option is required for frame-by-frame comparison
  98.                 system("test/x264-$version/x264 --verbose $opt $file -o $outfile-$version.264 > $outfile-$version.log 2>&1");
  99.             }
  100.             # TODO check for crashes
  101.             # TODO if (read_file("$outfile-$version.log") =~  m!could not open input file!) ...
  102.             # TODO check decompression with jm
  103.             # TODO dump (and check) frames
  104.             if ($k > 0)
  105.             {
  106.                 my $baseversion = $versions[$k - 1];
  107.                 print("comparing $version with $baseversion: ");
  108.                 $is_diff = 0;
  109.                 $is_diff ||= compare_logs("$outfile-$version.log", "$outfile-$baseversion.log");
  110.                 $is_diff ||= compare_raw264("$outfile-$version.264", "$outfile-$baseversion.264");
  111.                 if (! $is_diff) { print("identical n"); }
  112.                 $any_diff ||= $is_diff;
  113.             }
  114.         }
  115.     }
  116. }
  117. print "n";
  118. if (! $any_diff) { print "no differences foundn"; }
  119. else { print "some differences foundn"; exit 1; }
  120. sub compare_logs
  121. {
  122.     my ($log1, $log2) = @_;
  123.     my $logdata1 = read_file($log1);
  124.     my $logdata2 = read_file($log2);
  125.     # FIXME comparing versions with different log output format will fail
  126.     $logdata1 = join("n", grep { m!frame=! } split(m!n!, $logdata1));
  127.     $logdata2 = join("n", grep { m!frame=! } split(m!n!, $logdata2));
  128.     my $is_diff = 0;
  129.     if ($logdata1 ne $logdata2)
  130.     {
  131.         print("log files differ n");
  132.         $is_diff = 1;
  133.     }
  134.     my $stats1 = parse_log_overall_stats($log1);
  135.     my $stats2 = parse_log_overall_stats($log2);
  136.     if ($stats1->{psnr_y} != $stats2->{psnr_y})
  137.     {
  138.         printf("psnr change: %+f dB n", $stats1->{psnr_y} - $stats2->{psnr_y});
  139.         $is_diff = 1;
  140.     }
  141.     if ($stats1->{bitrate} != $stats2->{bitrate})
  142.     {
  143.         printf("bitrate change: %+f kb/s n", $stats1->{bitrate} - $stats2->{bitrate});
  144.         $is_diff = 1;
  145.     }
  146.     #arbitrarily set cutoff to 3% change
  147.     #$speed_change_min = 0.03;
  148.     #if (abs($stats1->{fps} - $stats2->{fps}) > $speed_change_min * ($stats1->{fps} + $stats2->{fps})/2)
  149.     #{
  150.     #    printf("speed change: %+f fps n", $stats1->{fps} - $stats2->{fps}); 
  151.     #    $is_diff = 1;
  152.     #}
  153.     return $is_diff;
  154.     # TODO compare frame by frame PSNR/SSIM, record improved or unimproved ranges
  155.     #parse_log_frame_stats($log1);
  156.     #parse_log_frame_stats($log2);
  157.     # TODO compare actual run times
  158. }
  159. sub compare_raw264
  160. {
  161.     my ($raw1, $raw2) = @_;
  162.     
  163.     # FIXME this may use a lot of memory
  164.     my $rawdata1 = read_file($raw1);
  165.     my $rawdata2 = read_file($raw2);
  166.     
  167.     # remove first NAL, it is a version-specific SEI NAL
  168.     my $pat = chr(0).chr(0).chr(1);
  169.     $rawdata1 =~ s!^.*?$pat.*?$pat!$pat!;
  170.     $rawdata2 =~ s!^.*?$pat.*?$pat!$pat!;
  171.     if ($rawdata1 ne $rawdata2)
  172.     {
  173.         print("compressed files differ n");
  174.         return 1;
  175.     }
  176.     return 0;
  177. }
  178. sub parse_log_frame_stats
  179. {
  180.     my ($log) = @_;
  181.     my $logtext = read_file($log);
  182.     my @frames = ();
  183.     while ($logtext =~ m!x264 [debug]: (frame=.*)!g)
  184.     {
  185.         my $line = $1;
  186.         if ($line !~ m!frame=s*(d+)s* QP=s*(d+)s* NAL=(d+)s* Slice:(w)s* Poc:(d+)s* I:(d+)s* P:(d+)s* SKIP:(d+)s* size=(d+) bytes PSNR Y:(d+.d+) U:(d+.d+) V:(d+.d+)!)
  187.         {
  188.             print "error: unparseable log line: $line n"; next;
  189.         }
  190.         
  191.         my $frame = 
  192.             +{
  193.                 num=>$1,
  194.                 qp=>$2,
  195.                 nal=>$3,
  196.                 slice=>$4,
  197.                 poc=>$5,
  198.                 count_i=>$6,
  199.                 count_p=>$7,
  200.                 count_skip=>$8,
  201.                 size=>$9,
  202.                 psnr_y=>$10,
  203.                 psnr_u=>$11,
  204.                 psnr_v=>$12,
  205.             };
  206.         if ($line =~ m!SSIM Y:(d+.d+)!)
  207.         {
  208.             $frame->{ssim} = $1;
  209.         }
  210.         push(@frames, $frame);
  211.     }
  212.     return @frames;
  213. }
  214. sub parse_log_overall_stats
  215. {
  216.     my ($log) = @_;
  217.     my $logtext = read_file($log);
  218.     if ($logtext !~ m!x264 [info]: PSNR Mean Y:(d+.d+) U:(d+.d+) V:(d+.d+) Avg:(d+.d+) Global:(d+.d+) kb/s:(d+.d+)!)
  219.     {
  220.         print "error: unparseable log summary info n"; return +{};
  221.     }
  222.     my $stats = 
  223.         +{ 
  224.             psnr_y=>$1,
  225.             psnr_u=>$2,
  226.             psnr_v=>$3,
  227.             psnr_avg=>$4,
  228.             psnr_global=>$5,
  229.             bitrate=>$6,
  230.         };
  231.     
  232.     if ($logtext !~ m!encoded (d+) frames, (d+.d+) fps!)
  233.     {
  234.         print "error: unparseable log summary info n"; return +{};
  235.     }
  236.     $stats->{num_frames} = $1;
  237.     $stats->{fps} = $2;
  238.     return $stats;
  239. }
  240. sub read_file
  241. {
  242.     my ($file) = @_;
  243.     open(F, $file) || die "could not open $file: $!";
  244.     undef $/;
  245.     my $data = <F>;
  246.     $/ = "n";
  247.     close(F);
  248.     return $data;
  249. }
  250. sub write_file
  251. {
  252.     my ($file, $data) = @_;
  253.     open(F, ">".$file) || die "could not open $file: $!";
  254.     print F $data;
  255.     close(F);
  256. }