Failed Conditions
Push — master ( 79098a...34c99d )
by Sébastien
04:17
created

VideoStream   B

Complexity

Total Complexity 46

Size/Duplication

Total Lines 217
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 46
eloc 56
dl 0
loc 217
ccs 85
cts 85
cp 1
rs 8.72
c 0
b 0
f 0

33 Methods

Rating   Name   Duplication   Size   Complexity  
A getCodecName() 0 3 1
A getBitRate() 0 3 1
A getColorTransfer() 0 3 1
A getProfile() 0 3 1
A getCodecTimeBase() 0 3 1
A getLevel() 0 3 1
A getFpsFromDuration() 0 7 3
A getCodedWidth() 0 3 1
A getStartTime() 0 3 1
A isAvc() 0 7 2
A getDisplayAspectRatio() 0 3 1
A getIndex() 0 3 1
A __construct() 0 4 1
A getRFrameRate() 0 3 1
A getWidth() 0 3 1
A getHeight() 0 3 1
A getCodecLongName() 0 3 1
A getDurationTs() 0 3 1
A getCodecTagString() 0 3 1
A getNbFrames() 0 3 1
A getCodedHeight() 0 3 1
A getTags() 0 3 1
B getFps() 0 22 10
A getCodecType() 0 3 1
A getColorSpace() 0 3 1
A getStreamMetadata() 0 3 1
A getDuration() 0 6 2
A getPixFmt() 0 3 1
A getDimensions() 0 5 1
A getColorRange() 0 3 1
A getAvgFrameRate() 0 3 1
A getSampleAspectRatio() 0 3 1
A getTimeBase() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like VideoStream often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use VideoStream, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Soluble\MediaTools\Video\Info;
6
7
use Psr\Log\LoggerInterface;
8
use Soluble\MediaTools\Video\Exception\UnexpectedMetadataException;
9
use Soluble\MediaTools\Video\Info\Util\MetadataTypeSafeReader;
10
11
class VideoStream implements VideoStreamInterface
12
{
13
    /** @var array<string, mixed> */
14
    private $streamMetadata;
15
16
    /** @var MetadataTypeSafeReader */
17
    private $tsReader;
18
19
    /**
20
     * @param array<string, mixed> $streamMetadata
21
     */
22 10
    public function __construct(array $streamMetadata, ?LoggerInterface $logger = null)
23
    {
24 10
        $this->streamMetadata = $streamMetadata;
25 10
        $this->tsReader       = new MetadataTypeSafeReader($streamMetadata, $logger);
26 10
    }
27
28 2
    public function getIndex(): int
29
    {
30 2
        return $this->tsReader->getKeyIntValue('index');
31
    }
32
33 2
    public function getCodecType(): string
34
    {
35 2
        return $this->tsReader->getKeyStringValue('codec_type');
36
    }
37
38 2
    public function getCodecName(): string
39
    {
40 2
        return $this->tsReader->getKeyStringValue('codec_name');
41
    }
42
43 1
    public function getCodecLongName(): ?string
44
    {
45 1
        return $this->tsReader->getKeyStringOrNullValue('codec_long_name');
46
    }
47
48 1
    public function getCodecTimeBase(): ?string
49
    {
50 1
        return $this->tsReader->getKeyStringOrNullValue('codec_time_base');
51
    }
52
53 1
    public function getCodecTagString(): ?string
54
    {
55 1
        return $this->tsReader->getKeyStringOrNullValue('codec_tag_string');
56
    }
57
58 4
    public function getWidth(): int
59
    {
60 4
        return $this->tsReader->getKeyIntValue('width');
61
    }
62
63 4
    public function getHeight(): int
64
    {
65 4
        return $this->tsReader->getKeyIntValue('height');
66
    }
67
68 1
    public function getCodedWidth(): ?int
69
    {
70 1
        return $this->tsReader->getKeyIntOrNullValue('coded_width');
71
    }
72
73 1
    public function getCodedHeight(): ?int
74
    {
75 1
        return $this->tsReader->getKeyIntOrNullValue('coded_height');
76
    }
77
78 1
    public function getSampleAspectRatio(): ?string
79
    {
80 1
        return $this->tsReader->getKeyStringOrNullValue('sample_aspect_ratio');
81
    }
82
83 1
    public function getDisplayAspectRatio(): ?string
84
    {
85 1
        return $this->tsReader->getKeyStringOrNullValue('display_aspect_ratio');
86
    }
87
88 3
    public function getPixFmt(): ?string
89
    {
90 3
        return $this->tsReader->getKeyStringOrNullValue('pix_fmt');
91
    }
92
93 1
    public function getAvgFrameRate(): ?string
94
    {
95 1
        return $this->tsReader->getKeyStringOrNullValue('avg_frame_rate');
96
    }
97
98 2
    public function getRFrameRate(): ?string
99
    {
100 2
        return $this->tsReader->getKeyStringOrNullValue('r_frame_rate');
101
    }
102
103 1
    public function getTimeBase(): ?string
104
    {
105 1
        return $this->tsReader->getKeyStringOrNullValue('time_base');
106
    }
107
108 1
    public function getDurationTs(): ?int
109
    {
110 1
        return $this->tsReader->getKeyIntOrNullValue('duration_ts');
111
    }
112
113 2
    public function getDuration(): float
114
    {
115
        try {
116 2
            return $this->tsReader->getKeyFloatValue('duration');
117 1
        } catch (UnexpectedMetadataException $e) {
118 1
            return 0;
119
        }
120
    }
121
122 1
    public function getProfile(): ?string
123
    {
124 1
        return $this->tsReader->getKeyStringOrNullValue('profile');
125
    }
126
127 3
    public function getBitRate(): ?int
128
    {
129 3
        return $this->tsReader->getKeyIntOrNullValue('bit_rate');
130
    }
131
132 3
    public function getNbFrames(): ?int
133
    {
134 3
        return $this->tsReader->getKeyIntOrNullValue('nb_frames');
135
    }
136
137 2
    public function isAvc(): ?bool
138
    {
139 2
        if (!isset($this->streamMetadata['is_avc'])) {
140 2
            return null;
141
        }
142
143 1
        return $this->streamMetadata['is_avc'] === 'true';
144
    }
145
146 1
    public function getLevel(): ?int
147
    {
148 1
        return $this->tsReader->getKeyIntOrNullValue('level');
149
    }
150
151 1
    public function getStartTime(): ?float
152
    {
153 1
        return $this->tsReader->getKeyFloatOrNullValue('start_time');
154
    }
155
156 1
    public function getColorRange(): ?string
157
    {
158 1
        return $this->tsReader->getKeyStringOrNullValue('color_range');
159
    }
160
161 1
    public function getColorSpace(): ?string
162
    {
163 1
        return $this->tsReader->getKeyStringOrNullValue('color_space');
164
    }
165
166 1
    public function getColorTransfer(): ?string
167
    {
168 1
        return $this->tsReader->getKeyStringOrNullValue('color_transfer');
169
    }
170
171 1
    public function getDimensions(): array
172
    {
173
        return [
174 1
            'width'  => $this->getWidth(),
175 1
            'height' => $this->getHeight()
176
        ];
177
    }
178
179 1
    public function getFps(?int $decimals = null): ?float
180
    {
181 1
        $rFrame = $this->getRFrameRate();
182 1
        $fps    = null;
183
184 1
        if ($rFrame !== null && preg_match('/^[0-9]+\/[0-9]+$/', $rFrame) !== false) {
185
            // Let's use the rframe_rate
186 1
            [$frames, $base] = explode('/', $rFrame);
187 1
            if (is_numeric($base) && $base > 0 && is_numeric($frames) && $frames > 0) {
188 1
                $fps = (float) ((int) $frames / (int) $base);
189
            }
190
        }
191
192 1
        if ($fps === null) {
193 1
            $fps = $this->getFpsFromDuration();
194
        }
195
196 1
        if ($decimals !== null && $fps !== null) {
197 1
            $fps = round($fps, $decimals);
198
        }
199
200 1
        return $fps;
201
    }
202
203 1
    private function getFpsFromDuration(): ?float
204
    {
205 1
        if (($this->getNbFrames() ?? 0) > 0 && ($this->getDuration() ?? 0) > 0) {
206 1
            return (float) $this->getNbFrames() / $this->getDuration();
207
        }
208
209 1
        return null;
210
    }
211
212
    /**
213
     * @return array<string, string>
214
     */
215 1
    public function getTags(): array
216
    {
217 1
        return $this->streamMetadata['tags'] ?? [];
218
    }
219
220
    /**
221
     * Return underlying ffprobe json metadata.
222
     *
223
     * @return array<string, mixed>
224
     */
225 1
    public function getStreamMetadata(): array
226
    {
227 1
        return $this->streamMetadata;
228
    }
229
}
230