#!/usr/bin/perl

use Video::Capture::V4l;
use Video::RTjpeg;

$|=1;
$SIG{PIPE} = 'IGNORE';

$stream = "/tmp/vstream";
require $stream;

$mpegencode = "/root/cvt/mpeg_movie-1.6.0/video_in/mpeg_encode";

my $gop = 8;

$tmpdir = "/tmp/encode$$/";
$tmpdir = "/tmp/encode";
mkdir $tmpdir, 0700;

$fsize  = $w*$h*2;

$partlen = $fps*60;
$partlen = $gop*100;

my @dec;

sub new_vdecoder {
   my $number = @dec;
   my $decp = do { local *DECODER_READER };
   my $decc = do { local *DECODER_WRITER };
   pipe $decp, $decc;
   if (fork==0) {
      my ($buf, $tables);
      open DATA, "<$outprefix.v$number" or die;

      read DATA, $buf, 4;
      my ($tlen) = unpack "N*", $buf;

      read DATA, $tables, $tlen;
      Video::RTjpeg::init_decompress($tables, $w, $h);

      while (read DATA, $buf, 8) {
         my ($time, $size) = unpack "N*", $buf;
         print $decc pack "N", $time;
         read DATA, $buf, $size;
         print $decc Video::RTjpeg::decompress $buf;
      }
      exit;
   }
   push @dec, $decp;
}

my @nframeid;

sub next_frame {
   my $min = 1e30;
   my $buf;
   my $minid;
   for (0..$#dec) {
      unless (defined $nframeid[$_]) {
         read $dec[$_], $buf, 4;
         $nframeid[$_] = unpack "N", $buf;
      }
      ($min,$minid) = ($nframeid[$_],$_) if $nframeid[$_] < $min && defined $nframeid[$_];
   }
   read $dec[$minid], $buf, $fsize;
   undef $nframeid[$minid];
   ($buf, $min);
}

new_vdecoder for 1..$vencoders;

my $part = 0;

sub do_encode {
   my ($pstart, $pframes) = @_;
   $pframes = sprintf "%06d", $pframes-1;
   $part = sprintf "%03d",  $part+1;

   open TEMPLATE, ">$tmpdir/param" or die;
   print TEMPLATE <<EOF;
OUTPUT		$outprefix.$part.mpg

#PATTERN		IBBBPBBB
PATTERN		IBBBPBBBPBBBPBBBPBBBPBBBPBBBPBBB
FORCE_ENCODE_LAST_FRAME

# You must specify the type of the input files.  The choices are:
#    YUV, PPM, JMOVIE, Y, JPEG, PNM
#
BASE_FILE_FORMAT	YUV

# this option is ignored if BASE_FILE_FORMAT is not YUV and you're running
YUV_SIZE	${w}x$h

# EYUV or UCB are the same as previous versions of this encoder.
# (All the Y's, then U's then V's, in 4:2:0 subsampling.)
# Other formats, such as Abekas, Phillips, or a general format are
# permissible, the general format is a string of Y's, U's, and V's
# to specify the file order.

INPUT_FORMAT EYUV

INPUT_CONVERT	*

# number of frames in a GOP.
#
# since each GOP must have at least one I-frame, the encoder will find the
# the first I-frame after GOP_SIZE frames to start the next GOP
#
# later, will add more flexible GOP signalling
#
GOP_SIZE	$partlen

# number of slices in a frame
#
# 1 is a good number.  another possibility is the number of macroblock rows
# (which is the height divided by 16)
#
SLICES_PER_FRAME	$w

# directory to get all input files from (makes this file easier to read)
INPUT_DIR	$tmpdir

# There are a bunch of ways to specify the input files.
# from a simple one-per-line listing, to the following 
# way of numbering them.  See the manual for more information.
INPUT
# '*' is replaced by the numbers 01, 02, 03, 04
# if I instead do [01-11], it would be 01, 02, ..., 09, 10, 11
# if I instead do [1-11], it would be 1, 2, 3, ..., 9, 10, 11
# if I instead do [1-11+3], it would be 1, 4, 7, 10
# the program assumes none of your input files has a name ending in ']'
# if you do, too bad!!!
#
#
frame*.yuv	[000000-$pframes]
END_INPUT

# Many of the remaining options have to do with the motion search and qscale

# FULL or HALF -- must be upper case
PIXEL		HALF

# means +/- this many pixels for both P and B frame searches
# specify two numbers if you wish to serc different ranges in the two.
RANGE		10

# this must be one of {EXHAUSTIVE, SUBSAMPLE, LOGARITHMIC}
PSEARCH_ALG	LOGARITHMIC

# this must be one of {SIMPLE, CROSS2, EXHAUSTIVE}
#
# note that EXHAUSTIVE is really, really, really slow
#
BSEARCH_ALG	CROSS2

#
# these specify the q-scale for I, P, and B frames
# (values must be between 1 and 31)
# These are the Qscale values for the entire frame in variable bit-rate
# mode, and starting points (but not important) for constant bit rate
#
IQSCALE		8
PQSCALE		10
BQSCALE		25

# this must be ORIGINAL or DECODED
REFERENCE_FRAME	DECODED

# for parallel parameters see parallel.param in the exmaples subdirectory

# if you want constant bit-rate mode, specify it as follows (number is bits/sec):
#BIT_RATE  2000000

# To specify the buffer size (327680 is default, measused in bits, for 16bit words)
#BUFFER_SIZE 800000

# The frame rate is the number of frames/second (legal values:
# 23.976, 24, 25, 29.97, 30, 50 ,59.94, 60
FRAME_RATE $fps

# There are many more options, see the users manual for examples....
# ASPECT_RATIO, USER_DATA, GAMMA, IQTABLE, etc.

#PARALLEL_TEST_FRAMES	3
#PARALLEL_CHUNK_TAPER

#PARALLEL
#localhost1	root	$mpegencode
#localhost2	root	$mpegencode
#END_PARALLEL

EOF

   close TEMPLATE;

   $ENV{HOST} = "localhost";
   system $mpegencode, "-quiet", "10", "$tmpdir/param";
}

my ($frame, $pstart, $pframe) = (0, 0, 0);

Video::RTjpeg::init_decompress("x" x (128*4), $w, $h);
while (my ($buf, $framex) = next_frame) {
   print ".";
   while ($frame < $framex) {
      if ($pframe == $partlen) {
         do_encode $pstart, $pframe;
         $pstart = $frame;
         $pframe = 0;
      }
      #$buf2 = Video::RTjpeg::yuvrgb($buf); open DISPLAY, "| display -size ${w}x$h rgb:-" or die; print DISPLAY $buf2; close DISPLAY;
      open FRAME, sprintf ">$tmpdir/frame%06d.yuv", $pframe;
      print FRAME $buf;
      close FRAME;
      $frame++;
      $pframe++;
      print "s" if $frame != $framex;
   }
   last if $frame >= $nframe;
}

do_encode $pstart, $pframe;