<?php
/**
* SeekQuarry/Yioop --
* Open Source Pure PHP Search Engine, Crawler, and Indexer
*
* Copyright (C) 2009 - 2026 Chris Pollett chris@pollett.org
*
* LICENSE:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* END LICENSE
*
* @author Chris Pollett chris@pollett.org
* @license https://www.gnu.org/licenses/ GPL3
* @link https://www.seekquarry.com/
* @copyright 2009 - 2026
* @filesource
*
* This class reads the settings an MP4 or WebM keeps beside an H.264
* stream. A decoder needs them before it can read a frame.
*/
namespace seekquarry\yioop\library\av_processing;
/**
* AvcConfig holds the settings an MP4 or a WebM keeps beside an H.264
* stream, and reads them out of the bytes the container stored.
*/
final class AvcConfig
{
/**
* $sequence_settings stores the sequence settings, or nothing where there
* is none.
* @var string
*/
public ?string $sequence_settings = null;
/**
* $picture_settings stores the picture settings, or nothing where there is
* none.
* @var string
*/
public ?string $picture_settings = null;
/**
* $stream_unit_length_size stores how many bytes each unit's length
* field takes. An MP4 writes a length in front of every unit of
* the stream, and a decoder cannot find the next unit without
* knowing the width of that field.
* @var int
*/
public int $stream_unit_length_size = 4;
/**
* readSettings reads the settings an MP4 or a WebM keeps beside an H.264
* stream, and hands back what they say. A container calls this once, when
* it first meets the track, because a decoder cannot read a frame until it
* knows how long each unit's length field is and which sequence and picture
* settings the stream started with. them, from the version byte onward.
*
* @param string $payload The settings as the container stored
* @return self The settings, ready to hand to a decoder.
*/
public static function readSettings(string $payload): self
{
$count_value = new self();
if (strlen($payload) < 7 || ord($payload[0]) !== 1) {
return $count_value;
}
$count_value->stream_unit_length_size = (ord($payload[4]) & 0x03) + 1;
$sequence_setting_count = ord($payload[5]) & 0x1F;
$position = 6;
$number = strlen($payload);
for ($i = 0; $i < $sequence_setting_count && $position + 2 <=
$number; $i++) {
$length = unpack('n', substr($payload, $position, 2))[1];
$position += 2;
if ($i === 0) {
$count_value->sequence_settings = substr($payload,
$position, $length);
}
$position += $length;
}
if ($position >= $number) {
return $count_value;
}
$picture_setting_count = ord($payload[$position]);
$position++;
for ($i = 0; $i < $picture_setting_count && $position + 2 <=
$number; $i++) {
$length = unpack('n', substr($payload, $position, 2))[1];
$position += 2;
if ($i === 0) {
$count_value->picture_settings = substr($payload, $position,
$length);
}
$position += $length;
}
return $count_value;
}
}