#---------------------------------------------------------------------
#      QualityLayersPrecompuation.pl
#---------------------------------------------------------------------
# 
#  perl script to run precomputations for Quality Layers estimation.
#  
#
# Command Line:
#   perl QualityLayersPrecomputation.pl configFile
#
# Note:
#   this script works only under Windows. Adaptation is needed to let it run under Linux. 
# Note:
#   Perl environment can be retreived at following URL: http://www.activestate.com/Products/ActivePerl/
#
#---------------------------------------------------------------------


#-----------  General parameters -------------------------------------
# Simulation: 
#  set to 1: only simulation
#  set to 0: run effectively
$Simulation = 1;
$VerboseCmdLine = 0;

#---- path to executables 
$extractor = ".\\bin\\BitStreamExtractorStatic.exe";
$decoder = ".\\bin\\H264AVCDecoderLibTestStatic.exe";
$bgprocess = "start /BelowNormal /min /wait";
# bgprocess has been set for windows. 
# For running under Linux, this variable could be set to "" or any other suitable background command line



#------------ Specific parameters ------------------------------------
# These parameters are defined in the configuration file provided on the command line

$origstream = ".\\str\\Crew00";
$extstream = ".\\str\\Crew_extracted.264";
$decodeseq = ".\\rec\\Crew_decoded.yuv";
$origSeq  = "..\\orig\\Crew_4CIF60.yuv";
$distofile = "tmp\\MobileQCIF_disto";
$width = 704;
$height = 576;
$varNbFrames = 150;
$varGop = 16;
$maxPoints = 9;


#--------- Read configuration file 
sub ReadConfigParameters()
{
  local ($file, @lines);
  $file = shift;
  print "reading parameters from $file\n";
  if (!open(CFGFILE, $file))
  {             
    die "can't open file $file";
  }
  @lines = <CFGFILE>;
  close CFGFILE;
  my $line;
  foreach $line (@lines)
  {
    if (  ($line =~ /^\#(.)*?$/msig) # comment line
       || ($line =~ /^\s*\n/msig) )  # empty line
    {
      next;
    }
    $line =~ /^\s*(\w*)\s*=\s*\"(.*)\"/;
    my $key;
    my $value;
    $key = $1;
    $value = $2;
    if (!((defined $key) && (defined $value))) {
        die "Following line is not recognised in $file:\n $line\n";
    }

    if ($key eq "origstream") {
      $origstream = $value;
    } elsif ($key eq "extstream")
    {
      $extstream = $value;
    } elsif ($key eq "decodeseq")
    {
      $decodeseq = $value;
    } elsif ($key eq "origSeq")
    {
      $origSeq = $value;
    } elsif ($key eq "distofile")
    {
      $distofile = $value;
    } elsif ($key eq "width")
    {
      $width = $value;
    } elsif ($key eq "height")
    {
      $height = $value;
    } elsif ($key eq "nbFrame")
    {
      $varNbFrames = $value;
    } elsif ($key eq "gopSize")
    {
      $varGop = $value;
    } elsif ($key eq "maxPoints")
    {
      $maxPoints = $value;
    } elsif ($key eq "simulation")
    {
      $Simulation = $value;
    }
  }
}

#------- conditional execution
sub DoExec() {
  my $cmdLine;
  $cmdLine = shift;
  if ($VerboseCmdLine) {
    print "Executing: $cmdLine\n";
  }
  if (!$Simulation) {
    print "running...\n";
    $cmdLine =~ s/\\/\\\\/msg;
    system $cmdLine;
  }
}


$extLine = "-cut";

$decLine = "-ql";

$esp = " ";

$varPoint = 0;
$varLayer = 0;
$varIntra = -1;

#--------- Main program
if ($#ARGV < 0)
{
    print "usage: QualityLayersPrecomputation.pl configFile \n";
    exit;
}
&ReadConfigParameters($ARGV[0]);

$varNbGop = int(($varNbFrames-2)/$varGop + 2);
print "Number of GOP $varNbGop \n";


# open output file for storing disto
open (FSOR, ">$distofile");


#calculate disto for frames inside a gop
for($varPoint = 0; $varPoint < $maxPoints; $varPoint++)
{
  for($varFrame = 2; $varFrame <= $varGop; $varFrame++)
  {
    $varOneFrame = 0;
    print "treating image:$varFrame layer:$varLayer varPoint:$varPoint\n";
    #EXTRACTION
    $cmdLine = "$bgprocess $extractor $origstream $extstream $extLine $varFrame $varLayer $varPoint $varOneFrame $varGop $varNbFrames $varIntra";
    &DoExec($cmdLine);
    #DECODAGE
    $cmdLine = "$bgprocess $decoder $extstream $decodeseq $decLine $origSeq $width $height $varNbFrames $varGop $varOneFrame";
    &DoExec($cmdLine);
    
    if (!$Simulation) {
        open (FENT, '<disto');
        @res = <FENT>;
        for($i = 1; $i <= $#res; $i++)
        {
            $varNumFrame = $varFrame + ($i-1)*$varGop;
            if ($varNumFrame < $varNbFrames)
            {
            print "disto ";
            print $res[$i];
            $ligne = $varNumFrame.$esp.$varLayer.$esp.$varPoint."\n".$res[$i]."\n";
            $ligne =~ s/\n\n/\n/;
            print FSOR $ligne;
            }
        }
    }
  }
}

#calculate disto for first frame
for($varPoint = 0; $varPoint < $maxPoints; $varPoint++)
{
    $varFrame = 0;
    $varOneFrame = 1;
    print "treating image:$varFrame layer:$varLayer varPoint:$varPoint\n";
    #EXTRACTION
    $cmdLine = "$bgprocess $extractor $origstream $extstream $extLine $varFrame $varLayer $varPoint $varOneFrame $varGop $varNbFrames $varIntra";
    &DoExec($cmdLine);
    #DECODAGE
    $cmdLine = "$bgprocess $decoder $extstream $decodeseq $decLine $origSeq $width $height $varNbFrames $varGop $varOneFrame";
    &DoExec($cmdLine);
    
    if (!$Simulation) 
    {
        open (FENT, '<disto');
        $dis = <FENT>;
        print "disto ";
        print $dis;
        $ligne = $varFrame.$esp.$varLayer.$esp.$varPoint."\n".$dis."\n";
        print FSOR $ligne;  
    }
}
 
#calculate disto for last frames of gop
for($varPoint = 0; $varPoint < $maxPoints; $varPoint++)
{
  for($i= 0; $i < $varNbGop; $i++)
  {
    $varOneFrame = 1;
    $varFrame = 1 + $i*$varGop;
    if ($varFrame < $varNbFrames)
    {

    print "treating image:$varFrame layer:$varLayer varPoint:$varPoint\n";
    #EXTRACTION
    $cmdLine = "$bgprocess $extractor $origstream $extstream $extLine $varFrame $varLayer $varPoint $varOneFrame $varGop $varNbFrames $varIntra";
    &DoExec($cmdLine);
    #DECODAGE
    $cmdLine = "$bgprocess $decoder $extstream $decodeseq $decLine $origSeq $width $height $varNbFrames $varGop $varOneFrame";
    &DoExec($cmdLine);
    
    if (!$Simulation)
    {
        open (FENT, '<disto');
        $dis = <FENT>;
        print "disto ";
        print $dis;
        $ligne = $varFrame.$esp.$varLayer.$esp.$varPoint."\n".$dis."\n";
        print FSOR $ligne; 
    }
    }
  }
}
       

close FENT;
close FSOR;
