#!/usr/bin/perl

# June 3, 2005 - mvr2mpg initial version 1.0
#
# Copyright © 2005 Thomas A. Fine
# License is herby granted to distribute and use freely, for commercial and
# non-commercial reasons, in whole or in part, provided that this copyright
# notice and license are maintained.
#
# Required programs: pnmcat, pnmhisteq, ffmpeg
# provide full paths, if needed:

$PNMCAT="pnmcat";
$PNMHISTEQ="pnmhisteq";
$FFMPEG="ffmpeg";

$outfile="out.mpg";

$fix_contrast=0;
if ($#ARGV >= 0) {
  if ($ARGV[0] eq "-c") {
    shift(@ARGV);
    $fix_contrast=1;
  }
}

if ($#ARGV == -1) {
  &usage;
}

$infile=shift(@ARGV);

if ($#ARGV == 0) {
  $outfile=shift(@ARGV);
  if ($outfile !~ /.mpg$/i) {
    $outfile .= ".mpg";
  }
} elsif ($#ARGV > 0) {
  &usage;
}

open(IN,$infile);

read(IN,$buf,1);  $version=ord($buf);
read(IN,$buf,1);  $width=ord($buf);
read(IN,$buf,1);  $height=ord($buf);
read(IN,$buf,1);  $depth=ord($buf);
read(IN,$buf,2);  $framecount=unpack("n",$buf);
read(IN,$buf,1);  $compress=ord($buf);
read(IN,$buf,1);  $eat=ord($buf);
read(IN,$buf,4);  $id=unpack("N",$buf);
read(IN,$buf,30); $description=$buf;
read(IN,$buf,2);  $audiorate=unpack("n",$buf);
read(IN,$buf,1);  $framerate=ord($buf);
read(IN,$buf,1);  $eat=ord($buf);

print "version=$version\n";
print "width=$width\n";
print "height=$height\n";
print "depth=$depth\n";
print "framecount=$framecount\n";
print "compress=$compress\n";
print "id=$id\n";
print "audiorate=$audiorate\n";
print "framerate=$framerate\n";
print "description=$description\n";

open(AUD,">/tmp/mvraud.out") || die "Can't open audio out!\n";

for ($i=0; $i<$framecount; ++$i) {
  read(IN,$buf,2);  $bitmapsize=unpack("n",$buf);
  last if (eof(IN));
  print "reading $bitmapsize bitmap\n";
  if (($nr=read(IN,$buf,$bitmapsize)) != $bitmapsize) {
    print "$nr != $bitmapsize\n";
    exit(1);
  }
  $frame=sprintf("/tmp/mvr.%d.ppm",$i);

  if ($fix_contrast) {
    open(PPM,"|$PNMHISTEQ >$frame") || die "Can't open frame $i out\n";
  } else {
    # pnmcat is used to convert the ascii PPM that I produce into raw
    # PPM required by ffmpeg
    open(PPM,"|$PNMCAT -lr >$frame") || die "Can't open frame $i out\n";
  }
  print PPM "P3\n$width $height\n255\n";
  for ($j=0; $j<$bitmapsize; $j+=2) {
    $x1=ord(substr($buf,$j,1));
    $x2=ord(substr($buf,$j+1,1));
    $r=$x1>>3;
    $b=$x2 & 0x1f;
    $g=(($x1&0x07)<<2) | ($x2>>6);
    $r *= 4; $g *= 4; $b *= 4;
    print PPM "$r $g $b ";
  }
  print PPM "\n";
  close(PPM);

  read(IN,$buf,2);  $audiosize=unpack("n",$buf);
  last if (eof(IN));
  print "reading $audiosize audio\n";
  if (($nr=read(IN,$buf,$audiosize)) != $audiosize) {
    print "$nr != $audiosize\n";
    exit(1);
  }
  print AUD $buf;
}
close(AUD);
print "$i frames read\n";

if (!eof(IN)) {
  print "error! Not EOF!\n";
}

#the data header from movierec output says 32000 samples per second and
#15 frames per second.  That doesn't quite jibe - if it's 15 frames per
#second then I'm only acutally seeing 30720 samples per second.
#But it's so close, and the moveis so short, I'll ignore that for now.

system("$FFMPEG -ar 32000 -f s16be -i /tmp/mvraud.out -r 15 -i /tmp/mvr.%d.ppm -r 30 $outfile");

for ($i=0; $i<$framecount; ++$i) {
  $frame=sprintf("/tmp/mvr.%d.ppm",$i);
  unlink($frame);
}
unlink("/tmp/mvraud.out");

#
# END OF MAIN
#

sub usage {
  print "usage: $0 [-c] mvr_file [outfile]\n";
  print "       -c automatically adjusts contrast for each frame\n";
  print "       \".mpg\" will be appended to outfile, if not included\n";
  print "       If outfile is not given, \"out.mpg\" is used.\n";
  exit(0);
}
