Passed
Pull Request — master (#262)
by Pascal
02:27
created

FFProbe::format()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 7
rs 10
1
<?php
2
3
namespace ProtoneMedia\LaravelFFMpeg\FFMpeg;
4
5
use Alchemy\BinaryDriver\Exception\ExecutionFailureException;
6
use FFMpeg\Exception\RuntimeException;
7
use FFMpeg\FFProbe as FFMpegFFProbe;
8
9
class FFProbe extends FFMpegFFProbe
10
{
11
    /**
12
     * @var \ProtoneMedia\LaravelFFMpeg\Filesystem\Media|\ProtoneMedia\LaravelFFMpeg\Filesystem\MediaOnNetwork
13
     */
14
    protected $media;
15
16
    public function setMedia($media): self
17
    {
18
        $this->media = $media;
19
20
        return $this;
21
    }
22
23
    /**
24
     * Create a new instance of this class with the instance of the underlying library.
25
     *
26
     * @param \FFMpeg\FFProbe $probe
27
     * @return self
28
     */
29
    public static function make(FFMpegFFProbe $probe): self
30
    {
31
        if ($probe instanceof FFProbe) {
32
            return $probe;
33
        }
34
35
        return new static($probe->getFFProbeDriver(), $probe->getCache());
36
    }
37
38
    /**
39
     * Probes the streams contained in a given file.
40
     *
41
     * @param string $pathfile
42
     * @return \FFMpeg\FFProbe\DataMapping\StreamCollection
43
     * @throws \FFMpeg\Exception\InvalidArgumentException
44
     * @throws \FFMpeg\Exception\RuntimeException
45
     */
46
47
    private function shouldUseCustomProbe($pathfile): bool
48
    {
49
        if (!$this->media) {
50
            return false;
51
        }
52
53
        if ($this->media->getLocalPath() !== $pathfile) {
54
            return false;
55
        }
56
57
        if (empty($this->media->getCompiledInputOptions())) {
58
            return false;
59
        }
60
61
        if (!$this->getOptionsTester()->has('-show_streams')) {
62
            throw new RuntimeException('This version of ffprobe is too old and does not support `-show_streams` option, please upgrade');
63
        }
64
65
        return true;
66
    }
67
68
    public function streams($pathfile)
69
    {
70
        if (!$this->shouldUseCustomProbe($pathfile)) {
71
            return parent::streams($pathfile);
72
        }
73
74
        return $this->probeStreams($pathfile, '-show_streams', static::TYPE_STREAMS);
75
    }
76
77
    public function format($pathfile)
78
    {
79
        if (!$this->shouldUseCustomProbe($pathfile)) {
80
            return parent::format($pathfile);
81
        }
82
83
        return $this->probeStreams($pathfile, '-show_format', static::TYPE_FORMAT);
84
    }
85
86
    /**
87
     * This is just copy-paste from FFMpeg\FFProbe...
88
     * It prepends the command with the headers.
89
     */
90
    private function probeStreams($pathfile, $command, $type, $allowJson = true)
91
    {
92
        $commands = array_merge(
93
            $this->media->getCompiledInputOptions(),
94
            [$pathfile, $command]
95
        );
96
97
        $parseIsToDo = false;
98
99
        if ($allowJson && $this->getOptionsTester()->has('-print_format')) {
100
            // allowed in latest PHP-FFmpeg version
101
            $commands[] = '-print_format';
102
            $commands[] = 'json';
103
        } elseif ($allowJson && $this->getOptionsTester()->has('-of')) {
104
            // option has changed in avconv 9
105
            $commands[] = '-of';
106
            $commands[] = 'json';
107
        } else {
108
            $parseIsToDo = true;
109
        }
110
111
        try {
112
            $output = $this->getFFProbeDriver()->command($commands);
113
        } catch (ExecutionFailureException $e) {
114
            throw new RuntimeException(sprintf('Unable to probe %s', $pathfile), $e->getCode(), $e);
115
        }
116
117
        if ($parseIsToDo) {
118
            $data = $this->getParser()->parse($type, $output);
119
        } else {
120
            try {
121
                $data = @json_decode($output, true);
122
123
                if (JSON_ERROR_NONE !== json_last_error()) {
124
                    throw new RuntimeException(sprintf('Unable to parse json %s', $output));
125
                }
126
            } catch (RuntimeException $e) {
127
                return $this->probeStreams($pathfile, false);
0 ignored issues
show
Bug introduced by
The call to ProtoneMedia\LaravelFFMp...FFProbe::probeStreams() has too few arguments starting with type. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

127
                return $this->/** @scrutinizer ignore-call */ probeStreams($pathfile, false);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
128
            }
129
        }
130
131
        return $this->getMapper()->map($type, $data);
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type array; however, parameter $data of FFMpeg\FFProbe\MapperInterface::map() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

131
        return $this->getMapper()->map($type, /** @scrutinizer ignore-type */ $data);
Loading history...
132
    }
133
}
134