refactor(streaming): extract resolveStreamCodecMeta from startStream

The codec-metadata derivation persisted for a started live stream (player
compatibility, audio/video codec names, resolution snapped to the nearest
standard height) was an inline block reading ffprobe output. Pull it into a
pure resolveStreamCodecMeta() helper taking the ffprobe array and the
player_allow_hevc flag and returning [compatible, audio, video, resolution].

The only external input, SettingsManager::getAll()['player_allow_hevc'], is now
passed in (getAll() just returns the cached settings array, so hoisting the read
out of the guard is free). Add unit tests: non-array/missing-codecs defaults,
compatible h264/aac, resolution snapping, HEVC gating by the allow flag, and
incompatible-but-reported codecs.

Verified: phpstan level 5 green, phpunit 379/379, make gates green.
This commit is contained in:
Divarion_D
2026-08-07 20:43:37 +03:00
parent 8973f5580f
commit f99048b79f
2 changed files with 78 additions and 13 deletions
@@ -228,4 +228,54 @@ final class StreamProcessMovieOutputTest extends TestCase {
$this->assertSame('headers', $out[0]['argument_key']);
$this->assertSame('X:1', $out[0]['value']);
}
// ── resolveStreamCodecMeta (startStream codec metadata) ────
public function testCodecMetaNonArrayReturnsDefaults(): void {
$this->assertSame([0, null, null, null], $this->call('resolveStreamCodecMeta', null, false));
$this->assertSame([0, null, null, null], $this->call('resolveStreamCodecMeta', 'not-json', false));
}
public function testCodecMetaWithoutCodecsKey(): void {
$this->assertSame([0, null, null, null], $this->call('resolveStreamCodecMeta', ['container' => 'mpegts'], false));
}
public function testCodecMetaCompatibleH264Aac(): void {
$probe = ['codecs' => [
'video' => ['codec_name' => 'h264', 'height' => 1080],
'audio' => ['codec_name' => 'aac'],
]];
[$compat, $audio, $video, $res] = $this->call('resolveStreamCodecMeta', $probe, false);
$this->assertSame(1, $compat);
$this->assertSame('aac', $audio);
$this->assertSame('h264', $video);
$this->assertSame(1080, $res);
}
public function testCodecMetaResolutionSnapsToNearest(): void {
$probe = ['codecs' => ['video' => ['codec_name' => 'h264', 'height' => 700]]];
[, , , $res] = $this->call('resolveStreamCodecMeta', $probe, false);
$this->assertSame(720, $res); // 700 -> nearest of 240..2160
}
public function testCodecMetaHevcGatedByAllowFlag(): void {
$probe = ['codecs' => [
'video' => ['codec_name' => 'hevc', 'height' => 2160],
'audio' => ['codec_name' => 'ac3'],
]];
$this->assertSame(0, $this->call('resolveStreamCodecMeta', $probe, false)[0]); // hevc not allowed
$this->assertSame(1, $this->call('resolveStreamCodecMeta', $probe, true)[0]); // hevc allowed
}
public function testCodecMetaIncompatibleStillReportsCodecs(): void {
$probe = ['codecs' => [
'video' => ['codec_name' => 'mpeg2video', 'height' => 576],
'audio' => ['codec_name' => 'aac'],
]];
[$compat, $audio, $video, $res] = $this->call('resolveStreamCodecMeta', $probe, false);
$this->assertSame(0, $compat); // mpeg2video not whitelisted
$this->assertSame('mpeg2video', $video);
$this->assertSame('aac', $audio);
$this->assertSame(576, $res);
}
}