mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-19 07:53:14 +00:00
809 lines
27 KiB
PHP
809 lines
27 KiB
PHP
<?php
|
|
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
|
|
|
/**
|
|
* Moovrelocator
|
|
*
|
|
* In H.264-based video formats (mp4, m4v) the metadata is called a "moov atom".
|
|
* The moov atom is a part of the file that holds the index information for the
|
|
* whole file. Many encoding software programs such as FFMPEG will insert this
|
|
* moov atom information at the end of the video file. This is bad. The moov atom
|
|
* needs to be located at the beginning of the file, or else the entire file will
|
|
* have to be downloaded before it begins playing
|
|
* (http://flowplayer.org/plugins/streaming/pseudostreaming.html).
|
|
*
|
|
* this source is based on sources and/or informations from the following sources:
|
|
*
|
|
* php-reader - http://code.google.com/p/php-reader/
|
|
* by Sven Vollbehr <sven@vollbehr.eu>
|
|
* [http://code.google.com/p/php-reader/people/detail?u=svollbehr]
|
|
*
|
|
* php-mp4info - http://code.google.com/p/php-mp4info/)
|
|
* by Tommy Lacroix <lacroix.tommy@gmail.com>
|
|
* [http://www.tommylacroix.com]
|
|
*
|
|
* QTIndexSwapper (Original Application) - http://renaun.com/air/QTIndexSwapper.air
|
|
* by Renaun Erickson (Adobe)
|
|
* [http://renaun.com]
|
|
*
|
|
* qt-faststart.c - http://cekirdek.pardus.org.tr/~ismail/ffmpeg-docs/qt-faststart_8c-source.html
|
|
* by Mike Melanson (Adobe) <melanson@pcisys.net>
|
|
* [http://blogs.adobe.com/penguin.swf/]
|
|
*
|
|
* PHP versions 5
|
|
*
|
|
* LICENSE: Moovrelocator - Copyright (c) 2009, Benjamin Carl -
|
|
* All rights reserved. Redistribution and use in source and binary forms, with
|
|
* or without modification, are permitted provided that the following conditions
|
|
* are met: Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer. * Redistributions in binary
|
|
* form must reproduce the above copyright notice, this list of conditions and the
|
|
* following disclaimer in the documentation and/or other materials provided with
|
|
* the distribution. * All advertising materials mentioning features or use of
|
|
* this software must display the following acknowledgement: This product includes
|
|
* software developed by Benjamin Carl and its contributors.
|
|
*
|
|
* Neither the name of Benjamin Carl nor the names of its contributors may be used
|
|
* to endorse or promote products derived from this software without specific prior
|
|
* written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
* Please feel free to contact us via e-mail: phpfluesterer@googlemail.com
|
|
*
|
|
* @category Moovrelocator
|
|
* @package Moovrelocator_Lib
|
|
* @subpackage Moovrelocator_Lib_Base
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @copyright 2009 Benjamin Carl
|
|
* @license http://www.opensource.org/licenses/bsd-license.php The BSD License
|
|
* @version SVN: $Id: Moovrelocator.class.php 2 2010-01-25 01:01:16Z phpfluesterer $
|
|
* @link http://www.benjamin-carl.de
|
|
* @see -
|
|
* @since File available since Release 1.0.0
|
|
*/
|
|
|
|
// get absolute path to this lib
|
|
define('PATH_MOOVRELOCATOR', str_replace($_SERVER['DOCUMENT_ROOT'], "", dirname(realpath(__FILE__))).DIRECTORY_SEPARATOR);
|
|
|
|
// atom poc class
|
|
//require_once PATH_MOOVRELOCATOR.'atom'.DIRECTORY_SEPARATOR.'Atom.class.php';
|
|
|
|
// bytearray to operate direct on bytes in memory just to simulate Adobe's AS3 Bytearray
|
|
//require_once PATH_MOOVRELOCATOR.'bytes'.DIRECTORY_SEPARATOR.'Bytearray.class.php';
|
|
|
|
// transform (taken from php-reader)
|
|
//require_once PATH_MOOVRELOCATOR.'bytes'.DIRECTORY_SEPARATOR.'Transform.class.php';
|
|
|
|
/**
|
|
* Moovrelocator
|
|
*
|
|
* MOOV Relocator is a well documented small library written in PHP to relocate (or move)
|
|
* the MOOV-Atom of MP4-Files from the end to the beginning of a file.
|
|
*
|
|
* @category Moovrelocator
|
|
* @package Moovrelocator_Lib
|
|
* @subpackage Moovrelocator_Lib_Base
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @copyright 2009 Benjamin Carl
|
|
* @license http://www.opensource.org/licenses/bsd-license.php The BSD License
|
|
* @version Release: @package_version@
|
|
* @link http://www.benjamin-carl.de
|
|
* @see -
|
|
* @since File available since Release 1.0.0
|
|
*/
|
|
class moov_relocator
|
|
{
|
|
/**
|
|
* holds the singleton instance of this class
|
|
*
|
|
* @var object
|
|
* @access private
|
|
*/
|
|
private static $_instance = null;
|
|
|
|
/**
|
|
* the file for output the fixed data
|
|
*
|
|
* @var string
|
|
* @access private
|
|
*/
|
|
private $_outputFile = false;
|
|
|
|
/**
|
|
* holds the size of inputfile in bytes
|
|
*
|
|
* @var integer
|
|
* @access private
|
|
*/
|
|
private $_filesize = 0;
|
|
|
|
/**
|
|
* holds the reference (file-handle) to file (input)
|
|
*
|
|
* @var integer
|
|
* @access private
|
|
*/
|
|
private $_fp = false;
|
|
|
|
/**
|
|
* holds the bytes of ftyp
|
|
* (instance of Bytearray)
|
|
*
|
|
* @var object
|
|
* @access private
|
|
*/
|
|
private $_ftypBytes;
|
|
|
|
/**
|
|
* holds the bytes of moov
|
|
* (instance of Bytearray)
|
|
*
|
|
* @var object
|
|
* @access private
|
|
*/
|
|
private $_moovBytes;
|
|
|
|
/**
|
|
* holds the bytes between fytp and moov
|
|
* (instance of Bytearray)
|
|
*
|
|
* @var object
|
|
* @access private
|
|
*/
|
|
private $_middleBytes;
|
|
|
|
/**
|
|
* holds the files atoms/boxes
|
|
*
|
|
* @var array
|
|
* @access private
|
|
*/
|
|
private $_fileAtoms = array();
|
|
|
|
/**
|
|
* holds the last processed atom/box
|
|
*
|
|
* @var object
|
|
* @access private
|
|
*/
|
|
private $_lastAtom = null;
|
|
|
|
/**
|
|
* holds the file-parsing-status
|
|
*
|
|
* @var boolean
|
|
* @access private
|
|
*/
|
|
private $_successfullyParsed = false;
|
|
|
|
/**
|
|
* holds the file-parsing-status
|
|
*
|
|
* @var boolean
|
|
* @access private
|
|
*/
|
|
private $_fileValid = null;
|
|
|
|
|
|
/**
|
|
* sets the input file to process
|
|
*
|
|
* this method sets the input file
|
|
*
|
|
* @param string $filename The input file to fix
|
|
*
|
|
* @return mixed The error-message (string) if opening the inputfile failed, otherwise TRUE
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
* @access public
|
|
*/
|
|
public function setInput($filename = null)
|
|
{
|
|
// check and open file
|
|
|
|
$this->closeFile();
|
|
|
|
if (!file_exists($filename) || !($this->_fp = fopen($filename, 'rb'))) {
|
|
return 'cannot open file: '.$filename;
|
|
}
|
|
|
|
// get size of file
|
|
$this->_filesize = filesize($filename);
|
|
|
|
// empty file?
|
|
if ($this->_filesize == 0) {
|
|
return 'file '.$filename.' seems to be empyt!';
|
|
}
|
|
|
|
// parse file's atoms
|
|
while (!feof($this->_fp) && ftell($this->_fp) < $this->_filesize) {
|
|
$this->_fileAtoms[] = $this->_parseAtomsFromInput();
|
|
}
|
|
|
|
$moovEOFCheck = $this->_moovAtomAtEOF();
|
|
if ($moovEOFCheck !== true) {
|
|
return $moovEOFCheck;
|
|
} else {
|
|
// successful parsed the file!
|
|
$this->_successfullyParsed = true;
|
|
}
|
|
|
|
// success
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* parse atoms / just parse and store / no check
|
|
*
|
|
* parse atoms / just parse and store / no check
|
|
*
|
|
* @return object An object of type Atom
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
* @access private
|
|
*/
|
|
private function _parseAtomsFromInput()
|
|
{
|
|
// reset file stream pointer to position of the lastAtom.offset + size
|
|
if ((isset($this->_fileAtoms[count($this->_fileAtoms) - 1]))) {
|
|
$lastAtom = $this->_fileAtoms[count($this->_fileAtoms) - 1];
|
|
$position = $lastAtom->getSize() + $lastAtom->getOffset();
|
|
if (ftell($this->_fp) <= $position) {
|
|
fseek($this->_fp, $position);
|
|
}
|
|
}
|
|
|
|
// get 8 bytes -> get totalSize and boxType
|
|
$atomData = unpack('NtotalSize/NboxType', fread($this->_fp, 8));
|
|
// store offset, size and type
|
|
$offset = ftell($this->_fp) - 8;
|
|
$size = $atomData['totalSize'];
|
|
$type = pack('N', $atomData['boxType']);
|
|
|
|
// check 64 bit size (files > 4GB)
|
|
if ($size == 1) {
|
|
$highInt = $atomData['totalSize'];
|
|
$size = ($highInt << 32) | $atomData['totalSize'];
|
|
}
|
|
|
|
// positioning of file-pointer
|
|
fseek($this->_fp, ($size + $offset));
|
|
|
|
// give back atom
|
|
return self::factory($offset, $size, $type);
|
|
}
|
|
|
|
|
|
/**
|
|
* checks for valid qt-file
|
|
*
|
|
* checks for valid qt-file
|
|
*
|
|
* @return boolean True if everything wents fine, otherwise false
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
* @access private
|
|
*/
|
|
private function _isValidQTFile()
|
|
{
|
|
// check if file was succesfully parsed
|
|
if (!$this->_successfullyParsed) {
|
|
return 'please open a file first!';
|
|
}
|
|
|
|
// get first atom
|
|
$firstAtom = $this->_fileAtoms[0];
|
|
|
|
// check first for being valid (first atom MUST be ftyp)
|
|
if ($firstAtom->getType() != moov_relocator_atom::FTYP_ATOM) {
|
|
$this->_fileValid = false;
|
|
return 'encountered non-QT top-level atom (is this a Quicktime file?)';
|
|
}
|
|
|
|
// check last for being valid
|
|
$lastAtom = $this->_fileAtoms[count($this->_fileAtoms) - 1];
|
|
|
|
if (!moov_relocator_atom::isValidAtom($lastAtom->getType())) {
|
|
$this->_fileValid = false;
|
|
return 'encountered non-QT top-level atom (is this a Quicktime file?';
|
|
}
|
|
|
|
// store validity
|
|
return $this->_fileValid = true;
|
|
}
|
|
|
|
|
|
/**
|
|
* check moov atoms position
|
|
*
|
|
* check moov atoms position
|
|
*
|
|
* @return mixed True if everything wents fine, otherwise string error-message
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
* @access private
|
|
*/
|
|
private function _moovAtomAtEOF()
|
|
{
|
|
if ($this->_fileAtoms[count($this->_fileAtoms) - 1]->getType() != moov_relocator_atom::MOOV_ATOM) {
|
|
return 'The moov-atom isn\'t located at the end of the file, the file is allready ready for progressive download or it is a invalid file';
|
|
}
|
|
|
|
// moov is at end of file...
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* set output file
|
|
*
|
|
* set output file
|
|
*
|
|
* @param string $filename The filename ( + path) to put result (fixed data) in
|
|
*
|
|
* @return boolean True if everything wents fine, otherwise false
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
* @access public
|
|
*/
|
|
public function setOutput($filename)
|
|
{
|
|
// store filename
|
|
$this->_outputFile = $filename;
|
|
|
|
// success
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* input, output and fix call - shortcut
|
|
*
|
|
* input, output and fix call - shortcut
|
|
*
|
|
* @param string $filename The input filename
|
|
* @param string $outputFilename The output filename
|
|
* @param boolean $overwrite The overwrite status
|
|
*
|
|
* @return mixed True if everything wents fine, otherwise error-message as string
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
* @access public
|
|
*/
|
|
public function relocateMoovAtom($filename, $outputFilename = null, $overwrite = false)
|
|
{
|
|
// read file, preprocess (parse atoms/boxes)
|
|
$result = $this->setInput($filename);
|
|
if ($result !== true) {
|
|
return $result;
|
|
}
|
|
|
|
if (is_null($outputFilename) && $overwrite === true) {
|
|
$fileResult = $filename;
|
|
} else {
|
|
$fileResult = $outputFilename;
|
|
}
|
|
|
|
// set the output filename and path
|
|
$result = $this->setOutput($fileResult);
|
|
if ($result !== true) {
|
|
return $result;
|
|
}
|
|
|
|
// moov positioning fix
|
|
$result = $this->fix();
|
|
if ($result !== true) {
|
|
return $result;
|
|
}
|
|
|
|
// success
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* fix moov-atom location
|
|
*
|
|
* fix moov-atom location
|
|
*
|
|
* @return mixed True if everything wents fine, otherwise error-message as string
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
* @access public
|
|
*/
|
|
public function fix()
|
|
{
|
|
// check if file was succesfully parsed
|
|
if (!$this->_successfullyParsed) {
|
|
return 'please open a file first! (syntax: '.__CLASS__.'->setInput($filename);)';
|
|
}
|
|
|
|
if (!$this->_outputFile) {
|
|
return 'please set an outputfile first! (syntax: '.__CLASS__.'->setOutput($file);)';
|
|
}
|
|
|
|
// check if moov atom is allready at beginning of file
|
|
if (!$this->_moovAtomAtEOF()) {
|
|
return 'nothing to do! moov allready at begin of file!';
|
|
}
|
|
|
|
// Bytearray's holding bytes from file
|
|
$this->_ftypBytes = new moov_relocator_bytearray();
|
|
$this->_middleBytes = new moov_relocator_bytearray();
|
|
$this->_moovBytes = new moov_relocator_bytearray();
|
|
|
|
// read in file's bytes
|
|
$result = $this->_readBytes();
|
|
if ($result !== true) {
|
|
return $result;
|
|
}
|
|
|
|
// now start swapping
|
|
$result = $this->_swapIndex();
|
|
if ($result !== true) {
|
|
return $result;
|
|
}
|
|
|
|
// write new file
|
|
$result = $this->_writeFile();
|
|
if ($result !== true) {
|
|
return $result;
|
|
}
|
|
|
|
// everythings fine!
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* reads all bytes from all found atoms
|
|
*
|
|
* reads all bytes from all found atoms
|
|
*
|
|
* @return mixed True if everything wents fine, otherwise error-message as string
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
* @access private
|
|
*/
|
|
private function _readBytes()
|
|
{
|
|
// read bytes from all found atoms
|
|
for ($atom = 0; $atom < count($this->_fileAtoms); $atom++) {
|
|
|
|
// get the current atom/box
|
|
$currentAtom = $this->_fileAtoms[$atom];
|
|
$currentAtomType = $currentAtom->getType();
|
|
|
|
// keep ftyp atom
|
|
if ($currentAtomType == moov_relocator_atom::FTYP_ATOM) {
|
|
// set file pointer to begin of file
|
|
fseek($this->_fp, 0);
|
|
$bytes = fread($this->_fp, $currentAtom->getSize());
|
|
$this->_ftypBytes->writeBytes($bytes);
|
|
|
|
} else if ($currentAtomType == moov_relocator_atom::MOOV_ATOM) {
|
|
$bytes = fread($this->_fp, $currentAtom->getSize());
|
|
$this->_moovBytes->writeBytes($bytes);
|
|
|
|
} else {
|
|
$bytes = fread($this->_fp, $currentAtom->getSize());
|
|
$this->_middleBytes->writeBytes($bytes);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* swaps the index from end to beginning
|
|
*
|
|
* swaps the index from end to beginning
|
|
*
|
|
* @return mixed True if everything wents fine, otherwise error-message as string
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
* @access private
|
|
*/
|
|
private function _swapIndex()
|
|
{
|
|
$moovSize = $this->_moovBytes->bytesAvailable();
|
|
|
|
$moovAType = '';
|
|
$moovASize = 0;
|
|
$offsetCount = 0;
|
|
|
|
$compressionCheck = $this->_moovBytes->readBytes(12, 4);
|
|
|
|
if ($compressionCheck == moov_relocator_atom::CMOV_ATOM) {
|
|
throw new Exception('compressed MP4/QT-file can\'t do this file: '.$file);
|
|
}
|
|
|
|
// begin of metadata
|
|
$metaDataOffsets = array();
|
|
$metaDataStrings = array();
|
|
$metaDataCurrentLevel = 0;
|
|
|
|
$moovStartOffset = 12;
|
|
|
|
for ($i = $moovStartOffset; $i < $moovSize - $moovStartOffset; $i++) {
|
|
$moovAType = $this->_moovBytes->readUTFBytes($i, 4);
|
|
|
|
if (moov_relocator_atom::isValidAtom($moovAType)) {
|
|
|
|
$moovASize = $this->_moovBytes->readUnsignedInt($i - 4);
|
|
|
|
if (($moovASize > 8) && ($moovASize + $i < ($moovSize - $moovStartOffset))) {
|
|
|
|
try {
|
|
$containerLength = 0;
|
|
$containerString = $moovAType;
|
|
|
|
for ($mi = count($metaDataOffsets) - 1; $mi > - 1; $mi--) {
|
|
|
|
$containerLength = $metaDataOffsets[$mi];
|
|
|
|
if ($i - $moovStartOffset < $containerLength && $i - $moovStartOffset + $moovASize > $containerLength) {
|
|
throw new Exception('bad atom nested size');
|
|
}
|
|
|
|
if ($i - $moovStartOffset == $containerLength) {
|
|
array_pop($metaDataOffsets);
|
|
array_pop($metaDataStrings);
|
|
} else {
|
|
$containerString = $metaDataStrings[$mi].".".$containerString;
|
|
}
|
|
}
|
|
|
|
if (($i - $moovStartOffset) <= $containerLength) {
|
|
array_push($metaDataOffsets, ($i - $moovStartOffset + $moovASize));
|
|
array_push($metaDataStrings, $moovAType);
|
|
}
|
|
|
|
if ($moovAType != moov_relocator_atom::STCO_ATOM && $moovAType != moov_relocator_atom::CO64_ATOM) {
|
|
$i += 4;
|
|
} elseif ($moovAType == moov_relocator_atom::URL_ATOM || $moovAType == moov_relocator_atom::XML_ATOM) {
|
|
$i += $moovASize - 4;
|
|
}
|
|
}
|
|
catch(Exception $e) {
|
|
echo 'EXCEPTION: '.$e->getMessage();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if ($moovAType == moov_relocator_atom::STCO_ATOM) {
|
|
$moovASize = $this->_moovBytes->readUnsignedInt($i - 4);
|
|
|
|
if ($i + $moovASize - $moovStartOffset > $moovSize) {
|
|
throw new Exception('bad atom size');
|
|
return;
|
|
}
|
|
|
|
$offsetCount = $this->_moovBytes->readUnsignedInt($i + 8);
|
|
|
|
for ($j = 0; $j < $offsetCount; $j++) {
|
|
$position = ($i + 12 + $j * 4);
|
|
|
|
$currentOffset = $this->_moovBytes->readUnsignedInt($position);
|
|
|
|
// cause of mooving the moov-atom right before the rest of data
|
|
// (behind ftyp) the new offset is caluclated:
|
|
// current-offset + size of moov atom (box) = new offset
|
|
$currentOffset += $moovSize;
|
|
|
|
$this->_moovBytes->writeBytes(moov_relocator_transform::toUInt32BE($currentOffset), $position + 1);
|
|
}
|
|
$i += $moovASize - 4;
|
|
|
|
} else if ($moovAType == moov_relocator_atom::CO64_ATOM) {
|
|
$moovASize = $this->_moovBytes->readUnsignedInt($i - 4);
|
|
|
|
if ($i + $moovASize - $moovStartOffset > $moovSize) {
|
|
throw new Exception('bad atom size');
|
|
return;
|
|
}
|
|
|
|
$offsetCount = $this->_moovBytes->readDouble($i + 8);
|
|
|
|
for ($j2 = 0; $j2 < $offsetCount; $j2++) {
|
|
$position = ($i + 12 + $j * 8);
|
|
|
|
$currentOffset = $this->_moovBytes->readUnsignedInt($position);
|
|
|
|
// cause of mooving the moov-atom right before the rest of data
|
|
// (behind ftyp) the new offset is caluclated:
|
|
// current-offset + size of moov atom (box) = new offset
|
|
$currentOffset += $moovSize;
|
|
|
|
// TODO implement!
|
|
//$this->_moovBytes->writeBytes(Transform::toUInt64BE($currentOffset), $position+1);
|
|
}
|
|
$i += $moovASize - 4;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* write the new byteorder to a new file
|
|
*
|
|
* write the new byteorder to a new file
|
|
*
|
|
* @return mixed True if everything wents fine, otherwise error-message as string
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
* @access private
|
|
*/
|
|
private function _writeFile()
|
|
{
|
|
// check if we need to unlink exisiting outputfile
|
|
if (file_exists($this->_outputFile)) {
|
|
|
|
// close handle
|
|
if ($this->_fp) {
|
|
@fclose($this->_fp);
|
|
$this->_fp = null;
|
|
}
|
|
|
|
if (!@unlink($this->_outputFile)) {
|
|
return 'error deleting file: '.$this->_outputFile.' outputfile "'.$this->_outputFile.'" exists (overwite = true)!';
|
|
}
|
|
}
|
|
|
|
// open predefined output file
|
|
if (!$fh = fopen($this->_outputFile, 'wb+')) {
|
|
return 'error opening outputfile: '.$this->_outputFile.' for wb+ access!';
|
|
}
|
|
|
|
// put ftyp atom/box in
|
|
if (!fwrite($fh, $this->_ftypBytes->readAllBytes())) {
|
|
return 'error writing ftyp-atom to outputfile: '.$this->_outputFile;
|
|
}
|
|
|
|
// put moov atom in
|
|
if (!fwrite($fh, $this->_moovBytes->readAllBytes())) {
|
|
return 'error writing moov-atom to outputfile: '.$this->_outputFile;
|
|
}
|
|
|
|
// put rest data in
|
|
if (!fwrite($fh, $this->_middleBytes->readAllBytes())) {
|
|
return 'error writing other atom(s) to outputfile: '.$this->_outputFile;
|
|
}
|
|
|
|
// close handle
|
|
fclose($fh);
|
|
|
|
// everything's fine
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* factory for creating atom object instances
|
|
*
|
|
* factory for creating atom object instances
|
|
*
|
|
* @param integer $offset The offset of the atom (in bytes)
|
|
* @param integer $size The size of the atom (in bytes)
|
|
* @param string $type The type of the atom
|
|
*
|
|
* @return object An instance of the Atom-class
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
* @access public
|
|
*/
|
|
public static function factory($offset, $size, $type)
|
|
{
|
|
// instanciate a new atom-object
|
|
$atom = new moov_relocator_atom();
|
|
|
|
// setup ...
|
|
$atom->setOffset($offset);
|
|
$atom->setSize($size);
|
|
$atom->setType($type);
|
|
|
|
// and give back ...
|
|
return $atom;
|
|
}
|
|
|
|
|
|
/**
|
|
* instance singleton requester
|
|
*
|
|
* method for singleton instantiation of this class
|
|
*
|
|
* @return moov_relocator
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
* @access public
|
|
*/
|
|
public static function getInstance()
|
|
{
|
|
if (is_null(self::$_instance)) {
|
|
self::$_instance = new self();
|
|
}
|
|
return self::$_instance;
|
|
}
|
|
|
|
|
|
/**
|
|
* prevents cloning of the class
|
|
*
|
|
* this method prevents the cloning of a class - but can be overridden by
|
|
* child
|
|
*
|
|
* @return void
|
|
* @access private
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
*/
|
|
private function __clone()
|
|
{
|
|
// empty container
|
|
}
|
|
|
|
|
|
/**
|
|
* gets called on garbage collecting (object destroyed)
|
|
*
|
|
* destruct method - gets called when instance of this class get
|
|
* collected from garbage collector. close the open filehandel on
|
|
* destruction.
|
|
*
|
|
* @return void
|
|
* @access public
|
|
* @author Benjamin Carl <phpfluesterer@googlemail.com>
|
|
* @version 0.1
|
|
* @since Method available since Release 0.1
|
|
*/
|
|
public function __destruct()
|
|
{
|
|
// close handle
|
|
$this->closeFile();
|
|
}
|
|
|
|
private function closeFile()
|
|
{
|
|
$this->_fileAtoms = array();
|
|
|
|
$this->_lastAtom = null;
|
|
|
|
$this->_successfullyParsed = false;
|
|
|
|
$this->_fileValid = null;
|
|
|
|
if ($this->_fp) {
|
|
@fclose($this->_fp);
|
|
}
|
|
}
|
|
}
|
|
|
|
?>
|