#!/usr/bin/perl -w

# Copyright CREX:
# This script is released under GPL licence
# TransPerl v0.4

use Getopt::Long;

# Height and width in pixels of the dvd
our $max_largeur;
our $max_hauteur;

our $vob, ;
our $nice="nice -20";
GetOptions("project=s"     => \$project, # the project's name
	   "help"         => \$help, # print some usefull help
	   "desentrelace" => \$desentrelace, # activates deinterlacing
	   "noise"        => \$noise, # activates a temporal denoiser filter
	   #	   "resume"       => \$resume,
	   "codec=s"      => \$codec, # sets the codec: lavc, xvid or x264
	   "soft=s"       => \$soft); # sets the encoder software: mencoder or transcode

if ($help) {
  print "Vous avez demandé de l'aide?
Pour utiliser ce script lancez-le avec en paramètre le nom du projet. ex:
./transperl.pl --project TWO_WEEKS_NOTICE
Paramètres:
  --soft nom_du_soft :
    Le programme d'encodage que vous souhaitez utiliser. Actuellement:
    mencoder OU transcode
  --codec nom_du_codec :
    Choix du codec MPEG4. Actuellement:
    xvid, lavc or x264

Options:
  --desentrelace :
    Désentrelace la vidéo lors de l'encodage
  --noise :
    Applique un filtre de débruitage sensé améliorer la compressibilité
\n";
  exit (1);
}

if (!$project) {
  print "Please give the a project's name with --project project_name!\n";
  exit(1);
}

######## deinterlacing
if ($desentrelace) {
  if ($soft eq "mencoder") {
    $deint = ",pp=fd";
  } elsif ($soft eq "transcode") {
    $deint = "-J smartdeinter=threshold=10:Blend=1:diffmode=2:highq=1";
  } else {
    print "Please give the name of the soft you want to use to compress the video with --soft\n";
  }
} else {
  $deint ='';
}

######## de-noiser
if ($noise) {
  $noise=",denoise3d";
} else {
  $noise='';
}

######### Parses tuxrip's conf file #############################
my ($root, $device, $delay, $lavcopts, $xvidencopts, $max_gain, $video_drv, $audio_drv, $burner, $burn_speed, $viewer, $credits_quants, $cdrom_mnt_point, $crop_threshold, $container, $resize, $lang, $x264encopts);

open(CONFIG, "$ENV{HOME}/.tuxriprc")
  or die "ERREUR: fichier de config de tuxrip inexistant";
while (<CONFIG>) {
  chomp;			# eats the carriage return
  if ($_ =~ m/^1\. */) {	# identifies the ligne beginning by "1. " of the conf file
    $root = $';			# $' matches the sub-chain that follows the regex
  }
  if ($_ =~ m/^2\. */) {	# ... and so on
    $device = $';
  }
  if ($_ =~ m/^3\. */) {
    $delay = $';
  }
  if ($_ =~ m/^4\. */) {
    $lavcopts = $';
  }
  if ($_ =~ m/^5\. */) {
    $xvidencopts = $';
  }
  if ($_ =~ m/^6\. */) {
    $max_gain = $';
  }
  if ($_ =~ m/^7\. */) {
    $video_drv = $';
  }
  if ($_ =~ m/^8\. */) {
    $audio_drv = $';
  }
  if ($_ =~ m/^9\. */) {
    $burner = $';
  }
  if ($_ =~ m/^10\. */) {
    $burn_speed = $';
  }
  if ($_ =~ m/^11\. */) {
    $viewer = $';
  }
  if ($_ =~ m/^12\. */) {
    $credit_quants = $';
  }
  if ($_ =~ m/^13\. */) {
    $cdrom_mnt_point = $';
  }
  if ($_ =~ m/^14\. */) {
    $crop_threshold = $';
  }
  if ($_ =~ m/^15\. */) {
    $container = $';
  }
  if ($_ =~ m/^16\. */) {
    $resize = $';
  }
}
$x264encopts = "bframes=2:weight_b:b_pyramid:4x4mv:frameref=2:psnr";

$vob = "$root/$project/vob/$project.vob";
print "Your conf file is : $root \n";

######### Parses the log file of the DVD #############################
open(DVD, "$root/$project/tmp/infos.dvd")
  or die "ERROR: can't find any DVD log file";
while (<DVD>) {
  chomp;			# eats a carriage return
  if ($_ =~ m/^VIDEO:  MPEG2  */) {
    my ($dimensions, $rubbish) = split /  /,$',2;
    print "the DVD's dimensions are: $dimensions\n";
    ($max_largeur,$max_hauteur,$rubbish) = split /x/,$dimensions,3;
  }
}



######### Parses the log file of the project ################################
open (LOG_PROJET, "$root/$project/tmp/log")
  or die "No log found for your project. Please make sure you created one with tuxrip and reached step n°5";

my ($crop_transcode, $crop_mencoder, $scale_transcode, $scale_mencoder, $bitrate);

while (<LOG_PROJET>) {
  chomp;

  ####### Parses and converts the cropping parameters #######################
  if ($_ =~ m/^cropping --> */ ) {
    my ($crop, $h,$l) = split / /,$',3;
    $crop_mencoder = $crop;
    my ($largeur,$hauteur,$crop_gauche,$crop_haut) = split /:/, $crop,4;
    ##### "Normalisation" du crop pour pouvoir utiliser le "fast resize"
    $largeur = $largeur - ($largeur%8);
    $hauteur = $hauteur - ($hauteur%8);
    my $crop_bas=$max_hauteur-$hauteur-$crop_haut;
    my $crop_droite=$max_largeur-$largeur-$crop_gauche;
    
    $crop_transcode = "$crop_haut,$crop_gauche,$crop_bas,$crop_droite";
    
    print "transcode's compatible crop is: $crop_transcode, mencoder's is: $crop_mencoder\n";
  }
  
  ####### Parses and gets the Scale and Bitrate parameters ##################
  if ($_ =~ m/^taille visée, résolution, bitrate --> */ ) {
    my ($taille_visee, $resolution, $bitrate_logged) = split / /,$',3;
    $bitrate = $bitrate_logged;
    $scale_mencoder = $resolution;
    my ($X, $Y) =  split /:/, $resolution,2;
    $scale_transcode = "$X"."x$Y";
    print "transcode's compatible scaling param is: $scale_transcode, mencoder's is: $scale_mencoder\n";
  }
}

######### Encodes according to the codec and the soft selected ############
my $commande_systeme;
if ($soft eq "mencoder") {
  my $commande_mencoder_base = "$nice mencoder $vob -mc 0 -nosound -vf crop=$crop_mencoder$deint$noise,scale=$scale_mencoder -ovc $codec ";
  if ($codec eq "lavc") {
    $commande_mencoder = $commande_mencoder_base."-lavcopts $lavcopts:vbitrate=$bitrate:vpass=";
  } elsif ($codec eq "xvid") {
    $commande_mencoder = $commande_mencoder_base."-xvidencopts $xvidencopts:bitrate=$bitrate:pass=";
  } elsif ($codec eq "x264") {
    $commande_mencoder = $commande_mencoder_base."-x264encopts $x264encopts:bitrate=$bitrate:pass=";
  }
  $commande_systeme = "${commande_mencoder}1 -o /dev/null &&${commande_mencoder}2 -o $root/$project/video/${project}sans-son.avi";
} else {
  my $commande_trancode = "transcode --nice 20 -i $vob -x vob,null -y xvid4,null -V $deint -j $crop_transcode -Z $scale_transcode,fast -w $bitrate";
  $commande_systeme = "$commande_trancode -o /dev/null -R 1&&$commande_trancode -o $root/$project/video/${project}sans-son.avi -R 2";
}

print "I'm going to lanch the encoding process with this command-line:\n$commande_systeme\n";
chdir "$root/$project/tmp";
#get_title();
#my %crops = compute_cropping($vob);
#`mplayer  $vob -vf rectangle=$crops{width}:$crops{height}:$crops{left}:$crops{top}`;
#audio_compression($type="mp3", $audiotrack, $vob);
system "$commande_systeme";
#compute_vid_siz($audio_path = "$root/$project/audio");
#get_chapters($chap_file = "$root/$project/tmp/$project-chapitrage");

sub get_title {
  my ($device) = @_;
  $_ = `dd if=$device ibs=1 skip=32808 count=32 2>/dev/null`; # get title
  s/ //g;			## zaps spaces
  return $_;
}

sub get_chapters {
  my ($chap_file, $title, $device) = @_;
  system "dvdxchap -t $title $device 2>/dev/null > ";
}

# TODO:
# have XviD compute the video size itself: You tell: 629359kB (real kB: 1024)
# It outputs: 640713896 bytes, which is 625697kb (99.4% of target size)
# on mux, it produces a 701M mkv file = 734056302 bytes (target was 702)
# ogm is 705M 739091172 bytes
# (audio was 45996342 and 45639587 bytes)

sub audio_compression {
  my ($type, $audiotrack, $input) = @_;
  chdir "$root/$project/tmp";
  if ($type eq "ac3") {
    system "tccat -i $input -d 0 | tcdemux -a $audiotrack -x ac3 -S 0 -M 1 -d 0 | tcextract -t vob -x ac3 -a $audiotrack -d 0 | tcextract -t raw -x ac3 -d 0 > $root/$project/audio/son.ac3";
  } else {
    my $pipe="/tmp/pcmpipe.raw";
    require POSIX;
    POSIX::mkfifo($pipe, 0666);
    
    # my $mplayer_audiotrack = $audiotrack + 128;
    #system "$nice mplayer -nortc -ao pcm:file=$pipe -vc dummy -aid $mplayer_audiotrack -vo null $input -quiet&";
    system "transcode -q 0 -i $input -a $audiotrack -u 50 --a52_drc_off -x null,vob -y null,wav -m $pipe -o /dev/null -J normalize";
    if ($type eq "mp3") {
      system "$nice lame -q 0 --abr 96 -r -s 48 --bitwidth 16 -o $root/$project/audio/son.mp3 $pipe";
    } else {
      #system "$nice mplayer -nortc -ao pcm -vc dummy -aid $mplayer_audiotrack -vo null -aofile $pipe $root/$project/vob/$project.vob -quiet&";
      system "$nice oggenc -r -C2 -R48000 -B16 -q1 -o $root/$project/audio/son.ogg $pipe";
    }
    unlink $pipe;
  }
}

sub compute_bitrate () {
  my ($target_size, $audio_size, $lenght) = @_;
    return ($target_size - $audio_size) * 1024 * 1024 / $lenght * 8 / 1000;
}

sub compute_res () {
  my ($width_croped, $height_croped, $width_disp, $height_disp, $width_pix, $height_pix, $bitrate, $CQ) = @_;
  my $ARc = ($width_croped * (($width_disp/$height_disp) / ($width_pix/$height_pix))) / $height_croped;
  
 
#  my %res{Y} = INT( SQRT(1000 * $bitrate / 25 / ARc / CQ) / 16 ) * 16;
#    %res{X}  INT( %res{Y} * $ARc / 16) * 16;
}

sub cc_check () {
  my $taille = (stat($vob))[7];
  if ($codec eq "lavc") {
    $cc_command = $commande_mencoder_base." -lavcopts vcodec=mpeg4:vmax_b_frames=0:vhq:v4mv:vqscale=2";
  } elsif ($codec eq "xvid") {
    $cc_command = $commande_mencoder_base." -xvidencopts vhq=3:fixed_quant=2";
  }
  
  my $pas=$taille_vob/105;
  for (my $i=0; i<100; $i++) {
    my $debut = ($i+2)*$pas;
    system "$cc_command -sb $debut -endpos $sec -o $RACINE/$project/tmp/cctemp${i}.avi >/dev/null 2>&1";
  }
}

sub compute_vid_siz {
  my ($audio_path) = @_;
  use Cwd;
  my $vid_siz = 0;
  my $orig_path = getcwd();	# saves the current path, to get back there

  chdir $audio_path;
  while (<*>) {
    $vid_siz += (stat($_))[7];	# get the size of all files in $audio_path
  }

  chdir $orig_path;
  return $vid_siz;
}

sub compute_bitrate {
  my ($vid_siz, $playtime, $container) = @_;
  my $bitrate = ($vid_siz * 1024 * 1024 / $playtime * 8 / 1000);
  # Ok, this is strictly experimental: matroska is more space-efficient than
  # ogm, and XviD produces slitly undersized files. This should help
  if ($container eq "matroska") {
    $bitrate = $bitrate * 1.0128;
  }
  use integer;
  return ($bitrate/1);		# trick to have a bitrate that's strictly an integer
}

sub compute_cropping {
  my ($vob) = @_;
  my $position = (stat($vob))[7];
  $position = $position/5;
  use integer;
  $position = $position/1;
  print "test pos: $position\n";
  for ( `mplayer $vob -sb $position -frames 4 -vf cropdetect -vo null -nosound` ) {
    chomp;
    if ($_ =~ m/^.*-vf crop=.*$/ ) {
      my ($start, $width, $height, $left, $top, $finish) = /(.*)=([0-9]+):([0-9]+):([0-9]+):([0-9]+)(.*)/;
      return (
	      width  => $width,
	      height => $height,
	      left => $left,
	      top => $top);
    }
  }
}

sub do_merge {
  my ($root, $project, $delay) = @_;
  my $audio_tracks = '';
  # TODO read audio dir + parse log files
  $audio_tracks = "$audio_tracks -s $decal -c LANGUAGE=${pisteaudio[2]} $root/$project/audio/son.ogg";
  system "ogmmerge -o $root/$project/video/${project}.ogm $root/$project/video/${project}sans-son.avi $audio_tracks 2>$RACINE/$project/tmp/logmux";
}
