diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 96179350..19244479 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -48,6 +48,12 @@ parameters: count: 1 path: src/Cli/Commands/MonitorCommand.php + - + message: '#^Static method XcVm\\Cli\\Commands\\MonitorCommand\:\:parseFrameRate\(\) is unused\.$#' + identifier: method.unused + count: 1 + path: src/Cli/Commands/MonitorCommand.php + - message: '#^Call to function is_numeric\(\) with int\\|int\<1, max\> will always evaluate to true\.$#' identifier: function.alreadyNarrowedType diff --git a/src/Cli/Commands/MonitorCommand.php b/src/Cli/Commands/MonitorCommand.php index aeb0462a..d6556698 100644 --- a/src/Cli/Commands/MonitorCommand.php +++ b/src/Cli/Commands/MonitorCommand.php @@ -509,22 +509,10 @@ class MonitorCommand implements CommandInterface { $d75674a646265e7b = $E02429d2ee600884['codecs']['video']['avg_frame_rate'] ?: $E02429d2ee600884['codecs']['video']['r_frame_rate']; goto label768; label768: - if (stripos($d75674a646265e7b, '/') !== false) { - goto label780; + $d75674a646265e7b = self::parseFrameRate($d75674a646265e7b); + if (0 < $d75674a646265e7b) { + $b4015d24aedaf0db = $d75674a646265e7b; } - $d75674a646265e7b = floatval($d75674a646265e7b); - goto label1052; - label780: - list($Be71401a913607c0, $Cd98e5a46a318d0a) = array_map('floatval', explode('/', $d75674a646265e7b)); - goto label1047; - label1047: - $d75674a646265e7b = floatval($Be71401a913607c0 / $Cd98e5a46a318d0a); - label1052: - if (!(0 < $d75674a646265e7b)) { - goto label1057; - } - $b4015d24aedaf0db = $d75674a646265e7b; - label1057: goto label1847; label1847: @@ -596,6 +584,22 @@ class MonitorCommand implements CommandInterface { return 0; } + /** + * Parse an ffprobe frame-rate field ("30", "30000/1001", "25/1") into fps. + * Extracted from the FPS-check goto cluster (label768/780/1047/1052/1057). + * + * @param mixed $rRate Raw avg_frame_rate / r_frame_rate value. + * @return float Frames per second; 0.0 for empty/zero/malformed input. + */ + private static function parseFrameRate($rRate): float { + $rRate = (string) $rRate; + if (strpos($rRate, '/') !== false) { + list($rNum, $rDen) = array_map('floatval', explode('/', $rRate)); + return $rDen != 0.0 ? (float) ($rNum / $rDen) : 0.0; + } + return (float) $rRate; + } + private function checkRunning(int $rStreamID): void { clearstatcache(true); $rPID = 0; diff --git a/tests/Unit/MonitorCommandTest.php b/tests/Unit/MonitorCommandTest.php new file mode 100644 index 00000000..9a05947d --- /dev/null +++ b/tests/Unit/MonitorCommandTest.php @@ -0,0 +1,38 @@ +setAccessible(true); + return $m->invoke(null, ...$args); + } + + // ── parseFrameRate (label768/780/1047/1052/1057) ─────────── + + public function testPlainInteger(): void { + $this->assertSame(30.0, $this->call('parseFrameRate', '30')); + $this->assertSame(25.0, $this->call('parseFrameRate', 25)); + } + + public function testRationalFrameRate(): void { + $this->assertSame(25.0, $this->call('parseFrameRate', '25/1')); + $this->assertEqualsWithDelta(29.97, $this->call('parseFrameRate', '30000/1001'), 0.001); + } + + public function testZeroAndMalformedAreZero(): void { + $this->assertSame(0.0, $this->call('parseFrameRate', '')); + $this->assertSame(0.0, $this->call('parseFrameRate', '0')); + $this->assertSame(0.0, $this->call('parseFrameRate', '0/0'), 'division-by-zero guarded'); + $this->assertSame(0.0, $this->call('parseFrameRate', '30/0'), 'zero denominator guarded'); + } +}