###########################################################################
#
# AudioConverter - helper plugin that does audio conversion
#
# A component of the Greenstone digital library software
# from the New Zealand Digital Library Project at the 
# University of Waikato, New Zealand.
#
# Copyright (C) 2008 New Zealand Digital Library Project
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
###########################################################################
package AudioConverter;

use MultimediaConverter;


use strict;
no strict 'refs'; # allow filehandles to be variables and viceversa

use gsprintf 'gsprintf';

BEGIN {
    @AudioConverter::ISA = ('MultimediaConverter');
}


my $arguments = [
		 ];

my $options = { 'name' => "ImageConverter",
		'desc' => "{ImageConverter.desc}",
		'abstract' => "yes",
		'inherits' => "yes",
		'args' => $arguments };

sub new {
    my ($class) = shift (@_);
    my ($pluginlist,$inputargs,$hashArgOptLists) = @_;
    push(@$pluginlist, $class);

    push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
    push(@{$hashArgOptLists->{"OptList"}},$options);

    my $self = new MultimediaConverter($pluginlist, $inputargs, $hashArgOptLists, 1);


    return bless $self, $class;

}

# Discover the characteristics of a audio file.

#  Equivalent step to that in ImagePlugin that uses ImageMagicks's
#  'indentify' utility

#  Here we use 'ffmpeg' for audio but for consistency keep the Perl
#  method name the same as before


sub identify { 
    my ($audio, $outhandle, $verbosity) = @_;

    # Use the ffmpeg command to get the file specs
    my $command = "ffmpeg -i \"$audio\"";

    print $outhandle "  $command\n" if ($verbosity > 2);
    my $result = '';
    $result = `$command 2>&1`;
    print $outhandle "  $result\n" if ($verbosity > 4);

    # Read the type, width, and height etc.
    my $vtype =  'unknown';
    my $vcodec = 'unknown';
    my $width =  'unknown';
    my $height = 'unknown';
    my $fps    = 'unknown';

    my $atype =  'unknown';
    my $afreq =  'unknown';
    my $achan =  'unknown';
    my $arate =  'unknown';

    my $audio_safe = quotemeta $audio;

    # strip off everything up to filename
    $result =~ s/^.*\'$audio_safe\'://s;

    if ($result =~ m/Audio: (\w+).*?, (\d+) Hz, (\w+)(?:, (\d+.*))?/m) {
	$atype = $1;
	$afreq = $2;
	$achan = $3;
	$arate = $4 if (defined $4);
    }

    # Read the duration
    my $duration = "unknown";
    if ($result =~ m/Duration: (\d+:\d+:\d+\.\d+)/m) {
	$duration = $1;
    }
    print $outhandle "  file: $audio:\t $atype, $duration\n" 
	if ($verbosity > 2);

    if ($verbosity >3) {
	print $outhandle "\t freq = $afreq Hz, $achan, $arate\n";
    }

    # Return the specs
    return ($duration, -s $audio, $atype,$afreq,$achan,$arate);
}



sub audio_convertto_cmd
{
    my $self = shift (@_);
    my ($originalfilename,$converttotype) = @_;

    my $output_dir = $self->{'cached_dir'};
    my $iaudio_root = $self->{'cached_file_root'};

    
    my $file = "$iaudio_root.$converttotype";
    my $filename = &util::filename_cat($output_dir,$file);
    
    my $exp_duration = $self->{'exp_duration'};
    my $t_opt = (defined $exp_duration) ? "-t $exp_duration" : "";
    
    my $main_opts = "-y $t_opt";
    

    my $originalfilename_gsdlenv = $self->gsdlhome_independent($originalfilename);
    my $filename_gsdlenv = $self->gsdlhome_independent($filename);
    
    
    my $convertto_cmd = "ffmpeg $main_opts -i \"$originalfilename_gsdlenv\"";
    $convertto_cmd .= " -y \"$filename_gsdlenv\"";
    
    return ($convertto_cmd,$filename,$file);
}



sub audio_stream_ffmpeg_cmd
{
    my $self = shift (@_);
    my ($iaudio_filename, $ofile_ext,
	$streaming_bitrate,$streaming_size, 
	$opt_streaming_achan, $opt_streaming_arate) = @_;

    my $streaming_achan 
	= (defined $opt_streaming_achan) ? $opt_streaming_achan : 2;

    my $streaming_arate 
	= (defined $opt_streaming_arate) ? $opt_streaming_arate : 22050;

    my $output_dir = $self->{'cached_dir'};
    my $iaudio_root = $self->{'cached_file_root'};

    my $op_file = "${iaudio_root}_stream.$ofile_ext";
    my $op_filename = &util::filename_cat($output_dir,$op_file);

    my $exp_duration = $self->{'exp_duration'};
    my $t_opt = (defined $exp_duration) ? "-t $exp_duration" : "";

    my $main_opts = "-y $t_opt";

    my $bitrate_opt = "-b $streaming_bitrate";
    my $stream_opts .= " -ac $streaming_achan -ar $streaming_arate";


    my $all_opts = "$main_opts $stream_opts"; 

    my $ffmpeg_cmd;

    my $iaudio_filename_gsdlenv = $self->gsdlhome_independent($iaudio_filename);
    my $op_filename_gsdlenv = $self->gsdlhome_independent($op_filename);

    
    $ffmpeg_cmd = "ffmpeg -i \"$iaudio_filename_gsdlenv\" $all_opts -y \"$op_filename_gsdlenv\"";

    return ($ffmpeg_cmd,$op_filename,$op_file);
}



sub stream_mp4_audio_cmd
{
    my $self = shift (@_);
    my ($ivideo_filename,$streaming_HQ_size, $streaming_HQ_AudioBitrate) = @_;

    my $output_dir = $self->{'cached_dir'};
    my $ivideo_root = $self->{'cached_file_root'};

    my $omp4_file = "${ivideo_root}_aHQstream.mp4";
    my $omp4_filename = &util::filename_cat($output_dir,$omp4_file);


    #my $exp_duration = $self->{'exp_duration'};
    #my $t_opt = (defined $exp_duration) ? "-t $exp_duration" : "";

	my $deinterlace = $self->{'videoDeinterlacingFilter'};
	my $video_processing_parameters;	
	# Use specific resizing algorythms depending if we need to downsize the video resolution or not
	if(!$streaming_HQ_size || $streaming_HQ_size eq "fullsize") { 
		$video_processing_parameters = "--strict-anamorphic";
	} else {
		$video_processing_parameters = "-w $streaming_HQ_size --loose-anamorphic";
	}
	# Use the deinterlace video filter if enabled in the plugin
	if ($deinterlace eq "true")
	{
		$video_processing_parameters .= " --decomb";
	}

    my $ivideo_filename_gsdlenv = $self->gsdlhome_independent($ivideo_filename);
    my $omp4_filename_gsdlenv = $self->gsdlhome_independent($omp4_filename);
	
    # Generate the pre and post video parameters for Handbrake v0.9.4
    my $pre_opts = "-t 1 -c 1";
    my $post_opts = "-f mp4 -O $video_processing_parameters -e x264 -a 1 -E faac -6 dpl2 -R Auto -B $streaming_HQ_AudioBitrate -D 0.0 -x ref=2:bframes=2:subq=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0";

    my $handbrake_cmd = "HandbrakeCLI.exe -i \"$ivideo_filename_gsdlenv\" $pre_opts -o \"$omp4_filename_gsdlenv\" $post_opts";

    #print STDERR "****\nHandbrake command: $handbrake_cmd\n****\n";
	
    return ($handbrake_cmd,$omp4_filename,$omp4_file);
}





1;
