#!/usr/bin/perl

# (c) G. Finch (salsaman)

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

#######################################################################
# LiVES mencoder plugin v1.10

# 1.7 add kvcd back in
# 1.8 use mjpeg with -ovc copy (thanks to Rich Felker for the suggestion)
# 1.9 add ffv1 and png support (thanks to anonymous) 
# 1.91 add ffv1 image formats
# 1.93 get audio codec for encoding

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

if (!defined($standalone)) {
    my $smogrify;
    if ($^O eq "MSWin32") {
	$smogrify="smogrify";
    }
    else {
	$smogrify=`which smogrify`;
	chomp($smogrify);
    }
    if ($smogrify ne "") {
	require $smogrify;
    }
}
else {
    $command=$ARGV[0];
}


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


if ($command eq "version") {
    print "mencoder encoder plugin v1.93\n";
    exit 0;
}


if ($command eq "init") {
    # perform any initialisation needed
    # On error, print error message and exit 1
    # otherwise exit 0

    if (&location("mencoder") eq "") {
	print "Mencoder was not found. Please install it and try again.";
	exit 1;
    }
    
    # end init code
    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|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, 128 - raw, 256 = wma2

   print "flv|flv|1|arate=44100;22050;11025|flv|\n";
   print "wmv2|wmv2/wma2/asf|256|arate=44100;22050;11025|wmv|\n";
   print "mjpeg|mjpg|2|none|avi|\n";
   print "ffv1|ffv1 (lossless)|2|none|avi|\n";
   print "kvcd|kvcd (experimental)|4|arate=32000;44100;48000,fps=24;25;30,aspect=352:240,hblock=16,vblock=16|mpg|\n";
   
   exit 0;
}

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

    if ($otype eq "flv") {
	$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 "</params>\n";

	}
    }
}



if ($command eq "encode") {
    # encode 
    
    $usemp3=$ARGV[13];
    $usemp3lame=$ARGV[14];

    $encoder_command="mencoder";

    # remove ":"'s from comments, mencoder doesn't like them even in quotes
    $title=~ s/:/ /g;
    $author=~ s/:/ /g;
    $comment=~ s/:/ /g;

    # mencoder doesn't like empty strings either
    if ($title eq "") {
	$title=" ";
    }
    if ($author eq "") {
	$author=" ";
    }
    if ($comment eq "") {
	$comment=" ";
    }

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

    # get audio codec
    $aq=&rc_get("encoder_acodec");

    # set the codec
    $vcodec="mjpeg";
    
    if ($otype eq "mpeg4" || $otype eq "mpeg2video" || $otype eq "ffv1" || $otype eq "flv" || $otype eq "wmv2") {
	$vcodec=$otype;
    }

    if ($otype eq "mpg1") {
	$vcodec="mpeg1video";
    }
    
    if ($otype eq "ffv1") {
	if ($img_ext eq ".png") {
	    $format=":format=BGR32";
	}
	else {
	    #jpeg
	    $format=":format=422P";
	}
    }
    else {
	$format="";
    }

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

    # TODO - recheck this
    $zeroframe=&mkname(0);
    `cp 00000001$img_ext $zeroframe$img_ext $err`;



    #prepare video stream

    if ($mf_ver==1) {
	if ($img_ext eq ".png") {
	    $syscom="$encoder_command  -mf on -mf type=png -vc mpng -o \"$tmpvid\" -ovc lavc -lavcopts vcodec=$vcodec:vhq$format -noskip -ofps $fps \\*$img_ext -frames " . ($end-$start+2) . " $err";
	}
	else {
	    $syscom="$encoder_command  -mf on -mf h=$vsize:w=$hsize:type=jpg -o \"$tmpvid\" -ovc lavc -lavcopts vcodec=$vcodec:vhq$format -noskip -ofps $fps \\*$img_ext -frames " . ($end-$start+2) . " $err";
	}
    }
    else {
	if ($img_ext eq ".png") {
	    $syscom=$encoder_command . " -mf fps=$fps:type=png -vc mpng -o \"" . $tmpvid . "\" -ovc lavc -lavcopts vcodec=$vcodec:vhq$format -noskip mf://*" . $img_ext . " -frames " . ($end-$start+2) . " $err";
	}
	else {
	    $syscom=$encoder_command . " -mf h=$vsize:w=$hsize:type=jpg -o \"" . $tmpvid . "\" -ovc lavc -lavcopts vcodec=$vcodec:vhq$format -noskip -ofps " . $fps . " mf://*" . $img_ext . " -frames " . ($end-$start+2) . " $err";
	}
    }
    if (defined($DEBUG_ENCODERS)) {
	print STDERR "Debug: mencoder command 1 is: $syscom\n";
    }
    system($syscom);

    #audio
    $audio_com="";
    unless ($audiofile eq "") {
	if ($aq==0) {
	    if ($usemp3lame) {
		$audio_com.="-audiofile ".$audiofile." -oac lavc -lavcopts acodec=libmp3lame";
	    }
	    else {
		$audio_com.="-audiofile ".$audiofile." -oac lavc -lavcopts acodec=mp3";
	    }
	}
	elsif ($aq==1) {
	    $audio_com="-audiofile ".$audiofile." -oac copy";
	}
	elsif ($aq==2) {
	    $audio_com="-audiofile ".$audiofile." -oac lavc -lavcopts acodec=mp2";
	}
	elsif ($aq==8) {
	    $audio_com="-audiofile ".$audiofile." -oac lavc -lavcopts acodec=wmav2";
	}
    }

    # muxing
    if ($otype eq "flv") {
	$lavfopts="-of lavf -lavfopts format=flv";
    }
    if ($otype eq "wmv2") {
	$lavfopts="-of lavf -lavfopts format=asf";
    }

    if ($otype eq "mjpeg" || $otype eq "ffv1" || $otype eq "flv" || $otype eq "wmv2") {
	$syscom=$encoder_command . " -mc 0 -o \"$nfile\" -ovc copy -noskip -ofps $fps $tmpvid $audio_com $lavfopts -info comment=\"$comment\":name=\"$title\":artist=\"$author\" $err";
    }
    elsif ($otype eq "kvcd") {
	$abitrate=112;
	$matrix="8,9,12,22,26,27,29,34,9,10,14,26,27,29,34,37,12,14,18,27,29,34,37,38,22,26,27,31,36,37,38,40,26,27,29,36,39,38,40,48,27,29,34,37,38,40,48,58,29,34,37,38,40,48,58,69,34,37,38,40,48,58,69,79";
	$inter_matrix="16,18,20,22,24,26,28,30,18,20,22,24,26,28,30,32,20,22,24,26,28,30,32,34,22,24,26,30,32,32,34,36,24,26,28,32,34,34,36,38,26,28,30,32,34,36,38,40,28,30,32,34,36,38,42,42,30,32,34,36,38,40,42,44";
	$scale="scale=352:240";

	$syscom="$encoder_command $tmpvid -mc 0 -of mpeg -ovc lavc $audio_com:abitrate=$abitrate:vcodec=mpeg1video:keyint=".int($fps).":mbd=1:vrc_minrate=64:vrc_maxrate=3000:vrc_buf_size=320:aspect=4/3:intra_matrix=$matrix:inter_matrix=$inter_matrix -vf $scale -o \"$nfile\"";

    }
    if (defined($DEBUG_ENCODERS)) {
	print STDERR "Debug: mencoder command 2 is: $syscom\n";
    }
    system($syscom);

    # required
    &sig_complete;
    exit 0;
}


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

    $tmpvid="tmpvid";
    if (-f $tmpvid) {
	unlink $tmpvid;
    }
    &sig_complete;
    exit 0;
}


if ($command eq "finalise") {
    # do any finalising code

    # ...

    # end finalising code
    print "finalised\n";
    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, clipped frames
}

