Skip to content

Commit

Permalink
init project
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisyue committed Mar 3, 2016
1 parent 608f1f4 commit f9e392d
Show file tree
Hide file tree
Showing 16 changed files with 546 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
composer.lock
phpunit.xml
vendor/
tags
*.cache
12 changes: 12 additions & 0 deletions .php_cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

$finder = Symfony\CS\Finder\DefaultFinder::create()
->exclude('vendor')
->in(__DIR__)
;

return Symfony\CS\Config\Config::create()
->setUsingCache(true)
->fixers(['-phpdoc_short_description', 'ordered_use'])
->finder($finder)
;
46 changes: 46 additions & 0 deletions Dumper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Chrisyue\PhpM3u8;

use Chrisyue\PhpM3u8\M3u8\M3u8;
use Chrisyue\PhpM3u8\M3u8\MediaSegment\UriProcessor\UriProcessorInterface;

class Dumper
{
private $mediaSegmentUriProcessor;

public function __construct(UriProcessorInterface $processor)
{
$this->mediaSegmentUriProcessor = $processor;
}

public function dump(M3u8 $m3u8)
{
$lines = [
'#EXTM3U',
sprintf('#EXT-X-VERSION:%s', $m3u8->getVersion()),
sprintf('#EXT-X-TARGETDURATION:%d', $m3u8->getTargetDuration()),
];

if ($m3u8->getMediaSequence()) {
$lines[] = sprintf('#EXT-X-MEDIA-SEQUENCE:%s', $m3u8->getMediaSequence());
}

if ($m3u8->getDiscontinuitySequence()) {
$lines[] = sprintf('#EXT-X-DISCONTINUITY-SEQUENCE:%s', $m3u8->getDiscontinuitySequence());
}

$lines[] = ''; // separator between m3u8 info and playlist

foreach ($m3u8->getPlaylist() as $mediaSegment) {
if ($mediaSegment->isDiscontinuity()) {
$lines[] = '#EXT-X-DISCONTINUITY';
}

$lines[] = sprintf('#EXTINF:%.3f,', $mediaSegment->getDuration());
$lines[] = $this->mediaSegmentUriProcessor->process($mediaSegment);
}

return implode(PHP_EOL, $lines);
}
}
34 changes: 34 additions & 0 deletions Loader/AbstractCachableLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Chrisyue\PhpM3u8\Loader;

use Psr\Cache\CacheItemPoolInterface;

abstract class AbstractCachableLoader implements LoaderInterface
{
private $cachePool;
private $options;

public function __construct(CacheItemPoolInterface $cachePool, array $options)
{
$this->cachePool = $cachePool;
$this->options = $options;
}

public function load($uri)
{
$cacheItem = $this->cachePool->getItem(md5($uri));
if ($cacheItem->isHit()) {
return $cacheItem->get();
}

$content = $this->loadContent($uri);
$cacheItem->set($content);
$cacheItem->expiresAfter($this->options['ttl']);
$this->cachePool->save($cacheItem);

return $content;
}

abstract protected function loadContent($uri);
}
21 changes: 21 additions & 0 deletions Loader/CachableLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Chrisyue\PhpM3u8\Loader;

class CachableLoader extends AbstractCachableLoader
{
protected function loadContent($uri)
{
$content = @file_get_contents($uri, null, stream_context_create([
'http' => [
'timeout' => 10,
],
]));

if (false === $content) {
throw new \Exception(sprintf('The m3u8 uri %s cannot be loaded', $uri));
}

return $content;
}
}
8 changes: 8 additions & 0 deletions Loader/LoaderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Chrisyue\PhpM3u8\Loader;

interface LoaderInterface
{
public function load($uri);
}
54 changes: 54 additions & 0 deletions M3u8/M3u8.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace Chrisyue\PhpM3u8\M3u8;

class M3u8
{
private $playlist;
private $version;
private $targetDuration;
private $discontinuitySequence;

public function __construct(Playlist $playlist, $version, $targetDuration, $discontinuitySequence = null)
{
$this->playlist = $playlist;
$this->version = $version;
$this->targetDuration = $targetDuration;
$this->discontinuitySequence = $discontinuitySequence;
}

public function getPlaylist()
{
return $this->playlist;
}

public function getVersion()
{
return $this->version;
}

public function getTargetDuration()
{
return $this->targetDuration;
}

public function getMediaSequence()
{
return $this->playlist->getFirst()->getSequence();
}

public function getDiscontinuitySequence()
{
return $this->discontinuitySequence;
}

public function getAge()
{
return $this->playlist->getAge();
}

public function getDuration()
{
return $this->playlist->getDuration();
}
}
39 changes: 39 additions & 0 deletions M3u8/MediaSegment/MediaSegment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Chrisyue\PhpM3u8\M3u8\MediaSegment;

class MediaSegment implements MediaSegmentInterface
{
protected $uri;
protected $duration;
protected $sequence;
protected $isDiscontinuity;

public function __construct($uri, $duration, $sequence, $isDiscontinuity = false)
{
$this->uri = $uri;
$this->duration = $duration;
$this->sequence = $sequence;
$this->isDiscontinuity = $isDiscontinuity;
}

public function getUri()
{
return $this->uri;
}

public function getDuration()
{
return $this->duration;
}

public function getSequence()
{
return $this->sequence;
}

public function isDiscontinuity()
{
return $this->isDiscontinuity;
}
}
14 changes: 14 additions & 0 deletions M3u8/MediaSegment/MediaSegmentInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Chrisyue\PhpM3u8\M3u8\MediaSegment;

interface MediaSegmentInterface
{
public function getUri();

public function getDuration();

public function getSequence();

public function isDiscontinuity();
}
21 changes: 21 additions & 0 deletions M3u8/MediaSegment/UriProcessor/CdnUriProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Chrisyue\PhpM3u8\M3u8\MediaSegment\UriProcessor;

use Chrisyue\PhpM3u8\M3u8\MediaSegment\MediaSegmentInterface;

class CdnUriProcessor implements UriProcessorInterface
{
private $host;
private $fullPathDir;

public function __construct($host)
{
$this->host = $host;
}

public function process(MediaSegmentInterface $mediaSegment)
{
return preg_replace('/^(https?:\/\/[^\/]+)?/', $this->host, $mediaSegment->getUri());
}
}
13 changes: 13 additions & 0 deletions M3u8/MediaSegment/UriProcessor/OriginUriProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Chrisyue\PhpM3u8\M3u8\MediaSegment\UriProcessor;

use Chrisyue\PhpM3u8\M3u8\MediaSegment\MediaSegmentInterface;

class OriginUriProcessor implements UriProcessorInterface
{
public function process(MediaSegmentInterface $mediaSegment)
{
return $mediaSegment->getUri();
}
}
10 changes: 10 additions & 0 deletions M3u8/MediaSegment/UriProcessor/UriProcessorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Chrisyue\PhpM3u8\M3u8\MediaSegment\UriProcessor;

use Chrisyue\PhpM3u8\M3u8\MediaSegment\MediaSegmentInterface;

interface UriProcessorInterface
{
public function process(MediaSegmentInterface $mediaSegment);
}
86 changes: 86 additions & 0 deletions M3u8/Playlist.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

namespace Chrisyue\PhpM3u8\M3u8;

use Chrisyue\PhpM3u8\M3u8\MediaSegment\MediaSegment;

class Playlist implements \Iterator
{
private $mediaSegments = [];
private $age;
private $position = 0;

public function __construct(array $mediaSegments = [], $age = null)
{
$this->mediaSegments = $mediaSegments;
$this->age = $age;
}

public function rewind()
{
$this->position = 0;
}

public function current()
{
return $this->mediaSegments[$this->position];
}

public function key()
{
return $this->position;
}

public function next()
{
++$this->position;
}

public function valid()
{
return isset($this->mediaSegments[$this->position]);
}

public function add(MediaSegment $mediaSegment)
{
$this->mediaSegments[] = $mediaSegment;

return $this;
}

public function getFirst()
{
$first = reset($this->mediaSegments);

if (false !== $first) {
return $first;
}
}

public function getDuration()
{
$duration = 0;
foreach ($this->mediaSegments as $segment) {
$duration += $segment->getDuration();
}

return $duration;
}

public function count()
{
return count($this->mediaSegments);
}

public function setAge($age)
{
$this->age = $age;

return $this;
}

public function getAge()
{
return $this->age;
}
}
Loading

0 comments on commit f9e392d

Please sign in to comment.