#!/usr/bin/perl

# (c) G. Finch (salsaman) 2009 - 2010

# released under the GNU GPL 3 or later
# see file COPYING or www.gnu.org for details


#######################################################################
# LiVES ffmpeg plugin v2.6
# v 2.1 - add experimental 3gp support
# v 2.2 - format changed in ffmpeg from image to image2, update
# v 2.3 add youtube and flv formats
# v 2.4 allow encoding of .png images
# v 2.5 add threading support and experimental webm encoding
# v 2.6 made threading support optional because of instability problems; versioning string changed in ffmpeg

#######################################################################

if (!defined($standalone)) {
    my $smogrify=`which smogrify`;
    chomp($smogrify);
    require $smogrify;
}
else {
    $command=$ARGV[0];
}


if ($command eq "version") {
    print "ffmpeg encoder plugin v2.6\n";
    exit 0;
}


if ($command eq "init") {

    # perform any initialisation needed
    # On error, print error message and exit 1
    # otherwise exit 0
    
    if (&location("ffmpeg") eq "") {
        print "The ffmpeg binary was not found, please install it and try again !";
	exit 1;
    }

    ##############################
    print "initialised\n";
    exit 0;
}
    
    


if ($command eq "get_capabilities") {
    # return capabilities - this is a bitmap field
    # bit 0 - takes extra parameters (using RFX request)
    # bit 1 - unused
    # bit 2 - can encode png
    # bit 3 - not pure perl
    print "5\n";
    exit 0;
}


if ($command eq "get_formats") {
   # for each format: -
   # return format_name|display_name|audio_types|restrictions|default_extension|

   # audio types are: 0 - cannot encode audio, 1 - can encode using
   #  mp3, 2 - can encode using pcm, 3 - can encode using pcm and mp3
   # 4 - mp2, 8 - vorbis, 16 - AC3, 32 - AAC, 64 - AMR-NB

   # restrictions: 'fps=xx.yy' which
   # means "can only encode at xx.yy frames per second", size=x X y, arate=audio rate 
    # - otherwise set it to 'none'


    print "divx|divx (25 fps)|5|fps=25.00|avi|\n";
    print "asf|asf|5|none|asf|\n";
    print "3gp_h263|3gp (h263)|96|size=176x144,arate=8000|3gp|\n";
    print "3gp_mp4|3gp (mp4)|96|size=176x144,arate=8000|3gp|\n";
    print "flv|flv|9|arate=44100;22050;11025|flv|\n";
    print "flv-youtube|flv (425x318, optimised for youtube)|33|arate=44100;22050;11025,size=425x318|flv|\n";
    print "flv-youtubex|flv (other sizes, optimised for youtube)|33|arate=44100;22050;11025,aspect=1.3333:1|flv|\n";
    print "webm|webm (experimental)|8|none|webm|\n";
    exit 0;
}




if ($command eq "get_rfx") {
    # nice example of how to give the user a choice of options

    if ($otype eq "flv"||$otype eq "flv-youtube"||$otype eq "flv-youtubex"||$otype eq "divx"||$otype eq "asf") {
	$aq=&rc_get("encoder_acodec");
	if ($aq==0) {
	    # mandatory section
	    print "<define>\n";
	    print "|1.7\n";
	    print "</define>\n";
	    
	    # mandatory section
	    print "<language_code>\n";
	    print "0xF0\n";
	    print "</language_code>\n";
	    
	    # optional section
	    print "<params>\n";
	    print "mp3|Use _mp3 audio codec|bool|1|1\n";
	    print "mp3lame|Use mp3_lame audio codec|bool|0|1\n";
	    print "threads|Number of threads (>1 may cause instability)|num0|1|1|16|";
	    print "</params>\n";

	}
    }
}







if ($command eq "encode") {
    # encode
    $encoder_command="ffmpeg";

    $ffver=`ffmpeg 2>&1|grep libavformat | grep -v configuration`;

    $ffver=(split(/\./,$ffver))[0];

    $ffver=(split(" ",$ffver))[-1];

    $usemp3=$ARGV[13];
    $usemp3lame=$ARGV[14];
    $nthreads=$ARGV[15];

    $vid_length=($end-$start+1)/$fps;

    $err=">/dev/null 2>&1";
    if (defined($DEBUG_ENCODERS)) {
	$err="1>&2";
    }

    if ($otype eq "") {
	$otype="divx";
	&rc_set("output_type",$otype);
    }

    $ncpus=&get_num_procs;


    # default seems to be divx
    $vcodec="";
    if ($otype eq "asf") {
	$vcodec="-f asf";
    }
    elsif ($otype eq "3gp_h263") {
	$vcodec="-f h263";
    }
    elsif ($otype eq "3gp_mp4") {
	$vcodec="-f mp4";
    }
    elsif ($otype eq "flv"||$otype eq "flv-youtube"||$otype eq "flv-youtubex") {
	$vcodec="-f flv";
    }
    elsif ($otype eq "webm") {
	$vcodec="-f webm";
    }

    if ($otype eq "flv-youtube"||$otype eq "flv-youtubex") {
	$vcodec.=" -b 1024k -bt 256k -maxrate 1024k -minrate 1024k -bufsize 8192k";
    }

    # video stream
    $audio_com="";
    unless ($audiofile eq "") {
	$aq=&rc_get("encoder_acodec");
	$audio_com="-i $audiofile";
	if ($aq==1) {
	    #pcm
	    $audio_com.=" -acodec copy";
	}
	elsif ($aq==5) {
	    $audio_com.=" -acodec aac -strict experimental";
	}
	elsif ($aq==6) {
	    $audio_com.=" -acodec amr_nb";
	}
	elsif ($aq==0) {
	    if ($usemp3lame) {
		$audio_com.=" -acodec libmp3lame";
	    }
	    else {
		$audio_com.=" -acodec mp3";
	    }
	}
	elsif ($aq==3) {
	    $audio_com.=" -acodec vorbis";
	}
	else {
	    $audio_com.=" -acodec mp2";
	}

	if ($otype eq "flv-youtube"||$otype eq "flv-youtubex") {
	    $audio_com.=" -ab 128k -ar $arate";
	}
	elsif ($otype eq "flv") {
	    $audio_com.=" -ab 192k -ar $arate";
	}
	elsif ($otype eq "3gp_h263" || $otype eq "3gp_mp4") {
	    $audio_com.=" -ac 1 -ab 12 -ar 8000";
	}

    }
    
    # unfortunately this does not work yet...
    if ($otype eq "theora") {
	$syscom="ffmpeg2theora -o \"$nfile\" -f image2 -i %8d$img_ext $audio_com -d off $err";
    }
    elsif ($otype eq "3gp") {
	$passfile="passfile";
	for $pass (1,2) {
	    $syscom="$encoder_command -strict 1 -pass $pass -passfile $passfile -y -r $fps -f image2 -i %8d$img_ext $audio_com -r $fps -t $vid_length $vcodec \"$nfile\" $err";
		if (defined($DEBUG_ENCODERS)) {
		    print STDERR "ffmpeg_encoder command is: $syscom\n";
		}
		
		system ($syscom);
	}
    }
    else {
	if ($nthreads>1) {
	    $threads=" -threads $nthreads";
	}
	else {
	    $threads="";
	}

	if ($ffver>=52) {
	    $syscom="$encoder_command $threads -metadata comment=\"$comment\" -metadata author=\"$author\" -metadata title=\"$title\" -y -r $fps -f image2 -i %8d$img_ext $audio_com -r $fps -t $vid_length $vcodec \"$nfile\" $err";
	}
	else {
	    $syscom="$encoder_command $threads -comment \"$comment\" -author \"$author\" -title \"$title\" -y -r $fps -f image2 -i %8d$img_ext $audio_com -r $fps -t $vid_length $vcodec \"$nfile\" $err";
	}
    }

    if (defined($DEBUG_ENCODERS)) {
	print STDERR "ffmpeg_encoder command is: $syscom\n";
    }

    system ($syscom);

    &sig_complete;
    exit 0;
}



if ($command eq "clear") {
    # this is called after "encode"
    # note that encoding could have been stopped at any time
    chdir $curtmpdir;

    unlink "temp.vid";

    unlink "passfile";
    &sig_complete;
    exit 0;
}



if ($command eq "finalise") {
    # do any finalising code
    
    # end finalising code
    print "finalised\n";
    exit 0;
}

exit 0;



###### subroutines #######

sub get_format_request {
    # return the code for how we would like audio and video delivered
    # this is a bitmap field composed of:
    # bit 0 - unset=raw pcm audio; set=pcm audio with wav header
    # bit 1 - unset=all audio; set=clipped audio
    # bit 2 - unset=all frames; set=frames for selection only

    return 7; # clipped pcm wav, frames start at selection
}


sub get_num_procs {
    my $result=`cat /proc/cpuinfo|grep processor`;

    $result=(split (/\n/,$result))[-1];
    $result=(split (/: /,$result))[1];
    return ++$result;
}
