HDTV using MPlayer
In my desktop computer, I’ve got an nvidia GeForce 6150 PCI-E video card. It has a built-in mpeg2 decoding helper in it. Using Linux, this is called XvMC, or Xvideo Motion Compensation. I finally got it partially usable.
I’m currently watching the news on WJBF, the only channel I get b/c I haven’t fully setup my antenna. Using xvmc is fairly simple:
mplayer -vc ffmpegmc12 -vo xvmc -framedrop dvb://WJBF-DT
I add -framedrop to keep the video and audio sync’ed. Mplayer will rant about waiting for retrace. Using OpenGL is actually better, for me at least.
mplayer -vo gl2 -framedrop dvb://WJBF-DT
It dropped 14 frames at the beginning, but hasn’t dropped another in 10 minutes. XvMC would have crapped out by now. A/V sync is still perfect. I’ve even got it full screen and it’s resizing from 1280×720 (720 HD resolution) to 1440×900.
PVR Cron
For about a year now, I’ve been playing around with my digital tuner card. It wasn’t until I turned off the cable that I have a need to use it. Using some cool linux tools, I’ve made a script to record HDTV broadcasts to my computer. It is a work in progress, but here’s what I’ve got so far.
The Tuner Card
The tuner card is DVB based on a Conextant chipset, so the first step was to get my kernel to make the card usable. A quick check will show if the driver is loaded:
dmesg | grep dvb
The Tools Required
- dvb-atsc-tools
- azap
- ffmpeg
Channel Scan
Scan for channels using:
dvbscan /usr/share/dvb/atsc/us-ATSC-center-frequencies-8VSB > ~/.azap/channels.conf
Edit the file ~/.azap/channels.conf to make sure the channel names are correct. Your base frequencies file may be in a different location, but it is usually under /usr/share.
Iteration 1: Crontab Recording
At first, I used only the crontab to record. Here’s an example:
24 12 * * * /usr/bin/azap -c /home/dvr/.azap/channels.conf -r WRDW-HD
25 12 * * * /bin/cat /dev/dvb/adapter0/dvr0 > /data/dvr/young-restless.mpeg
35 13 * * * /usr/bin/pkill cat
36 13 * * * /usr/bin/pkill azap
37 13 * * * /usr/bin/ffmpeg -i /data/dvr/young-restless.mpeg -s 1024x476 -vcodec libxvid -b 1600000 -acodec copy /data/dvr/y-r-friday.avi
This is a very ugly solution with lots of cracks. For instance, if I were running cat from a console when /usr/bin/pkill cat were running, it would die. Heaven forbid another processes is using cat when that runs. Also, I had to change the name of the ffmpeg output file every day.
Iteration 2: Cronable Perl Script
This script does pretty much the same thing as the above 4 lines in the crontab does. This means you don’t have to write 4 lines in the crontab for each recording, just 1 line. Also, the file name is appended with the date in yyyy-mm-dd format.
#!/usr/bin/perl
#Does someone need a reminder?
if ( $#ARGV != 2 ) {
print “Usage:\n”;
print “record.pl \n”;
exit;
}
#Creates a random 16 character (a-z) string
sub randstr {
my @chars=(‘a’..’z');
my $res = “”;
for(my $i=0;$i<16;$i++) {
$res .= $chars[rand($#chars)];
}
return $res;
}
#Grab the command line args
my ( $channel, $length, $finalFileName ) = @ARGV;
#Temporary mpeg filename
my $tempFileName = randstr();
#Add date to final filename
$finalFileName .= “-”.`date +%Y-%m-%d`;
$finalFileName =~ s/\n//;
#Start Azap in the background
print “Starting azap\n”;
system( “/usr/bin/azap -c /home/barry/.azap/channels.conf -r $channel >/dev/null 2>/dev/null &” );
sleep 5;
#Start cat in the background
print “Starting cat\n”;
system( “/bin/cat /dev/dvb/adapter0/dvr0 > /data/dvr/$tempFileName.mpeg &” );
#Sleep the required seconds for the show to record
print “Recording for “.(60*$length).” seconds…\n”;
sleep 60*$length;
#TODO: Remove pkill, as it may cause problems
print “Killing cat and azap.\n”;
`pkill cat`;
`pkill azap`;
#Resize & Encode to XVID using ffmpeg
#ffmpeg sometimes stops working b/c of bad mpeg data
#TODO: Replace with mencoder
print “Encoding…\n”;
`/usr/bin/ffmpeg -i /data/dvr/$tempFileName.mpeg -s 1024×476 -vcodec libxvid -b 1600000 -acodec copy /data/dvr/$finalFileName.avi`;
#Remove the temporary mpeg file
`rm $tempFileName.mpeg`;
print “Done!\n”;
I know it’s not the most elegant of perl scripts, but it gets the job done. Here’s a sample cron:
25 12 * * * /home/dvr/record.pl WRDW-HD 70 young-restless
As you can see from the TODO comments, I continue to tinker with the script. When I make a good development, I’ll post it. If you have any suggestions, feel free to post a comment or contact me.