<?php

ini_set('display_errors', true);
setlocale(LC_CTYPE, "en_US.UTF-8");

$dirs = $argv;

array_shift($dirs);

if (!$dirs) {
    echo 'Usage : php '.basename(__FILE__).' [directory]...'.PHP_EOL; 
    exit;
}
echo 'Running on:'.PHP_EOL.implode(PHP_EOL, $dirs).PHP_EOL.PHP_EOL;

$p = new process($dirs);

$files = $p->getAllFiles();

foreach ($files as $file) {
    //*
    if (preg_match('#/no/#', $file)) {
        continue;
    }
    /**/
    echo $file.' : ';
    try {
        $compatible = $p->isCompatible($file);
    } catch (Exception $e) {
        echo $e->getMessage().PHP_EOL;
        continue;
    }
    echo ($compatible ? 'ok' : 'no').PHP_EOL;
    //*
    if (!$compatible) {
        $mvDir = dirname($file).'/no';
        if (!is_dir($mvDir)) {
            @mkdir($mvDir);
        }
        rename($file, $mvDir.'/'.basename($file));
        echo 'moved'.PHP_EOL;
    }
    /**/
}

class process {
    
    protected $_dirs;
    
    public function __construct($dirs)
    {
        if (!is_array($dirs)) {
            $dirs = array($dirs);
        }
        $this->_dirs = $dirs;
    }
    
    public function getAllFiles ()
    {
        $files = array();
        foreach ($this->_dirs as $dir) {
            foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) as $file) {
                if ($file->isDir()) {
                    continue;
                }
                $files[] = realpath($file->getPathname());
            }
        }
        sort($files);
        return $files;
    }
    
    public function getStreams ($file)
    {
        $info = $this->shellExec('ffmpeg -i '.escapeshellarg($file));
        
        $reg = '~Stream'.
            '\s+#(?P<index>[0-9.]+(?:\([^)]+\))?):'.
        	'\s+(?P<type>[^\s:]+):'.
            '\s+(?P<codec>[^,]+),'.
            '\s+(?P<data>.+)'.
            '~';
        if (!preg_match_all($reg, $info, $matches, PREG_SET_ORDER)) {
            throw new Exception('cannot parse');
        }
        
        return $matches;
    }
    
    public function isCompatible ($file)
    {
        $streams = $this->getStreams($file);
        
        if (count($streams) != 2) {
            throw new Exception('More or less than 2 streams');
        }
        
        foreach ($streams as $stream) {
            if (strtolower($stream['type']) == 'audio') {
                if (!$this->isAudioCompatible($stream['codec'])) {
                    return false;
                }
            } elseif (strtolower($stream['type']) == 'video') {
                if (!$this->isVideoCompatible($stream['codec'])) {
                    return false;
                }
            }
        }
        return true;
    }
    
    public function isAudioCompatible ($codec)
    {
        return !!preg_match($this->getRegsCompatibleCodecs($this->getCompatibleAudioCodecs()), $codec);
    }
    
    public function isVideoCompatible ($codec)
    {
        return !!preg_match($this->getRegsCompatibleCodecs($this->getCompatibleVideoCodecs()), $codec);
    }
    
    public function getRegsCompatibleCodecs (array $codecs)
    {
        $codecs = implode('|', $codecs);
        $codecs = '#'.$codecs.'#i';
        return $codecs;
    }
    
    public function getCompatibleAudioCodecs ()
    {
        return array('AAC', 'downmix', 'FLAC', 'MP2', 'MP3', 'Vorbis');
    }
    
    public function getCompatibleVideoCodecs ()
    {
        return array ('MPEG2', 'h264', 'MPEG4', 'VC1');
    }
    
    public function shellExec ($cmd)
    {
        //echo $cmd.PHP_EOL;
        return shell_exec($cmd.' 2>&1');
    }
}