Passed
Push — master ( eb1d3e...b38e7e )
by Sébastien
02:22
created

InterlaceDetect::guessInterlacing()   B

Complexity

Conditions 9
Paths 26

Size

Total Lines 61
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 36
CRAP Score 9.2363

Importance

Changes 0
Metric Value
cc 9
eloc 42
nc 26
nop 3
dl 0
loc 61
ccs 36
cts 42
cp 0.8571
crap 9.2363
rs 7.6924
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @see       https://github.com/soluble-io/soluble-mediatools for the canonical repository
7
 *
8
 * @copyright Copyright (c) 2018-2019 Sébastien Vanvelthem. (https://github.com/belgattitude)
9
 * @license   https://github.com/soluble-io/soluble-mediatools/blob/master/LICENSE.md MIT
10
 */
11
12
namespace Soluble\MediaTools\Video\Detection;
13
14
use Soluble\MediaTools\Common\Assert\PathAssertionsTrait;
15
use Soluble\MediaTools\Common\Exception\FileNotFoundException;
16
use Soluble\MediaTools\Common\Exception\FileNotReadableException;
17
use Soluble\MediaTools\Common\Exception\UnsupportedParamException;
18
use Soluble\MediaTools\Common\Exception\UnsupportedParamValueException;
19
use Soluble\MediaTools\Common\IO\PlatformNullFile;
20
use Soluble\MediaTools\Common\Process\ProcessFactory;
21
use Soluble\MediaTools\Common\Process\ProcessParamsInterface;
22
use Soluble\MediaTools\Video\Config\FFMpegConfigInterface;
23
use Soluble\MediaTools\Video\Exception\AnalyzerExceptionInterface;
24
use Soluble\MediaTools\Video\Exception\AnalyzerProcessExceptionInterface;
25
use Soluble\MediaTools\Video\Exception\InvalidParamException;
26
use Soluble\MediaTools\Video\Exception\MissingInputFileException;
27
use Soluble\MediaTools\Video\Exception\ProcessFailedException;
28
use Soluble\MediaTools\Video\Exception\RuntimeReaderException;
29
use Soluble\MediaTools\Video\Filter\IdetVideoFilter;
30
use Soluble\MediaTools\Video\VideoConvertParams;
31
use Symfony\Component\Process\Exception as SPException;
32
33
class InterlaceDetect
34
{
35
    use PathAssertionsTrait;
36
37
    public const DEFAULT_INTERLACE_MAX_FRAMES = 1000;
38
39
    /** @var FFMpegConfigInterface */
40
    protected $ffmpegConfig;
41
42 2
    public function __construct(FFMpegConfigInterface $ffmpegConfig)
43
    {
44 2
        $this->ffmpegConfig = $ffmpegConfig;
45 2
    }
46
47
    /**
48
     * @throws AnalyzerExceptionInterface
49
     * @throws AnalyzerProcessExceptionInterface
50
     * @throws ProcessFailedException
51
     * @throws MissingInputFileException
52
     * @throws RuntimeReaderException
53
     */
54 2
    public function guessInterlacing(string $file, int $maxFramesToAnalyze = self::DEFAULT_INTERLACE_MAX_FRAMES, ?ProcessParamsInterface $processParams = null): InterlaceDetectGuess
55
    {
56 2
        $adapter = $this->ffmpegConfig->getAdapter();
57 2
        $params  = (new VideoConvertParams())
58 2
            ->withVideoFilter(new IdetVideoFilter()) // detect interlaced frames :)
59 2
            ->withVideoFrames($maxFramesToAnalyze)
60 2
            ->withNoAudio() // speed up the thing
61 2
            ->withOutputFormat('rawvideo')
62 2
            ->withOverwrite();
63
64
        try {
65 2
            $this->ensureFileReadable($file);
66
67 1
            $arguments = $adapter->getMappedConversionParams($params);
68 1
            $ffmpegCmd = $adapter->getCliCommand($arguments, $file, new PlatformNullFile());
69
70 1
            $pp = $processParams ?? $this->ffmpegConfig->getProcessParams();
71
72 1
            $process = (new ProcessFactory($ffmpegCmd, $pp))->__invoke();
73 1
            $process->mustRun();
74 1
        } catch (FileNotFoundException | FileNotReadableException $e) {
75 1
            throw new MissingInputFileException($e->getMessage());
76
        } catch (UnsupportedParamValueException | UnsupportedParamException $e) {
77
            throw new InvalidParamException($e->getMessage());
78
        } catch (SPException\ProcessFailedException | SPException\ProcessTimedOutException | SPException\ProcessSignaledException $e) {
79
            throw new ProcessFailedException($e->getProcess(), $e);
80
        } catch (SPException\RuntimeException $e) {
81
            throw new RuntimeReaderException($e->getMessage());
82
        }
83
84 1
        $stdErr = preg_split("/(\r\n|\n|\r)/", $process->getErrorOutput());
85
86
        // Counted frames
87 1
        $interlaced_tff = 0;
88 1
        $interlaced_bff = 0;
89 1
        $progressive    = 0;
90 1
        $undetermined   = 0;
91 1
        $total_frames   = 0;
92
93 1
        if ($stdErr !== false) {
94 1
            foreach ($stdErr as $line) {
95 1
                if (mb_substr($line, 0, 12) !== '[Parsed_idet') {
96 1
                    continue;
97
                }
98
99 1
                $unspaced = sprintf('%s', preg_replace('/( )+/', '', $line));
100 1
                $matches  = [];
101 1
                if (preg_match_all('/TFF:(\d+)BFF:(\d+)Progressive:(\d+)Undetermined:(\d+)/i', $unspaced, $matches) < 1) {
102 1
                    continue;
103
                }
104
105
                //$type = strpos(strtolower($unspaced), 'single') ? 'single' : 'multi';
106 1
                $interlaced_tff += (int) $matches[1][0];
107 1
                $interlaced_bff += (int) $matches[2][0];
108 1
                $progressive += (int) $matches[3][0];
109 1
                $undetermined += (int) $matches[4][0];
110 1
                $total_frames += ((int) $matches[1][0] + (int) $matches[2][0] + (int) $matches[3][0] + (int) $matches[4][0]);
111
            }
112
        }
113
114 1
        return new InterlaceDetectGuess($interlaced_tff, $interlaced_bff, $progressive, $undetermined);
115
    }
116
}
117