#!/usr/bin/perl
#
# $Id: mencoder_tivo.pl 9 2005-10-04 13:07:50Z andrew $
# Subversion repository: http://svn.stellman-greene.com/mencoder_tivo/
# Home page: http://www.stellman-greene.com/astellman/mencoder_tivo/
# 
# This software is released under the GNU General Public License (GPL).
# http://www.gnu.org/copyleft/gpl.html
#
# (c) 2005 Andrew Stellman

use strict;

my $version = "1.0.1";
my $version_date = "03-Oct-2005";

=head1 mencoder_tivo.pl

perl script to help you use MEncoder to create files that you can transfer to your TiVo

=head2 Usage

mencoder_tivo.pl filename [filename [filename [...]]] --output=filename arguments

=head1 Description

When TiVo released version 7.2 of the TiVo software and version 2.2 of the TiVo desktop software, they added a feature which allows the TiVo to retrieve video from a home network. Unfortunately, the TiVo can't play all formats. mencoder_tivo.pl will read any video file and convert it into a format which the TiVo can play.

mencoder_tivo.pl requires MEncoder to be in the path. MEncoder is part of the MPlayer system which can be downloaded from http://www.mplayerhq.hu/.

=head2 Arguments

=head3 filename

A list of one or more input files must be specified on the command line. The input files will be stitched together into one output file.

=head3 --output=filename

One output filename must be specified.

=head3 --low-quality (optional)

Create a smaller, low-quality file. By default, mencoder_tivo.pl produces a 480x480 file with video bitrate of 4000 (maximum 12000). The low-quality option will reduce the resolution to 352x480 and set the bitrate to 1000. This option will override the --resolution and --bitrate options.

=head3 --very-low-quality (optional)

Create an even smaller, lower-quality file. This reduces the bitrate even further (to 750), the framerate to 24000/1001 (default is 30000/1001) and the audio sample rate to 64 (default is 96). This option overrides the --low-quality option.

=head3 --widescreen (optional)

Set the aspect to 16/9. (The default aspect is 4/3.)

=head3 --resolution=[720:480|704:480|544:480|480:480|352:480] (optional)

The default resolution is 480x480, but one of the other TiVo-supported resolutions can be used instead.

=head3 --bitrate=4000/12000 (optional)

By default, files are encoded with a bitrate of 4000 and maximum bitrate of 12000. This option will override that default.

=head3 --omit-lavcresample (optional)

Omit the '-af lavcresample=48000' option, which will cause some versions of MEncoder to crash.

=head3 --print (optional)

This option tells mencoder_tivo.pl to print the MEncoder command instead of executing it.

=head3 --help (optional)

Display a help message.


=cut


# read the arguments
my $argument;
my %arguments = ();
my @input_files = ();
my $reading_filenames = 1;
while( $argument = shift ) {
	# check for --help argument
	print_usage("") if $argument =~ "--help";

	# read the filenames first, then the --* arguments
	if ($reading_filenames) {
		if ($argument =~ /^--/) {
			if ($#input_files == -1) { 
				print_usage("At least one input file must be specified");
			} else {
				$reading_filenames = 0;
			}
		} else {
			$input_files[$#input_files + 1] = $argument;
		}
	}
	
	if (!$reading_filenames) {
		# read the --* arguments
		if ($argument =~ /^(.*)=(.*)$/) {
			check_argument ( $1, $2 );
			$arguments{ $1 } = $2;
		} else {
			check_argument ( $argument, "" );
			$arguments{ $argument } = "1";
		}
	}
}

# make sure input and output filenames were specified
if ( $#input_files == -1 ) {
	print_usage("One or more input files must be specified.");
}
if ( $arguments{ "--output" } eq "" ) {
	print_usage("An output file must be specified.");
}


# set defaults
my $bitrate = 4000;
my $max_bitrate = 12000;
my $min_bitrate = 1000;
my $resolution = "480:480";
my $lavcresample = "-af lavcresample=48000";
my $aspect = "4/3";
my $audiorate = "96";
my $framerate = "30000/1001";

# set video bitrate
# (note that --low-quality will override this)
if ( $arguments{ "--bitrate" } ne "" ) {
	print $arguments{ "--bitrate" } . "\n";
	$arguments{ "--bitrate" } =~ /^(\d+)\/(\d+)$/;
	$bitrate = $1;
	$max_bitrate = $2;
}

# set resolution
# (note that --low-quality will override this)
if ( $arguments{ "--resolution" } ne "" ) {
	$resolution = $arguments{ "--resolution" };
}


# set low-quality parameters
if ( $arguments{ "--low-quality" } ne "" ) {
	$bitrate = 1000;
	$max_bitrate = 1000;
	$resolution = "352:480";
}

# set very-low-quality parameters
if ( $arguments{ "--very-low-quality" } ne "" ) {
	$bitrate = 750;
	$max_bitrate = 750;
	$min_bitrate = 750;
	$audiorate = "64";
	$framerate = "24000/1001";
	$resolution = "352:480";
}

# set widescreen parameters
if ( $arguments{ "--widescreen" } ne "" ) {
	$aspect = "16/9";
}



# check for --omit-lavcresample
if ( $arguments { "--omit-lavcresample" } ne "" ) {
	$lavcresample = "";
}


# build command line
my $command = "mencoder -of mpeg -oac lavc -ovc lavc -ofps $framerate -srate 48000 " 
	. "$lavcresample -vf scale=$resolution -lavcopts aspect=$aspect:acodec=mp2:abitrate=$audiorate:" 
	. "vcodec=mpeg2video:vmax_b_frames=2:vbitrate=$bitrate:vrc_maxrate=$max_bitrate:"
	. "vrc_minrate=$min_bitrate:vrc_buf_size=1835 -o \"$arguments{ '--output' }\" ";
for ( my $i = 0; $i <= $#input_files; $i++ ) {
	$command .= "$input_files[$i] ";
}



# execute MEncoder
if ( $arguments{ "--print" } ne "" ) {
	print "$command\n";
} else {
	# Open the output of the command, use sysread() to do an unbuffered read
	# so we get real-time output
	open(CMD,"$command 2>&1 |");
	my $char;
	while(sysread(CMD,$char,1)) {
		print $char;
	}
	close(CMD);
}






# verify that an argument is allowed
sub check_argument {
	my ($argument, $parameter) = @_;
	if ( $argument eq "--resolution" ) {
		return if $parameter eq "720:480";
		return if $parameter eq "704:480";
		return if $parameter eq "544:480";
		return if $parameter eq "480:480";
		return if $parameter eq "352:480";
		print_usage("Invalid parameter '$parameter' for --resolution argument\nResolution can be either 720:480, 704:480, 544:480, 480:480 or 352:480");
	}
	if ( $argument eq "--bitrate" ) {
		return if $parameter =~ /^\d+\/\d+$/;
		print_usage("Invalid parameter '$parameter' for --bitrate argument");
	}
	if ( $argument eq "--output" ) {
		print_usage("A filename must be specified with --output") if ( $parameter eq "" );
		return;
	}
	return if ( $argument eq "--low-quality" )  && ( $parameter eq "" );
	return if ( $argument eq "--very-low-quality" )  && ( $parameter eq "" );
	return if ( $argument eq "--widescreen" )  && ( $parameter eq "" );
	return if ( $argument eq "--omit-lavcresample" ) && ( $parameter eq "" );
	return if ( $argument eq "--print" ) && ( $parameter eq "" );
	print_usage("Invalid argument '$argument=$parameter'") if $parameter ne "";
	print_usage("Invalid argument '$argument'");
}




# print the usage
sub print_usage {
	my ($message) = @_;
	
	print "$message\n\n" if $message ne "";
	
	print <<EOM;
mencoder_tivo.pl $version $version_date (c) 2005 Andrew Stellman
mencoder_tivo.pl filename [filename [filename [...]]] --output=filename arguments

Valid arguments:

filename 
  Specify one or more input files to be converted
  Input files will be stitched together into one output file

--output=filename
  Specify the output filename

--low-quality (optional)
  Create a smaller, low-quality file (bitrate 1000, resolution 352:480). 
  This option will override the --resolution and --bitrate options.

--very-low-quality (optional)
  Create an even smaller, lower-quality file. This reduces the bitrate 
  even further (to 750), the framerate to 24000/1001 (default is 30000/1001) 
  and the audio sample rate to 64 (default is 96). This option overrides 
  the --low-quality option.

--widescreen (optional)
  Set the aspect to 16/9. (The default aspect is 4/3.)
  
--resolution=[720:480|704:480|544:480|480:480|352:480] (optional)
  Specify a resolution (default is 480:480).

--bitrate=4000/12000 (optional)
  Specify a bitrate (default is 4000 with maximum bitrate 12000)

--omit-lavcresample
  Omit the '-af lavcresample=48000' option, which will cause some versions 
  of MEncoder to crash.

--print (optional)
  print the MEncoder command instead of executing it.

--help (optional)
  Display this message.
  
mencoder_tivo.pl requires MEncoder to be in the path. MEncoder is part of the
MPlayer system which can be downloaded from http://www.mplayerhq.hu/. It will
convert any video file supported by mplayer. Make sure to install all video
codecs when you install mplayer.

For more information:
http://www.stellman-greene.com/astellman/mencoder_tivo/
EOM
	exit(-1);
}
