photo/app/Media/MSVideo/Containers/rlist.php

104 lines
2.5 KiB
PHP
Raw Normal View History

2024-09-24 11:55:40 +00:00
<?php
namespace App\Media\MSVideo\Containers;
/*
* https://netghost.narod.ru/gff/graphics/summary/micriff.htm
*
* Indicate the format of the data stream(s) stored in the file
*/
use Illuminate\Support\Collection;
use App\Media\MSVideo\Container;
use App\Media\MSVideo\Containers\rlist\movi;
class rlist extends Container
{
private const container_classes = 'App\\Media\\MSVideo\\Containers\\rlist\\';
public function __construct(int $offset,int $size,string $filename,bool $be,?string $data)
{
parent::__construct($offset,$size,$filename,$be,$data);
$this->containers = $this->parseContainer($data);
// For debugging
if (FALSE)
$this->debug = hex_dump($data ?: $this->data(min($size,256)));
}
private function parseContainer(string $bytes=NULL): Collection
{
$this->be = FALSE; // @todo
$rp = 0;
if (! $bytes) {
$fh = fopen($this->filename,'r');
fseek($fh,$this->offset);
}
$result = collect();
// Our first container should be hrl
$read = $bytes ? substr($bytes,$rp,4) : fread($fh,4);
$rp += 4;
$header = unpack('a4name',$read);
switch ($header['name']) {
case 'hdrl':
case 'strl':
case 'INFO':
while ($rp < $this->size) {
$read = $bytes ? substr($bytes,$rp,8) : fread($fh,8);
$rp += 8;
$header = unpack('a4name/Vsize',$read);
// We cant have a php function named 'list', so we change it to rlist
if ($header['name'] === 'LIST')
$header['name'] = 'RLIST';
$class = self::container_classes.$header['name'];
$data = $bytes
? substr($bytes,$rp,$header['size'])
: ($header['size'] && ($header['size'] <= self::record_size) ? fread($fh,$header['size']) : NULL);
if ($header['size']) {
$o = class_exists($class)
? new $class($this->offset+$rp,$header['size'],$this->filename,$this->be,$data)
: new Unknown($this->offset+$rp,$header['size'],$this->filename,$header['name'],$this->be,$data);
$result->push($o);
$rp += $header['size'];
// Only need to seek if we didnt read all the data
if ((! $bytes) && ($header['size'] > self::record_size))
fseek($fh,$this->offset+$rp);
} else {
dd([get_class($this) => $data,'header'=>$header,'ptr'=>$rp,'size'=>$this->size,'bytes'=>$bytes]);
}
}
break;
case 'movi':
$result->push(new movi($this->offset,$this->size,$this->filename,$this->be));
break;
default:
throw new \Exception('Unhandled header type: '.$header['name']);
}
if (! $bytes) {
fclose($fh);
unset($fh);
}
return $result;
}
}