#!/usr/bin/perl

use Getopt::Long;
use IPC::Open3;
our $novideo = 0;
&Getopt::Long::Configure(qw(bundling));
&GetOptions("n" => \$novideo);
&main();

sub main
{
	foreach my $file (@ARGV) {
		&moov_one_file($file);
	}
}

sub moov_one_file
{
	my $input = shift @_;
	local(*CIN, *COUT);
	my $pid = open3(\*CIN, \*COUT, \*COUT,
		"ffmpeg", "-i", $input, "-acodec", "copy",
		$novideo ? ("-vn") : ("-vcodec", "copy"),
		"-moov_size", "4", "-y", ".moov.mp4");
	close CIN;

	my $moov_size = 4 + &moov_get_extra(\*COUT);
	waitpid($pid, 0);
	my $status = $? >> 8;
	close COUT;

	# Run with exact moov_size
	print "$input: moov_size=$moov_size\n";
	$pid = open3(\*CIN, \*COUT, \*COUT,
		"ffmpeg", "-i", $input, "-acodec", "copy",
		$novideo ? ("-vn") : ("-vcodec", "copy"),
		"-moov_size", $moov_size, "-y", ".moov.mp4");
	close CIN;
	while (defined(my $line = <COUT>)) {
	}
	close COUT;
	waitpid($pid, 0);
	my $status = $? >> 8;
	if ($status != 0) {
		print STDERR "$input: 2nd stage error\n";
		return;
	}

	# Set filetimes to original
	my @stat = stat($input);
	if (!utime($stat[8], $stat[9], ".moov.mp4")) {
		print STDERR "$input: could not set utimes on temporary file: $!\n";
		return;
	}
	if (!rename(".moov.mp4", $input)) {
		print STDERR "$input: could not move temporary file back: $!\n";
		return;
	}
	return 1;
}

sub moov_get_extra
{
	local *FH = shift @_;
	my $extra = 0;
	my $seen = undef;

	while (defined(my $line = <FH>)) {
		if ($line =~ /reserved_moov_size is too small, needed (\d+) additional/) {
			$seen = 1;
			$extra = $1;
			last;
		}
	}
	if (!$seen) {
		return undef;
	}
	return $extra;
}
