108 changes: 47 additions & 61 deletions trunk/export/transcode.pm
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,11 @@ package export::transcode;
my $transcode = '';
my $mythtranscode = '';

my $aspect;
my $inaspect;
my $width;
my $height;
my $pad_h;
my $pad_w;
# Load nuv info
load_finfo($episode);

# Start the transcode command
$transcode = "$NICE transcode"
# -V is now the default, but need to keep using it because people are still using an older version of transcode
Expand All @@ -87,84 +84,73 @@ package export::transcode;
$transcode .= ' -u 100,'.($num_cpus);
}

if ($self->val('force_aspect')) {
$inaspect = $self->val('force_aspect');
print "Forcing input aspect ratio of $inaspect\n";
} else {
$inaspect = $episode->{'finfo'}{'aspect'};
}

# Import aspect ratio
if ($inaspect) {
if ($inaspect == 1 || $inaspect eq '1:1') {
$transcode .= ' --import_asr 1';
}
elsif ($inaspect =~ m/^1.3/ || $inaspect eq '4:3') {
$transcode .= ' --import_asr 2';
}
elsif ($inaspect =~ m/^1.7/ || $inaspect eq '16:9') {
$transcode .= ' --import_asr 3';
}
elsif ($inaspect == 2.21 || $inaspect eq '2.21:1') {
$transcode .= ' --import_asr 4';
}
if ($episode->{'finfo'}{'aspect'} eq '1:1') {
$transcode .= ' --import_asr 1';
}
# Output aspect ratio
if ($self->{'out_aspect'}) {
$aspect = $self->{'out_aspect'};
} else {
$aspect = $inaspect;
elsif ($episode->{'finfo'}{'aspect'} eq '4:3') {
$transcode .= ' --import_asr 2';
}
elsif ($episode->{'finfo'}{'aspect'} eq '16:9') {
$transcode .= ' --import_asr 3';
}
elsif ($episode->{'finfo'}{'aspect'} eq '2.21:1') {
$transcode .= ' --import_asr 4';
}

if ($self->{'aspect_stretched'}) {
# The output is actually a stretched aspect ratio
# (like 480x480 for SVCD, which is 4:3)
# Output aspect ratio
$self->{'out_aspect'} ||= $episode->{'finfo'}{'aspect_f'};

# Stretch the width to the full aspect ratio for calculating
$width = int($self->{'height'} * $aspect + 0.5);
# Calculate the height required to keep the source in aspect
$height = $width / $inaspect;
# Round to nearest even number
# The output is actually a stretched aspect ratio
# (like 480x480 for SVCD, which is 4:3)
if ($self->{'aspect_stretched'}) {
# Stretch the width to the full aspect ratio for calculating
$width = int($self->{'height'} * $self->{'out_aspect'} + 0.5);
# Calculate the height required to keep the source in aspect
$height = $width / $episode->{'finfo'}{'aspect_f'};
# Round to nearest even number
$height = int(($height + 2) / 4) * 4;
# Calculate how much to pad the height (both top & bottom)
# Calculate how much to pad the height (both top & bottom)
$pad_h = int(($self->{'height'} - $height) / 2);
# Set the real width again
# Set the real width again
$width = $self->{'width'};
# No padding on the width
# No padding on the width
$pad_w = 0;
}
# The output will need letter/pillarboxing
else {
# The output will need letter/pillarboxing
if ($self->{'width'} / $self->{'height'} <= $aspect) {
# We need to letterbox
$width = $self->{'width'};
$height = $width / $inaspect;
# We need to letterbox
if ($self->{'width'} / $self->{'height'} <= $self->{'out_aspect'}) {
$width = $self->{'width'};
$height = $width / $episode->{'finfo'}{'aspect_f'};
$height = int(($height + 2) / 4) * 4;
$pad_h = int(($self->{'height'} - $height) / 2);
$pad_w = 0;
} else {
# We need to pillarbox
$pad_h = int(($self->{'height'} - $height) / 2);
$pad_w = 0;
}
# We need to pillarbox
else {
$height = $self->{'height'};
$width = $height * $inaspect;
$width = int(($width + 2) / 4) * 4;
$pad_w = int(($self->{'width'} - $width) / 2);
$pad_h = 0;
$width = $height * $episode->{'finfo'}{'aspect_f'};
$width = int(($width + 2) / 4) * 4;
$pad_w = int(($self->{'width'} - $width) / 2);
$pad_h = 0;
}
}

$transcode .= ' --export_asr ';
if ($aspect == 1) {
if ($self->{'out_aspect'} == 1) {
$transcode .= '1';
}
elsif ($aspect =~ m/^1.3/) {
# 4:3
# 4:3
elsif ($self->{'out_aspect'} =~ m/^1.3/) {
$transcode .= '2';
}
elsif ($aspect =~ m/^1.7/) {
# 16:9
# 16:9
elsif ($self->{'out_aspect'} =~ m/^1.7/) {
$transcode .= '3';
}
elsif ($aspect == 2.21) {
# 2.21:1
elsif ($self->{'out_aspect'} == 2.21) {
$transcode .= '4';
}

Expand Down Expand Up @@ -211,8 +197,8 @@ package export::transcode;
}

if ($fpsout != $episode->{'finfo'}{'fps'}) {
$transcode .= ' -J fps=' . $episode->{'finfo'}{'fps'} . ':' .
$fpsout . ':pre';
$transcode .= ' -J fps=' . $episode->{'finfo'}{'fps'} . ':'
.$fpsout . ':pre';
}

# Resize & pad
Expand Down
2 changes: 0 additions & 2 deletions trunk/export/transcode/DVCD.pm
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ package export::transcode::DVCD;
sub export {
my $self = shift;
my $episode = shift;
# Load nuv info
load_finfo($episode);
# Force to 4:3 aspect ratio
$self->{'out_aspect'} = 1.3333;
$self->{'aspect_stretched'} = 1;
Expand Down
2 changes: 0 additions & 2 deletions trunk/export/transcode/DVD.pm
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,6 @@ package export::transcode::DVD;
sub export {
my $self = shift;
my $episode = shift;
# Load nuv info
load_finfo($episode);
# Force to 4:3 aspect ratio
$self->{'out_aspect'} = 1.3333;
$self->{'aspect_stretched'} = 1;
Expand Down
2 changes: 0 additions & 2 deletions trunk/export/transcode/SVCD.pm
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,6 @@ package export::transcode::SVCD;
sub export {
my $self = shift;
my $episode = shift;
# Load nuv info
load_finfo($episode);
# Force to 4:3 aspect ratio
$self->{'out_aspect'} = 1.3333;
$self->{'aspect_stretched'} = 1;
Expand Down
2 changes: 0 additions & 2 deletions trunk/export/transcode/VCD.pm
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ package export::transcode::VCD;
sub export {
my $self = shift;
my $episode = shift;
# Load nuv info
load_finfo($episode);
# Force to 4:3 aspect ratio
$self->{'out_aspect'} = 1.3333;
$self->{'aspect_stretched'} = 1;
Expand Down
3 changes: 1 addition & 2 deletions trunk/export/transcode/XviD.pm
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,7 @@ package export::transcode::XviD;
sub export {
my $self = shift;
my $episode = shift;
# Make sure we have finfo
load_finfo($episode);
# Set the output framerate
$self->{'out_fps'} = $episode->{'finfo'}{'fps'};
# Build the transcode string
my $params = " -N 0x55" # make *sure* we're exporting mp3 audio
Expand Down
51 changes: 45 additions & 6 deletions trunk/mythtv/nuvinfo.pm
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package mythtv::nuvinfo;
BEGIN {
use Exporter;
our @ISA = qw/ Exporter /;
our @EXPORT = qw/ &nuv_info /;
our @EXPORT = qw/ &nuv_info &aspect_str &aspect_float /;
}

# Opens a .nuv file and returns information about it
Expand All @@ -46,8 +46,10 @@ package mythtv::nuvinfo;
$info{'keyframedist'}
) = unpack('Z12 Z5 xxx i i i i a xxx d d i i i i', $buffer);
# Is this even a NUV file?
return mpeg_info($file) unless ($info{'finfo'} =~ /MythTVVideo/);
# return mpeg_info($file) unless ($info{'finfo'} =~ /\w/);
if ($info{'finfo'} !~ /MythTVVideo/) {
close DATA;
return mpeg_info($file);
}
# Perl occasionally over-reads on the previous read()
seek(DATA, 72, 0);
# Read and parse the first frame header
Expand Down Expand Up @@ -109,7 +111,10 @@ package mythtv::nuvinfo;
$info{'height'} += 0;
# Make some corrections for myth bugs
$info{'audio_sample_rate'} = 44100 if ($info{'audio_sample_rate'} == 42501 || $info{'audio_sample_rate'} =~ /^44\d\d\d$/);
$info{'aspect'} = 1.333;
$info{'aspect'} = '4:3';
# Cleanup
$info{'aspect'} = aspect_str($info{'aspect'});
$info{'aspect_f'} = aspect_float($info{'aspect'});
# Return
return %info;
}
Expand Down Expand Up @@ -152,15 +157,49 @@ package mythtv::nuvinfo;
."in your mplayer config). If not, email the output to the nuvexport author.\n\n"
." $program -v -v -v -v -nolirc -nojoystick -vo null -ao null -frames 0 -identify '$file'\n\n";
}

$info{'aspect'} =~ s/\,/\./;
# Cleanup
$info{'aspect'} = aspect_str($info{'aspect'});
$info{'aspect_f'} = aspect_float($info{'aspect'});
# ID_VIDEO_BITRATE=6500000
# ID_AUDIO_FORMAT=80
# ID_LENGTH=3554
# Return
return %info;
}

sub aspect_str {
my $aspect = shift;
# Already in ratio format
return $aspect if ($aspect =~ /^\d+:\d+$/);
# European decimals...
$aspect =~ s/\,/\./;
# Parse out decimal formats
if ($aspect == 1) { return '1:1'; }
elsif ($aspect =~ m/^1.3/) { return '4:3'; }
elsif ($aspect =~ m/^1.7/) { return '16:9'; }
elsif ($aspect == 2.21) { return '2.21:1'; }
# Unknown aspect
print STDERR "Unknown aspect ratio: $aspect\n";
return $aspect.':1';
}

sub aspect_float {
my $aspect = shift;
# European decimals...
$aspect =~ s/\,/\./;
# In ratio format -- do the math
if ($aspect =~ /^\d+:\d+$/) {
my ($w, $h) = split /:/, $aspect;
return $w / $h;
}
# Parse out decimal formats
if ($aspect == 1) { return 1; }
elsif ($aspect =~ m/^1.3/) { return 4 / 3; }
elsif ($aspect =~ m/^1.7/) { return 16 / 9; }
# Unknown aspect
return $aspect;
}

# return true
1;

Expand Down
11 changes: 8 additions & 3 deletions trunk/mythtv/recordings.pm
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ package mythtv::recordings;
# We should probably do some sorting by timestamp (and also count how many shows there are)
$num_shows = 0;
foreach my $show (sort keys %Shows) {
@{$Shows{$show}} = sort {$a->{start_time} <=> $b->{start_time} || $a->{channel} <=> $b->{channel}} @{$Shows{$show}};
@{$Shows{$show}} = sort {$a->{'start_time'} <=> $b->{'start_time'} || $a->{'channel'} <=> $b->{'channel'}} @{$Shows{$show}};
$num_shows++;
}

Expand All @@ -154,6 +154,11 @@ package mythtv::recordings;
my $episode = shift;
return if ($episode->{'finfo'});
%{$episode->{'finfo'}} = nuv_info($episode->{'filename'});
# Aspect override?
if ($exporter->val('force_aspect')) {
$episode->{'finfo'}{'aspect'} = aspect_str($exporter->val('force_aspect'));
$episode->{'finfo'}{'aspect_f'} = aspect_float($exporter->val('force_aspect'));
}
}

#
Expand All @@ -168,9 +173,9 @@ package mythtv::recordings;
$day = int($day);
# Special datetime format?
if ($showtime = arg('date')) {
print "$year-$month-$day-$hour-$minute-$second -> ",ParseDate("$year-$month-$day $hour:$minute:$second"), "\n";
#print "$year-$month-$day-$hour-$minute-$second -> ",ParseDate("$year-$month-$day $hour:$minute:$second"), "\n";
$showtime = UnixDate(ParseDate("$year-$month-$day $hour:$minute:$second"), $showtime);
print "$showtime\n";exit;
#print "$showtime\n";exit;
}
# Default to the standard
else {
Expand Down
33 changes: 17 additions & 16 deletions trunk/nuv_export/cli.pm
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ package nuv_export::cli;
our $config_file = undef;
GetOptions('ffmpeg' => sub { $export_prog = 'ffmpeg'; },
'transcode' => sub { $export_prog = 'transcode'; },
'mencoder' => sub { $export_prog = 'mencoder'; },
'mencoder' => sub { $export_prog = 'mencoder'; },
'config|c=s' => \$config_file,
);

Expand Down Expand Up @@ -110,28 +110,29 @@ package nuv_export::cli;
my %args;

# Load the following extra parameters from the commandline
add_arg('search-only', 'Search only, do not do anything with the found recordings');
add_arg('confirm!', 'Confirm commandline-entered choices');
add_arg('search-only', 'Search only, do not do anything with the found recordings');
add_arg('confirm!', 'Confirm commandline-entered choices');

add_arg('title=s', 'Find programs to convert based on their title.');
add_arg('subtitle|episode=s', 'Find programs to convert based on their subtitle (episode name).');
add_arg('description=s', 'Find programs to convert based on their description.');
add_arg('infile|input|i=s', 'Input filename');
add_arg('chanid|channel=i', 'Find programs to convert based on their chanid');
add_arg('starttime|start_time=i', 'Find programs to convert based on their starttime.');
add_arg('title=s', 'Find programs to convert based on their title.');
add_arg('subtitle|episode=s', 'Find programs to convert based on their subtitle (episode name).');
add_arg('description=s', 'Find programs to convert based on their description.');
add_arg('infile|input|i=s', 'Input filename');
add_arg('chanid|channel=i', 'Find programs to convert based on their chanid');
add_arg('starttime|start_time=i', 'Find programs to convert based on their starttime.');

add_arg('require_cutlist', 'Only show programs that have a cutlist?');
add_arg('require_cutlist', 'Only show programs that have a cutlist?');
add_arg('force_aspect|force-aspect=s', 'Force input aspect ratio rather than detect it.');

add_arg('mode|export=s', 'Specify which export mode to use');
add_arg('mode|export=s', 'Specify which export mode to use');

add_arg('noserver|no-server', "Don't talk to the server -- do all encodes here in this execution");
add_arg('noserver|no-server', "Don't talk to the server -- do all encodes here in this execution");

add_arg('nice=i', 'Set the value of "nice" for subprocesses');
add_arg('version', 'Show the version and exit');
add_arg('nice=i', 'Set the value of "nice" for subprocesses');
add_arg('version', 'Show the version and exit');

# Load the commandline options
add_arg('help:s', 'Show nuvexport help');
add_arg('debug', 'Enable debug mode');
add_arg('help:s', 'Show nuvexport help');
add_arg('debug', 'Enable debug mode');

# Load the commandline arguments
sub load_cli_args {
Expand Down
3 changes: 2 additions & 1 deletion trunk/nuv_export/shared_utils.pm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ package nuv_export::shared_utils;
&clear &find_program &shell_escape
&wrap &wipe_tmpfiles
&system &mkdir
@Exporters @episodes
@Exporters @episodes $exporter
$DEBUG $NICE
$num_cpus $is_child
@tmpfiles %children
Expand All @@ -30,6 +30,7 @@ package nuv_export::shared_utils;
# Variables that we export so all other modules can share them
our @Exporters; # A list of the various exporters
our @episodes; # A list of the requested episodes
our $exporter; # The selected export module
our $is_child = 0; # This is set to 1 after forking to a new process
our @tmpfiles; # Keep track of temporary files, so we can clean them up upon quit
our %children; # Keep track of child pid's so we can kill them off if we quit unexpectedly
Expand Down
28 changes: 7 additions & 21 deletions trunk/nuv_export/ui.pm
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ package nuv_export::ui;
my $description = arg('description');
next unless (!$subtitle || $episode->{'title'} =~ /$subtitle/si);
next unless (!$description || $episode->{'description'} =~ /$description/si);
# Make sure we have finfo
load_finfo($episode);
# Add this to the list
push @matches, $episode;
}
}
Expand Down Expand Up @@ -224,15 +227,8 @@ package nuv_export::ui;
$query .= "$count. ";
# Print out the show name
$query .= "$episode->{'title'} " if ($episode->{'title'} && $episode->{'title'} ne 'Untitled');
if($episode->{'finfo'}{'aspect'} == "1.3333") {
$aspect = "4:3";
} elsif($episode->{'finfo'}{'aspect'} == "1.7777" ||
$episode->{'finfo'}{'aspect'} == "1.7778" ) {
$aspect = "16:9";
} else {
$aspect = "$episode->{'finfo'}{'aspect'}:1"
}
$query .= "($episode->{'showtime'}) ".$episode->{'finfo'}{'width'}.'x'.$episode->{'finfo'}->{'height'}.' '.$episode->{'finfo'}{'video_type'}." ($aspect)";
$query .= "($episode->{'showtime'}) ".$episode->{'finfo'}{'width'}.'x'.$episode->{'finfo'}->{'height'}
.' '.$episode->{'finfo'}{'video_type'}.' ('.$episode->{'finfo'}{'aspect'}.')';
$query .= wrap($episode->{'description'}, 80, $newline, '', $newline) if ($episode->{'description'});
$query .= "\n";
$episode_choices[$count-1] = $episode;
Expand Down Expand Up @@ -281,11 +277,8 @@ package nuv_export::ui;
# Build the query
my $count = 0;
my $query = "\nYou have chosen to export $num_episodes episode" . ($num_episodes == 1 ? '' : 's') . ":\n\n";
my $aspect;
foreach my $episode (@episodes) {
$count++;
# Make sure we have finfo
load_finfo($episode);
# Print out this choice, adjusting space where necessary
$query .= ' ';
$query .= ' ' if ($num_episodes > 10 && $count < 10);
Expand All @@ -294,15 +287,8 @@ package nuv_export::ui;
# Print out the show name
$query .= "$episode->{'show_name'}:$newline";
$query .= "$episode->{'title'} " if ($episode->{'title'} && $episode->{'title'} ne 'Untitled');
if($episode->{'finfo'}{'aspect'} == "1.3333") {
$aspect = "4:3";
} elsif($episode->{'finfo'}{'aspect'} == "1.7777" ||
$episode->{'finfo'}{'aspect'} == "1.7778" ) {
$aspect = "16:9";
} else {
$aspect = "$episode->{'finfo'}{'aspect'}:1"
}
$query .= "($episode->{'showtime'}) ".$episode->{'finfo'}{'width'}.'x'.$episode->{'finfo'}->{'height'}.' '.$episode->{'finfo'}{'video_type'}." (".$aspect.")";
$query .= "($episode->{'showtime'}) ".$episode->{'finfo'}{'width'}.'x'.$episode->{'finfo'}->{'height'}
.' '.$episode->{'finfo'}{'video_type'}.' ('.$episode->{'finfo'}{'aspect'}.')';
$query .= wrap($episode->{'description'}, 80, $newline, '', $newline) if ($episode->{'description'});
$query .= "\n";
}
Expand Down
8 changes: 4 additions & 4 deletions trunk/nuvexport
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# $Author$

# Version
$VERSION = '0.2 0.20050723.cvs';
$VERSION = '0.2 0.20050823.svn';

# Autoflush buffers
$|++;
Expand Down Expand Up @@ -114,12 +114,12 @@
# Load the recordings, and the $video_dir variable
load_recordings();

# Which exporter to use
$exporter = query_exporters($export_prog);

# Load episodes from the commandline (and display/quit if this is search-only)
@episodes = load_cli_episodes();

# Which exporter to use
my $exporter = query_exporters($export_prog);

# Gather the episodes we want to transcode (unless we have them from the cli already)
@episodes = &load_episodes(@episodes) unless ($is_cli);

Expand Down
2 changes: 1 addition & 1 deletion trunk/nuvexport.spec
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Name: nuvexport
Version: 0.2
Release: 0.20050723.cvs
Release: 0.20050823.svn
License: GPL
Summary: mythtv nuv video file conversion script
URL: http://forevermore.net/nuvexport/
Expand Down
7 changes: 7 additions & 0 deletions trunk/nuvexportrc
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@
#
fast_denoise = yes

#
# If nuvexport is having trouble detecting the aspect ratio of your recordings
# (MythTV still hard-codes all software-encoded files as 1:1 regardless of
# the true aspect), set this option to one of the following:
#
# force_aspect = [ 1:1 4:3 16:9 2.21:1 ]

</generic>

<ffmpeg>
Expand Down