Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /*
- * qtfaststart.php v0.1 by Valentin Schmidt
- * based on qt-faststart.c v0.2 by Mike Melanson (melanson@pcisys.net)
- *
- * This file is placed in the public domain. Use the program however you
- * see fit.
- *
- * This utility rearranges a Quicktime file such that the moov atom
- * is in front of the data, thus facilitating network streaming.
- *
- * Notes: Quicktime files can come in many configurations of top-level
- * atoms. This utility stipulates that the very last atom in the file needs
- * to be a moov atom. When given such a file, this utility will rearrange
- * the top-level atoms by shifting the moov atom from the back of the file
- * to the front, and patch the chunk offsets along the way. This utility
- * presently only operates on uncompressed moov atoms.
- */
- define('MOOV_ATOM', 'moov');
- define('FTYP_ATOM', 'ftyp');
- define('CMOV_ATOM', 'cmov');
- define('STCO_ATOM', 'stco');
- define('CO64_ATOM', 'co64');
- define('ATOM_PREAMBLE_SIZE', 8);
- define('COPY_BUFFER_SIZE', 1024);
- function
- BE_32($x, $offset=0){
- return
- (ord($x[$offset+0]) << 24) |
- (ord($x[$offset+1]) << 16) |
- (ord($x[$offset+2]) << 8) |
- (ord($x[$offset+3]));
- }
- function
- BE_64($x, $offset=0){
- return
- (ord($x[$offset+0]) << 56) |
- (ord($x[$offset+1]) << 48) |
- (ord($x[$offset+2]) << 40) |
- (ord($x[$offset+3]) << 32) |
- (ord($x[$offset+4]) << 24) |
- (ord($x[$offset+5]) << 16) |
- (ord($x[$offset+6]) << 8) |
- (ord($x[$offset+7]));
- }
- function
- status($s){
- echo $s.'<br />';
- }
- function
- qtfaststart($inputVideoFile, $outputVideoFile){
- $atom_offset = 0;
- $atom_type = '';
- $infile = fopen($inputVideoFile, "rb");
- if (!$infile) {
- return 0;
- }
- /* traverse through the atoms in the file to make sure that 'moov' is at the end */
- while (!feof($infile)) {
- if (($atom_bytes = fread($infile, ATOM_PREAMBLE_SIZE)) == FALSE) {
- break;
- }
- $atom_size = BE_32($atom_bytes, 0);
- $atom_type = substr($atom_bytes, 4, 4);
- /* keep ftyp atom */
- if ($atom_type == FTYP_ATOM) {
- $ftyp_atom_size = $atom_size;
- fseek($infile, -ATOM_PREAMBLE_SIZE, SEEK_CUR);
- $ftyp_atom = fread($infile, $ftyp_atom_size);
- $start_offset = ftell($infile);
- } else {
- /* 64-bit special case */
- if ($atom_size == 1) {
- if (($atom_bytes = fread($infile, ATOM_PREAMBLE_SIZE)) == FALSE) {
- break;
- }
- $atom_size = BE_64($atom_bytes, 0);
- fseek($infile, $atom_size - ATOM_PREAMBLE_SIZE * 2, SEEK_CUR);
- } else {
- fseek($infile, $atom_size - ATOM_PREAMBLE_SIZE, SEEK_CUR);
- }
- }
- $atom_offset += $atom_size;
- /* The atom header is 8 (or 16 bytes), if the atom size (which
- * includes these 8 or 16 bytes) is less than that, we won't be
- * able to continue scanning sensibly after this atom, so break. */
- if ($atom_size < 8) break;
- }
- if (
- $atom_type != MOOV_ATOM) {
- status("last atom in file was not a moov atom");
- fclose($infile);
- return 0;
- }
- /* moov atom was, in fact, the last atom in the chunk; load the whole moov atom */
- fseek($infile, -$atom_size, SEEK_END);
- $last_offset = ftell($infile);
- $moov_atom_size = $atom_size;
- if (($moov_atom = fread($infile, $moov_atom_size)) == FALSE) {
- fclose($infile);
- return 0;
- }
- /* this utility does not support compressed atoms yet, so disqualify
- * files with compressed QT atoms */
- if (substr($moov_atom, 12, 4) == CMOV_ATOM) {
- status("this utility does not support compressed moov atoms yet");
- fclose($infile);
- return 0;
- }
- /* close; will be re-opened later */
- fclose($infile);
- /* crawl through the moov chunk in search of stco or co64 atoms */
- for ($i = 4; $i < $moov_atom_size - 4; $i++) {
- $atom_type = substr($moov_atom, $i, 4);
- if ($atom_type == STCO_ATOM) {
- status(" patching stco atom");
- $atom_size = BE_32($moov_atom, $i - 4);
- if ($i + $atom_size - 4 > $moov_atom_size) {
- status(" bad atom size");
- return 0;
- }
- $offset_count = BE_32($moov_atom, $i + 8);
- for ($j = 0; $j < $offset_count; $j++) {
- $current_offset = BE_32($moov_atom, $i + 12 + $j * 4);
- $current_offset += $moov_atom_size;
- $moov_atom[$i + 12 + $j * 4 + 0] = chr( ($current_offset >> 24) & 0xFF);
- $moov_atom[$i + 12 + $j * 4 + 1] = chr( ($current_offset >> 16) & 0xFF);
- $moov_atom[$i + 12 + $j * 4 + 2] = chr( ($current_offset >> 8) & 0xFF);
- $moov_atom[$i + 12 + $j * 4 + 3] = chr( ($current_offset >> 0) & 0xFF);
- }
- $i += $atom_size - 4;
- } else if ($atom_type == CO64_ATOM) {
- status(" patching co64 atom");
- $atom_size = BE_32($moov_atom, $i - 4);
- if ($i + $atom_size - 4 > $moov_atom_size) {
- status(" bad atom size");
- return 0;
- }
- $offset_count = BE_32($moov_atom, $i + 8);
- for ($j = 0; $j < $offset_count; $j++) {
- $current_offset = BE_64($moov_atom, $i + 12 + $j * 8);
- $current_offset += $moov_atom_size;
- $moov_atom[$i + 12 + $j * 8 + 0] = chr( ($current_offset >> 56) & 0xFF);
- $moov_atom[$i + 12 + $j * 8 + 1] = chr( ($current_offset >> 48) & 0xFF);
- $moov_atom[$i + 12 + $j * 8 + 2] = chr( ($current_offset >> 40) & 0xFF);
- $moov_atom[$i + 12 + $j * 8 + 3] = chr( ($current_offset >> 32) & 0xFF);
- $moov_atom[$i + 12 + $j * 8 + 4] = chr( ($current_offset >> 24) & 0xFF);
- $moov_atom[$i + 12 + $j * 8 + 5] = chr( ($current_offset >> 16) & 0xFF);
- $moov_atom[$i + 12 + $j * 8 + 6] = chr( ($current_offset >> 8) & 0xFF);
- $moov_atom[$i + 12 + $j * 8 + 7] = chr( ($current_offset >> 0) & 0xFF);
- }
- $i += $atom_size - 4;
- }
- }
- /* re-open the input file and open the output file */
- $infile = fopen($inputVideoFile, "rb");
- if (!$infile) {
- return 0;
- }
- if (
- $start_offset > 0) { /* seek after ftyp atom */
- fseek($infile, $start_offset, SEEK_SET);
- $last_offset -= $start_offset;
- }
- $outfile = fopen($outputVideoFile, "wb");
- if (!$outfile) {
- fclose($infile);
- return 0;
- }
- /* dump the same ftyp atom */
- if ($ftyp_atom_size > 0) {
- status(" writing ftyp atom");
- if ((fwrite($outfile, $ftyp_atom, $ftyp_atom_size)) == FALSE) {
- fclose($infile);
- fclose($outfile);
- return 0;
- }
- }
- /* dump the new moov atom */
- status(" writing moov atom");
- if ((fwrite($outfile, $moov_atom, $moov_atom_size)) == FALSE) {
- fclose($infile);
- fclose($outfile);
- return 0;
- }
- /* copy the remainder of the infile, from offset 0 -> last_offset - 1 */
- status(" copying rest of file");
- while ($last_offset) {
- if ($last_offset > COPY_BUFFER_SIZE)
- $bytes_to_copy = COPY_BUFFER_SIZE;
- else
- $bytes_to_copy = $last_offset;
- if (($copy_buffer = fread($infile, $bytes_to_copy)) == FALSE) {
- fclose($infile);
- fclose($outfile);
- return 0;
- }
- if ((fwrite($outfile, $copy_buffer, $bytes_to_copy)) == FALSE) {
- fclose($infile);
- fclose($outfile);
- return 0;
- }
- $last_offset -= $bytes_to_copy;
- }
- fclose($infile);
- fclose($outfile);
- return 1;
- }
- ?>
Add Comment
Please, Sign In to add comment