Passed
Push — master ( 4bc7af...ac0e9d )
by Amin
02:25
created

HLSFilter::streamFilter()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 1
dl 0
loc 13
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of the PHP-FFmpeg-video-streaming package.
5
 *
6
 * (c) Amin Yazdanpanah <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Streaming\Filters;
13
14
use Streaming\StreamInterface;
15
use Streaming\File;
16
use Streaming\Representation;
17
use Streaming\Utiles;
18
19
class HLSFilter extends StreamFilter
20
{
21
    /**  @var \Streaming\HLS */
22
    private $hls;
23
24
    /** @var string */
25
    private $dirname;
26
27
    /** @var string */
28
    private $filename;
29
30
    /** @var string */
31
    private $seg_sub_dir;
32
33
    /** @var string */
34
    private $base_url;
35
36
    /** @var string */
37
    private $seg_filename;
38
39
    /**
40
     * @param
41
     * @return array
42
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment @return at position 0 could not be parsed: Unknown type name '@return' at position 0 in @return.
Loading history...
43
    private function getFormats(): array
44
    {
45
        $format = ['-c:v', $this->hls->getFormat()->getVideoCodec()];
0 ignored issues
show
Bug introduced by
The method getVideoCodec() does not exist on FFMpeg\Format\FormatInterface. It seems like you code against a sub-type of FFMpeg\Format\FormatInterface such as FFMpeg\Format\VideoInterface or Streaming\Format\Video or FFMpeg\Format\Video\DefaultVideo. ( Ignorable by Annotation )

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

45
        $format = ['-c:v', $this->hls->getFormat()->/** @scrutinizer ignore-call */ getVideoCodec()];
Loading history...
46
        $audio_format = $this->hls->getFormat()->getAudioCodec();
0 ignored issues
show
Bug introduced by
The method getAudioCodec() does not exist on FFMpeg\Format\FormatInterface. It seems like you code against a sub-type of FFMpeg\Format\FormatInterface such as FFMpeg\Format\AudioInterface. ( Ignorable by Annotation )

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

46
        $audio_format = $this->hls->getFormat()->/** @scrutinizer ignore-call */ getAudioCodec();
Loading history...
47
48
        return $audio_format ? array_merge($format, ['-c:a', $audio_format]) : $format;
49
    }
50
51
    /**
52
     * @param Representation $rep
53
     * @param bool $not_last
54
     * @return array
55
     */
56
    private function playlistPath(Representation $rep, bool $not_last): array
57
    {
58
        return $not_last ? [$this->dirname . "/" . $this->filename . "_" . $rep->getHeight() . "p.m3u8"] : [];
59
    }
60
61
    /**
62
     * @param Representation $rep
63
     * @return array
64
     */
65
    private function getAudioBitrate(Representation $rep): array
66
    {
67
        return $rep->getAudioKiloBitrate() ? ["-b:a", $rep->getAudioKiloBitrate() . "k"] : [];
68
    }
69
70
    /**
71
     * @return array
72
     */
73
    private function getBaseURL(): array
74
    {
75
        return $this->base_url ? ["-hls_base_url", $this->base_url] : [];
76
    }
77
78
    /**
79
     * @param
80
     * @return array
81
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment @return at position 0 could not be parsed: Unknown type name '@return' at position 0 in @return.
Loading history...
82
    private function getKeyInfo(): array
83
    {
84
        return $this->hls->getHlsKeyInfoFile() ? ["-hls_key_info_file", $this->hls->getHlsKeyInfoFile()] : [];
85
    }
86
87
    /**
88
     * @return string
89
     */
90
    private function getInitFilename(): string
91
    {
92
        return $this->seg_sub_dir . $this->filename . "_" . $this->hls->getHlsFmp4InitFilename();
93
    }
94
95
    /**
96
     * @param Representation $rep
97
     * @return string
98
     */
99
    private function getSegmentFilename(Representation $rep): string
100
    {
101
        $ext = ($this->hls->getHlsSegmentType() === "fmp4") ? "m4s" : "ts";
102
        return $this->seg_filename . "_" . $rep->getHeight() . "p_%04d." . $ext;
103
    }
104
105
    /**
106
     * @param Representation $rep
107
     * @return array
108
     */
109
    private function initArgs(Representation $rep): array
110
    {
111
        return [
112
            "-s:v", $rep->getResize(),
113
            "-crf", "20",
114
            "-sc_threshold", "0",
115
            "-g", "48",
116
            "-keyint_min", "48",
117
            "-hls_list_size", $this->hls->getHlsListSize(),
118
            "-hls_time", $this->hls->getHlsTime(),
119
            "-hls_allow_cache", (int)$this->hls->isHlsAllowCache(),
120
            "-b:v", $rep->getKiloBitrate() . "k",
121
            "-maxrate", intval($rep->getKiloBitrate() * 1.2) . "k",
122
            "-hls_segment_type", $this->hls->getHlsSegmentType(),
123
            "-hls_fmp4_init_filename", $this->getInitFilename(),
124
            "-hls_segment_filename", $this->getSegmentFilename($rep)
125
        ];
126
    }
127
128
    /**
129
     * @param Representation $rep
130
     * @param bool $not_last
131
     */
132
    private function getArgs(Representation $rep, bool $not_last): void
133
    {
134
        $this->filter = array_merge(
135
            $this->filter,
136
            $this->initArgs($rep),
137
            $this->getAudioBitrate($rep),
138
            $this->getBaseURL(),
139
            $this->getKeyInfo(),
140
            $this->hls->getAdditionalParams(),
141
            ["-strict", $this->hls->getStrict()],
142
            $this->playlistPath($rep, $not_last)
143
        );
144
    }
145
146
    /**
147
     * set segments paths
148
     */
149
    private function segmentPaths()
150
    {
151
        if ($this->hls->getTsSubDirectory()) {
152
            File::makeDir($this->dirname . "/" . $this->hls->getTsSubDirectory() . "/");
153
        }
154
155
        $base = Utiles::appendSlash($this->hls->getHlsBaseUrl());
156
157
        $this->seg_sub_dir = Utiles::appendSlash($this->hls->getTsSubDirectory());
158
        $this->seg_filename = $this->dirname . "/" . $this->seg_sub_dir . $this->filename;
159
        $this->base_url = $base . $this->seg_sub_dir;
160
    }
161
162
    /**
163
     * set paths
164
     */
165
    private function setPaths(): void
166
    {
167
        $this->dirname = str_replace("\\", "/", $this->hls->getPathInfo(PATHINFO_DIRNAME));
168
        $this->filename = $this->hls->getPathInfo(PATHINFO_FILENAME);
169
        $this->segmentPaths();
170
    }
171
172
    /**
173
     * @param StreamInterface $stream
174
     * @return void
175
     */
176
    public function streamFilter(StreamInterface $stream): void
177
    {
178
        $this->hls = $stream;
0 ignored issues
show
Documentation Bug introduced by
$stream is of type Streaming\StreamInterface, but the property $hls was declared to be of type Streaming\HLS. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
179
        $this->setPaths();
180
181
        $reps = $this->hls->getRepresentations();
0 ignored issues
show
Bug introduced by
The method getRepresentations() does not exist on Streaming\StreamInterface. It seems like you code against a sub-type of Streaming\StreamInterface such as Streaming\Streaming. ( Ignorable by Annotation )

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

181
        /** @scrutinizer ignore-call */ 
182
        $reps = $this->hls->getRepresentations();
Loading history...
182
183
        foreach ($reps as $key => $rep) {
184
            if ($key) {
185
                $this->filter = array_merge($this->filter, $this->getFormats());
186
            }
187
188
            $this->getArgs($rep, end($reps) !== $rep);
189
        }
190
    }
191
}