#!/usr/bin/perl
#   $Id: motion,v 1.4 2013/07/15 03:16:35 az Exp $
# 
#   File:		motion
#   Date:		09 Jul 2013 13:37:02
#   Author:		Alexander Zangerl <az@snafu.priv.at>
# 
#   Abstract:
#	reactive component for foscam ip cam
#	when the foscam detects motion it visits the script's url, 
#	which triggers a download of the next minute or so of video
#
use strict;
use LWP::UserAgent;
use POSIX qw(strftime);
use CGI::Simple;
use Proc::PID::File;
use File::Temp qw(tempdir);
use MIME::Parser;

my $source='http://YOURCAM/videostream.cgi?user=USER&pwd=PWD';
my $destdir="/stuff/motion";
my $destfn="motion-%G%m%d-%H%M.avi";
my $caplen=120;

my $q=CGI::Simple->new;
(!-d $destdir) && mkdir ($destdir,0755);

my ($tempdir);
$tempdir=tempdir("/tmp/motion.XXXXXXXXXX");
my $parser=MIME::Parser->new;
$parser->output_dir($tempdir);
my $bodyfile="$tempdir/body";
my $headerfile="$tempdir/header";

# don't use a proxy for this
my $ua=LWP::UserAgent->new(env_proxy=>0);
my $starttime=time;

$SIG{CHLD}='IGNORE';
if (my $kid=fork())
{
    # parent: we're done
    print $q->header(-status=>204);
}
else
{
    # child: do the work
    close STDOUT;
    close STDIN;
    close STDERR;
    if (!Proc::PID::File->running(dir=>$destdir,name=>"motion"))
    {
	# prep bodyfile, limitedwrite will fill it up
	open(F,">$bodyfile") or die "can't open $bodyfile: $!\n";
	my $request=$ua->get($source,":content_cb"=>\&limitedwrite);
	close(F);
	open(F,">$headerfile") or die "can't open $headerfile: $!\n";
	print F $request->headers->as_string."\n"; # no extra blank line!
	close(F);

	# parse and split into lotsa jpegs
	my $entity=$parser->parse_two($headerfile,$bodyfile);
	# ...whose names are numeric but not zero-padded (but avconv copes)
	my $fpattern=$entity->parts(0)->bodyhandle()->path;
	# if you give it a '%d' in the input filename pattern
	$fpattern=~s/-\d+.jpg$/-%d.jpg/;

	# figure out the average frames/second
	opendir(D,$tempdir);
	my $fps=grep(/\.jpg$/,readdir(D));
	closedir(D);
	$fps/=$caplen;

	system("avconv","-v","quiet","-r",$fps,"-i",$fpattern,"-c:v","libx264",
	       strftime("$destdir/$destfn",localtime));
    }
    system("rm","-rf",$tempdir);
}

exit 0;

sub limitedwrite
{
    my ($data,$response,$proto)=@_;

    die("enough.") if (time>=$starttime+$caplen);
    print F $data;
}





