Entries Tagged as ''

Anniversary

Today is my 2nd. wedding anniversary! It is also my mothers birthday. Happy birthday Mum!

Last year we were apart for our 1st. anniversary, as Mingzhen had just left for Beijing to embark on her Chinese career. It was about this time last year, just as she arrived in Beijing that Mingzhen discovered her pregnancy and our plans evolved. Now we are apart again as our little daughter is now 4 months old and they are both waiting for me in Beijing. I will spend a month here finishing up ready to embark on my Chinese career. If all goes well, I will be there in mid-July when I can finally give her my present.

It seems we have had some bad luck with timing our anniversary so far, on the other hand, we had the blessing of Anya arriving in the meantime. Now if we can just manage to all be together next year, that will make it all worthwhile.

I love you Mingzhen.

PSP Encode

I have been having loads of fun with my PSP slim. I researched playing video on this device, turns out it supports both standard MPEG4 and thanks to Sony being pretty keen on AVCHD, it now supports AVC MP4 file formats, which gives superior quality playback and/or compression.

Since I live in Australia, I wanted to convert both my widescreen camcorder files to view on my PSP and DVDs as well. We use the PAL standard, at 25 frames per second these files will not play on my Japanese PSP, which can only support NTSC frame rates of 23.976 and 29.97 fps.

So, I have developed a script that uses mencoder and ffmpeg, mainly to convert DVDs with subtitles to the PSP.

Features:

  • Supports creation of full 480×272 screen size AVC MP4 videos.
  • Supports subtitle rendering.
  • Easy to use, just run it a directory with free space, with or without a filename – no filename means access the dvd device.
  • Auto frame rate conversion – will convert 25 fps input to 23.976 by remuxing slower audio (a bit slow, 2 conversions).
  • Auto track selection – at present just converts the longest track only – for movies.
  • Adds a little gamma to the output, PSPs need it for video I think.

Requirements:

  • Linux, prefer Debian or Ubuntu I think, should work on others too.
  • mplayer/mencoder
  • ffmpeg
  • sox

I am using PSP slim firmware 3.71 – if you want to try this script, you probably need something recent like this or newer.

Usage:

Just make a new directory on a location with plenty of space – if it needs to down convert from PAL, this is a slow and space consuming process. It currently takes 2 conversions. It uses threads to speed things up a little, could take a few hours to complete on a 1.8Ghz dual core. So have around 10Gb free when you start.

Change to this new directory.

Now Simply run it with a video file or it will default to using the device /dev/cdrom.

It should give you some feedback about the 2 stages or 1 stage it needs to do.

When its done, you should have a file called output.mp4 in that directory. Maybe a log file or 2. Just move that mp4 to your PSPs video folder, maybe change the filename too. You should be able to watch it now.

Its still very basic, its just designed to work without much brilliant feedback at this stage.

Download pspencode.pl
#!/usr/bin/perl
 
# script to automate the encoding of PSP AVC videos with subtitles
# I release this under GPLv2 you know what that means.
 
#$tvaspect = "scale"; # Plays on PSP in 'full screen' mode and on a 16:9 TV
$tvaspect = "expand"; # Plays on PSP in 'zoom' mode and on a regular 4:3 TV
$profile = 1; # 2 different profiles for AVC MP4, 1=regular and 2=large.
$debug = 0; # 1 for messages and a short test, 2 for no final run
			# 3 for test run with output
#$noise = ",noise=5t";
#$noise = ",noise=3t";
#$noise = "";
$gamma = "eq=4:0";
$slang = "-slang en";
$alang = "-alang zh";
 
$bframe = "i_certify_that_my_video_stream_does_not_use_b_frames:";
#$bframe = "";
 
if ($profile == 1) {
	$tvaspect = "scale";
}
$disaspect = 1.7647; # this is used for calculating the subtitles position.
$embed = 1; # embedd fonts - only appropriate for encoding
$subexp = ":";
$output = "output.mp4";
$ffmpeglog = "ffmpeg.log";
$poll = 2;
$rfsw = 720; # rate frame size - the width of the first stage in 2 stage encode
$rfsh = 544; # rate frame size - the height of the first stage in 2 stage encode
 
sub execdebug {
	my $cmd = join (" ",@_);
	if ($debug > 0) {
		print "$cmd\n";
	}
#	my $out = spacepad(132,$cmd);
	if ($debug < 2) {
		$error =  `sh -c \"$cmd\" 2>&1`;
	}
	if ($debug > 2) {
		system $cmd;
	}
	return $error;
}
 
# first arg is the ref num, rest is command
sub execmencode {
	my $cmd = join (" ",@_[2..$#_]);
	my $out = "";
	if ($debug > 0) {
		print "$cmd\n";
		$out = "| tee stage1.log ";
	}
	if ($debug == 2) {
		return;
	}
	open (FILE,"$cmd 2>&1$out |");
	print "Stage ".@_[0].".\n";
	if ($debug == 3) {
		print;
	}
	$skip = 100;
	$i = 0;
	while (<FILE>) {
		$i++;
		if (($i % $skip) != 1) {
			next;
		}
		if (/^Pos:/) {
#			print;
			@row = split(/\(|\)/,$_);
			if ($complete != @row[1]) {
				$complete = @row[1];
				print "Stage ".@_[0].": $complete\n";
			}
		}
	}
	close FILE;
	print "Stage ".@_[0]." complete.\n";
}
 
sub execffmpeg {
	my $cmd = join (" ",@_[2..$#_]);
	unless ($pid = fork) {
		unless (fork) {
			`sh -c \"$cmd\" > $ffmpeglog 2>&1`;
			exit;
		}
		exit;
	}
	my $found = 0;
	for ($i=0;$i<16;$i++) {
		if (-s $ffmpeglog) {
			$found = 1;
			last;
		}
		sleep 1;
	}
	if ($found == 0) {
		print "Error, cannot find log to analyse.\n";
		exit -1;
	}
	if ($debug > 0) {
		print "$cmd\n";
	}
	if ($debug == 2) {
		return;
	}
	if ($debug == 3) {
		print;
	}
	print "Stage ".@_[0].".\n";
	while (1) {
		$_ = `tail -n 1 $ffmpeglog`;
		if (/^video/) {
			last;
		}
		my @row = split (/frame=/);
		my @info = split (/fps=/,@row[$#row]);
		$complete = (int((@info[0]/@_[1])*100));
		if ($complete != $prev) {
			$prev = $complete;
			print "Stage ".@_[0].": ".$complete."%\n";
		}
		sleep $poll;
	}
}
 
#$hori = 1024;
#$hori = 720;
$hori = 480;
$vert = int(($hori/$disaspect)+0.5);
if ($profile == 1) { 
	$bitrate = 592;
#	$bitrate = 296;
	$hori = 480;
	$vert = 272;
} elsif ($profile == 2) {
	$bitrate = 1184;
#	$bitrate = 592;
	$hori = 720;
	$vert = 480;
}
%titles = ();
 
if (@ARGV[0] eq "") {
	$dev = "/dev/cdrom";
} else {
	$dev = @ARGV[0];
}
my $maxlen = 0;
if (!($dev =~ /\.avi$|\.mpg$|\.mp4$|\.mov$/i)) {
# now extract info about this dvd with a cropdetect call
	$cmd = "mplayer -identify -monitoraspect $disaspect -zoom -vf cropdetect -frames 1 -ss 0:07:00 -vo aa -ao null -dvd-device \"$dev\" dvd://1";
	if ($debug > 0) {
		print "$cmd\n";
	}
	$detect =  `sh -c \"$cmd\" 2>&1`;
 
	my %titles = ();
	my $crop = "";
	my $aspect_internal = 0;
	my $aspect_viewing = 0;
	my $fps = 0;
	@detectdata = split(/\n/,$detect);
	foreach (@detectdata) {
		if (/^ID_DVD_TITLE/) {
			my @row = split(/\=/,$_);
			if (/^ID_DVD_TITLES/) {
				$numtitles = @row[1];
			} else {
				$titles{@row[0]} = @row[1];
			}
		}
	}
# extract title lengths
	my $longest = 1;
	for ($i=1;$i<=$numtitles;$i++) {
		my $len = $titles{"ID_DVD_TITLE_".$i."_LENGTH"};
		if ($len > $maxlen) {
			$maxlen = $len;
			$longest = $i;
		}
	}
	$dev = "-dvd-device \"$dev\" dvd://$longest";
	$cmd = "mplayer -identify -monitoraspect $disaspect -zoom -vf cropdetect -frames 40 -ss 0:05:00 -vo aa -ao null $dev";
} else {
	$fileflag = 1;
	my @row = split (/\./,$dev);
	if (@row[1] ne "mp4") {
		$output = "\"".@row[0].".mp4\"";
	}
	$dev = "\"$dev\"";
	if ($dev eq $output) {
		$output =~ s/\.mp4/_PSP\.mp4/;
	}
	$cmd = "mplayer -identify -monitoraspect $disaspect -zoom -vf cropdetect -frames 40 -ss 0:05:30 -vo aa -ao null $dev";
}
 
if ($debug > 0) {
	print "$cmd\n";
}
$detect =  `sh -c \"$cmd\" 2>&1`;
 
@detectdata = split(/\n/,$detect);
foreach (@detectdata) {
	if (/CROP/) {
		my @rowa = split(/\-vf\ crop\=/);
		my @rowb = split(/\)/,@rowa[1]);
		$crop = @rowb[0];
	}
	if (/^VO:/) {
		my @rowa = split(/\s+/,$_);
		my @rowb = split(/x/,@rowa[2]);
		if (@rowb[1] > 0) {
			$aspect_internal = @rowb[0]/@rowb[1];
		}
	}
	if (/^ID_VIDEO_ASPECT/) {
		my @row = split(/\=/,$_);
		$aspect_viewing = @row[1];
	}
	if (/^ID_VIDEO_FPS/) {
		my @row = split(/\=/,$_);
		$fps = @row[1]*1;
	}
	if (/^number\ of\ subtitles/) {
		my @row = split(/\s+/,$_);
		$subs = @row[$#row];
		if (($subs > 0)&&($slang ne "")) {
			$subexp = "0:0";
		}
	}
}
my $frames = int($maxlen*$fps);
 
if ($aspect_internal == 0) {
	print "could not determine the aspects for this DVD,\n";
	exit -1;
}
my @row = split (/\:/,$crop);
my $aspect_crop = (@row[0]/@row[1]);
my $aspect_original = ($aspect_crop*$aspect_viewing)/$aspect_internal;
$subpos = int(105-230*((1.96-$disaspect)*(1.01-((1+((1.78-$disaspect)/1.6))*($disaspect/$aspect_original))))); # this is a magic equation I just made up to help position subtitles
if ($debug > 0 ){
	print "ao: $aspect_original\n";
}
if ($subpos < 81) {
	$subpos = 81;
}
if ($subpos > 99) {
	$subpos = 99;
}
 
my $mencode = "";
if ($fps == 25) {
	$mencode = "mencoder -sws 9 -vf $gamma -noautoexpand -oac pcm -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=7800:keyint=250:threads=2 $slang $alang -af volnorm=1:.19 -sub-bg-alpha 255 -spualign 2 -spuaa 4 -spugauss 1.0 -ffactor 10 -o test.avi";
} else {
	$mencode = "mencoder -sws 9 $slang $alang -af volnorm=2:.19,channels=2 -ofps 24000/1001 -vf $gamma$noise -oac faac -faacopts br=192:mpeg=4:object=2:raw -ovc x264 -x264encopts bitrate=$bitrate:global_header:partitions=all:trellis=1:vbv_maxrate=".int(($bitrate*1.2973)+.5).":vbv_bufsize=2000:level_idc=30:threads=auto -of lavf -lavfopts $bframe"."format=psp -sub-bg-alpha 255 -spualign 2 -spuaa 4 -spugauss 0.2 -ffactor 10 -o $output";
}
$len = $maxlen;
if ($debug > 0) {
	$len = 60;
	$mencodelen = " -ss 00:25:00 -endpos $len";
} else {
	$mencodelen = " -endpos $len";
}
$frames = int($fps*$len);
my $finlen = " -endpos $len";
if ($fps == 25) {
	$finlen = " -endpos ".((($len*25000)/23976));
}
if ($fileflag > 0) {
	$finlen = "";
	$frames = 1;
} else {
	$mencode .= $mencodelen;
}
 
my $pull = "";
my $cropfilt = "";
if ($fps == 25) {
	if ($aspect_original > $disaspect) {
		$scalex = $rfsw;
		$scaley = int(($rfsw/$disaspect)+.5);
		$cropfilt = "-vf-add scale=$scalex:".(int((($scalex/$aspect_original)+.5)/2)*2).",expand=$scalex:$scaley:$subexp:$embed";
 
	} else {
		$scalex = int(($rfsh/$disaspect)+.5);
		$scaley = $rfsh;
		$cropfilt = "-vf-add scale=".(int(($scaley*$aspect_original)+.5)).":$scaley,expand=$scalex:$scaley:$subexp:$embed";
	}
} else {
	if ($aspect_original > $disaspect) {
#		$cropfilt = "-vf-add scale=$hori:-2,expand=$hori"."::$subexp:$embed:$disaspect,expand=$hori:$vert";
		$cropfilt = "-vf-add scale=$hori:-2,expand=$hori:$vert:$subexp:$embed";
	} else {
#		$cropfilt = "-vf-add scale=-2:$vert,expand=:$vert:$subexp:$embed:$disaspect,expand=$hori:$vert";
		$cropfilt = "-vf-add scale=-2:$vert,expand=$hori:$vert:$subexp:$embed";
	}
}
 
if ($fps == 29.97) {
	$pull = "-vf-pre filmdint";
}
#if ($aspect_original > $disaspect) {
#	$cropfilt = "-vf-add scale=$hori:-2,expand=$hori:$vert:$subexp:$embed";
#}
 
$cmd = "$mencode -subpos $subpos $cropfilt -vf-pre crop=$crop -vf-pre harddup $pull $dev -msglevel all=9";
execdebug "rm -f test.avi";
execmencode (1,$frames,$cmd);
if ($fps == 25) {
	execdebug "rm -f track.wav";
	execdebug "mplayer -vc null -vo null -ao pcm:fast:file=track.wav test.avi";
	execdebug "rm -f track.raw";
	execdebug "sox track.wav -r 50050 track.raw resample -qs";
	execdebug "rm -f track.wav";
	execdebug "sox -r 48000 -s -w -c 2 track.raw track.wav";
	execdebug "rm -f track.raw";
	execdebug "rm -f $output";
	execdebug "rm -f $ffmpeglog";
#	system "ffmpeg -i test.avi -vcodec rawvideo -pix_fmt yuv420p -f rawvideo - | mencoder -sws 9 -af volnorm=2:.19 -vf harddup,$tvaspect=$scalex:$scaley -aspect $disaspect -oac faac -faacopts br=192:mpeg=4:object=2:raw -ovc x264 -x264encopts bitrate=$bitrate:global_header:partitions=all:trellis=1:vbv_maxrate=".int(($bitrate*1.2973)+.5).":vbv_bufsize=2000:level_idc=30:threads=auto -of lavf -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames:format=psp $limit -o $output -audiofile track.wav -demuxer rawvideo -rawvideo fps=23.976:i420:w=$hori:h=$vert -";
	sleep 1;
	my $out = " > /dev/null";
	if ($debug > 0) {
		$out = " > stage2.log";
	}
	execffmpeg (2,$frames,"ffmpeg -i test.avi -v 9 -vcodec rawvideo -pix_fmt yuv420p -f rawvideo - | mencoder -sws 9 -af volnorm=2:.19 -vf harddup$noise,$tvaspect=$hori:$vert -aspect $disaspect -oac faac -faacopts br=192:mpeg=4:object=2:raw -ovc x264 -x264encopts bitrate=$bitrate:global_header:partitions=all:trellis=1:vbv_maxrate=".int(($bitrate*1.2973)+.5).":vbv_bufsize=2000:level_idc=30:threads=auto -of lavf -lavfopts $bframe"."format=psp$finlen $limit -o $output -audiofile track.wav -demuxer rawvideo -rawvideo fps=23.976:i420:w=$scalex:h=$scaley -$out 2>&1");
	if ($debug == 0) {
		execdebug "rm -f track.wav";
		execdebug "rm -f test.avi";
	}
	execdebug "rm -f $ffmpeglog";
}
 
waitpid($pid,0);
print "complete!\n";

Folk Songs

I just love this album. There is something very special about it, in the right mood, it is able to transform me well – it is very delicate. I would recommend it to be taken with no distractions and then relax into it – preferably nice headphones. There is a moment in the 3rd. track "Bodas De Prata" where the music hits an amazing chord progression by Egberto Gismonti and Jan Garbarek takes off melodically with Charlie Haden underpinning the ride brilliantly. Following it closely will lift you off the ground. I find this is definitely a mood album, if you catch yourself in the wrong mood, it may bore you. Jan has a distinctive playing style that some find abbrasive. I find him magical and teamed with these musicians, it is a kind of melancholy that puts me back in touch with the natural world. When I’m down, this music can make me appreciate being alive.

Teclast T39

This is the 2nd. Teclast device I own. I have had the T39 for nearly a year I think, prior to that I had a Teclast C260 which ended up bricked for some time – after buying the T39, I actually managed to fix the C260 by following some un-bricking guidelines from the interweb.

The T39 has been the best MP3 player I’ve ever owned and also a great MP4 player as well. I started with MP3 back at the turn of the millenium [Read more →]

Hejira

Hejira is one of my favourite albums. It is quite a delicate creation, but delivered with such confidence by Joni. Of course working with Jaco gave it an extra confident edge. I find it to be the album I turn to for emotional stability. Its an album created through travel, so it came with me to China.

I listened to it and Weather Report’s "Black Market" for much of 2nd. and 3rd. trips to China. This time for me was very special, experiencing living in Beijing and travelling to The Great Wall, Tianjin, The Summer Palace, then Qingdao by train and Laoshan on the 3rd trip. This music definitely provided an appropriate backdrop for such an amazing experience. I deliberately over-listened to it so that now when I listen to it, it sends me back to that time. Both occasions were in Autumn, which is a great time to be in China.

Its definitely my favourite Joni Mitchell album – but I must admit I know only a few. Of course, along with Weather Report’s "Black Market" – the first recording they made with Jaco Pastorious, they travel together well in my portable player.

The Juliet Letters

I just watched a rather corny but humbling film called The Family Man – with Nicholas Cage made around 2000. At the end was some Elvis Costello music. I’ve always respected Elvis and some of his music is quite special for me. I missed a lot of his early stuff, just simply being too young to get into it at the time.

I bought Spike when I was about 15, loved it a lot. It seemed to have a broad range of Elvis’s style from snappy pop to hard edge rock to delicate ballads. I think for me, at 15, this was a breath of fresh air for me away from the pop charts. Since then, I’ve always kept my ears open whenever I hear his distinct and mature voice.

Now, I am listening to The Juliet Letters again, which I haven’t heard for maybe 15 years. I remember seeing something on TV about it, the songs are letters, diverse and expressive, they have been made into song with accompaniment by The Brodsky Quartet

Floating Point

John McLaughlin’s latest fusion is a true gem. I loved his previous album "Industrial Zen", but I have a slight issue with the sound. These days John likes to use a lot of midi gear and though I’m sure that makes his music development process a lot easier, I feel it loses a little in the freshness of the sound. His guitar technique loses something in the midi transforms, luckily for McLaughlin, his genius lies in his choice of notes – just like Coltrane. These days, he can still maintain the subtle bends and blue tails he carefully places in the music, but that freshness of an acoustic resonance is lost.

With his latest, I feel he has made another step in fusion, successfully merging his comfortable midi development environment with some great acoustic musicians – its clear in this work how working with the sliding instrument, Bansuri and some kind of Veena – possibly a Mohan Veena, has elevated the music with a fresh feel – and the percussion! its lovely to hear such fresh trebbles and Indian knocks throughout.

I think maybe Industrial Zen had more interesting compositions, but lacked the presence this album has – sounds like John has a new target for his passion for fusion.

What a brilliant musician, still managing to find new paths in this era of his life shows how his determination has prevented any staleness from creeping in.

My wife’s blog

My wife Mingzhen is an old hand at blogging. Mingzhen’s Blog, I have a long way to go to catch up.