Removing Letterboxing in MythTV

I currently record all my shows in MythTV using a couple of Hauppauge PVR-[12]50’s. This works great, but I sometimes record shows originally  filmed in HD and they show up as letterboxed 4:3 shows. This isn’t a problem when I play them back on a standard def 4:3 display, but when played back on my widescreen displays they end up having a black border all they way around the show. I know I can just use the playback menu  ‘adjust fill’ option and set it to ‘full’ in order to fix this, but that has to be done every time I start playback. I wish there was a way for MythTV to automatically detect this situation and automatically select the correct playback fill.

To handle this situation, I created a small ‘user job’ script that I run automatically on the shows that I know will be recorded in a letterboxed format. It takes the original 4:3 mpeg2 recording and crops 60 pixels off the top and bottom and re-encodes it to a 16:9 aspect mpeg2 file. It then replaces the original file with the transcoded version, updates the mythconverg database to reflect the changed file settings, runs mythcommflag to rebuild the seektable (ffw/rwd doesn’t work without this) and finally runs a lossless mythtranscode with the –mpeg2 option (length of the recording is incorrectly shown without this).

The following is that script…

—————————————————————————–

#!/usr/bin/perl -w
# sdletterbox.pl v1.0
# By Shawn Flynn
#
# A MythTV user job script for cropping/transcoding Standard Def 4:3
# letterboxed recordings into Standard Def 16:9 Widescreen
#
# Usage info will be output if the script is run with no arguments (or insufficient arguments)
#
# Contains elements of mythtv.pl by Nigel Pearson
# and ipodexport.pl by Justin Hornsby
#
# Requirements: nice, ffmpeg, perl and the DBI & DBD::mysql modules
# Also requires MythTV perl bindings
#
#
# PERL MODULES WE WILL BE USING
use DBI;
use DBD::mysql;
use MythTV;
# Set default values
my $chanid = '';
my $starttime = '';

$connect = undef;
$keepold = 0;
$debug = 0;

$croptop = '60';
$cropbottom = '60';
$vcodec = 'mpeg2video';
$vbitrate = '8000k';

##################################
# #
# Main code starts here !! #
# #
##################################

$usage = "\nUsage: \n"
  ."sdletterbox.pl chanid=%CHANID starttime=%STARTTIME% [keepold] [debug]\n"
  ."\n%CHANID% = channel ID associated with the recording to export\n"
  ."%STARTTIME% = recording start time in either 'yyyy-mm-dd hh:mm:ss' or 'yyyymmddhhmmss' format\n"
  ."croptop=nn = number of lines to remove from top of video\n"
  ."cropbottom=nn = number of lines to remove from bottom of video\n"
  ."vcodec=xxxxx = ffmpeg video codec to use for transcode\n"
  ."vbitrate=xxxx = video bitrate to use for transcode\n"
 ."keepold = do not delete the original file. Rename to filename.old instead.\n"
  ."debug = enable debugging information - outputs which commands would be run etc\n"
  ."\nExample: sdletterbox.pl chanid=3310 starttime=20080626225900 debug \n";

# get this script's ARGS
#

foreach (@ARGV){
  if ($_ =~ m/chanid/) {
  $chanid = (split(/\=/,$_))[1];
  }
  elsif ($_ =~ m/starttime/) {
  $starttime = (split(/\=/,$_))[1];
  }
  elsif ($_ =~ m/croptop/) {
  $croptop = (split(/\=/,$_))[1];
  }
  elsif ($_ =~ m/cropbottom/) {
  $cropbottom = (split(/\=/,$_))[1];
  }
  elsif ($_ =~ m/vcodec/) {
  $vcodec = (split(/\=/,$_))[1];
  }
  elsif ($_ =~ m/vbitrate/) {
  $vbitrate = (split(/\=/,$_))[1];
  }
  elsif ($_ =~ m/debug/) {
  $debug = 1;
  }
  elsif ($_ =~ m/keepold/) {
  $keepold = 1;
  }
}

if ($chanid eq '') {
  die "$usage";
}
elsif ($starttime eq '') {
  die "$usage";
}

# Kludge to compensate for my offset capture on source 3
if ($chanid gt 2999) {
  $croptop -= 10;
  $cropbottom += 10;
}

# Setup Database Connections and Perl Bindings
my $myth = new MythTV();
$connect = $myth->{'dbh'};

# Get the Filename and Path from DB
if ($debug) {
  print ("Fetching filename and path...\n");
}

$query = "SELECT basename FROM recorded WHERE chanid=$chanid AND starttime=$starttime";
$query_handle = $connect->prepare($query);
$query_handle->execute() || die "Unable to query recorded table\n";
my ($basename) = $query_handle->fetchrow_array;
if ($debug) {
  print ("Filename = $basename\n");
}

my $storagegroup = new MythTV::StorageGroup();
$dir = $storagegroup->FindRecordingDir($basename);
if ($debug) {
  print ("Path = $dir\n");
}

$filename = $dir . "/" . $basename;
$filenameold = $filename . ".old";
$filenamenew = $dir . "/sdletterbox." . $basename;

# Is this a 4:3 aspect recording?
# Query the DB to see if it knows the aspect ratio
$query = "SELECT aspect FROM recordedfile WHERE chanid=$chanid AND starttime=$starttime";
$query_handle = $connect->prepare($query);
$query_handle->execute() || die "Unable to query recordedfile table\n";
$aspectratio = $query_handle->fetchrow_array;
if (!$aspectratio) {
  # Aspect ratio wasn't in the DB, see if mplayer can find it from the file
  $aspectratio=0.0;
  my $data = `mplayer -v -v -v -v -nolirc -nojoystick -vo null -ao null -frames 1 -identify '$filename' 2>/dev/null`;
# study $data;
  ($aspectratio) = $data =~ m/^ID_VIDEO_ASPECT=0*([1-9]\d*(?:[\.\,]\d+)?)/m;
}
if ($debug) {
  print ("Aspect Ratio = $aspectratio\n");
}
if (!($aspectratio =~ m/^1.3/)) {
  die "This is not a 4:3 aspect recording\n";
}

# Is this a letterboxed show?
# To be implemented in the future if I ever figure out how to do it

# Transcode the file
if (-e $filename) {
  $command = "nice -n19 ffmpeg -i $filename -croptop $croptop -cropbottom $cropbottom -vcodec $vcodec -sameq -b $vbitrate -acodec copy -aspect 16:9 -y $filenamenew";
  if ($debug) {
  print "\n\nUSING $command \n\n";
  }
  system "$command";
}
else {
  die "File $filename does not exist.";
}

# Swap original<>new files
# Delete the original file if requested
if ($debug) {
  print "\nRenaming $filename to $filenameold\n";
}
rename($filename,$filenameold);
if ($debug) {
  print "\nRenaming $filenamenew to $filename\n";
}
rename($filenamenew,$filename);
if (!$keepold) {
  if ($debug) {
  print "\nDeleting $filenameold\n";
  }
  unlink($filenameold);
}

# Set the Widescreen flag in the DB
if ($debug) {
  print ("Setting Widescreen flag\n");
}

$query = "UPDATE program SET hdtv=0,videoprop='WIDESCREEN' WHERE chanid=$chanid AND starttime=$starttime";
$query_handle = $connect->prepare($query);
$query_handle->execute() || die "Unable to query program table\n";

$query = "UPDATE recordedprogram SET hdtv=0,videoprop='WIDESCREEN' WHERE chanid=$chanid AND starttime=$starttime";
$query_handle = $connect->prepare($query);
$query_handle->execute() || die "Unable to query recordedprogram table\n";

# RE-index the file
if ($debug) {
  print "Rebuilding seektable for $filename\n";
}
system "mythcommflag --chanid $chanid --starttime $starttime --rebuild";

# Lossless transcode to fix file length displayed
if ($debug) {
  print "Lossless mythtranscode for $filename\n";
}
system "mythtranscode --chanid $chanid --starttime $starttime --mpeg2";

—————————————————————————–

One Response to “Removing Letterboxing in MythTV”

  1. Scott says:

    Does this work on .24? When I run it, it tells me the program is not 4:3, and it is. Thanks.

Leave a Reply

You must be logged in to post a comment.