Skip to content

Commit

Permalink
Merge pull request #363 from StudioMaX/asf-guids
Browse files Browse the repository at this point in the history
[ASF] Improve support of Header Extension Object data
  • Loading branch information
JamesHeinrich authored Dec 28, 2021
2 parents 341d335 + 06382ae commit a461450
Showing 1 changed file with 157 additions and 7 deletions.
164 changes: 157 additions & 7 deletions getid3/module.audio-video.asf.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@

class getid3_asf extends getid3_handler
{
protected static $ASFIndexParametersObjectIndexSpecifiersIndexTypes = array(
1 => 'Nearest Past Data Packet',
2 => 'Nearest Past Media Object',
3 => 'Nearest Past Cleanpoint'
);

protected static $ASFMediaObjectIndexParametersObjectIndexSpecifiersIndexTypes = array(
1 => 'Nearest Past Data Packet',
2 => 'Nearest Past Media Object',
3 => 'Nearest Past Cleanpoint',
0xFF => 'Frame Number Offset'
);

protected static $ASFTimecodeIndexParametersObjectIndexSpecifiersIndexTypes = array(
2 => 'Nearest Past Media Object',
3 => 'Nearest Past Cleanpoint'
);

/**
* @param getID3 $getid3
*/
Expand Down Expand Up @@ -1581,8 +1599,9 @@ public static function KnownGUIDs() {
'GETID3_ASF_Audio_Media' => 'F8699E40-5B4D-11CF-A8FD-00805F5C442B',
'GETID3_ASF_Media_Object_Index_Object' => 'FEB103F8-12AD-4C64-840F-2A1D2F7AD48C',
'GETID3_ASF_Alt_Extended_Content_Encryption_Obj' => 'FF889EF1-ADEE-40DA-9E71-98704BB928CE',
'GETID3_ASF_Index_Placeholder_Object' => 'D9AADE20-7C17-4F9C-BC28-8555DD98E2A2', // http://cpan.uwinnipeg.ca/htdocs/Audio-WMA/Audio/WMA.pm.html
'GETID3_ASF_Compatibility_Object' => '26F18B5D-4584-47EC-9F5F-0E651F0452C9', // http://cpan.uwinnipeg.ca/htdocs/Audio-WMA/Audio/WMA.pm.html
'GETID3_ASF_Index_Placeholder_Object' => 'D9AADE20-7C17-4F9C-BC28-8555DD98E2A2', // https://metacpan.org/dist/Audio-WMA/source/WMA.pm
'GETID3_ASF_Compatibility_Object' => '26F18B5D-4584-47EC-9F5F-0E651F0452C9', // https://metacpan.org/dist/Audio-WMA/source/WMA.pm
'GETID3_ASF_Media_Object_Index_Parameters_Object'=> '6B203BAD-3F11-48E4-ACA8-D7613DE2CFA7',
);
return $GUIDarray;
}
Expand Down Expand Up @@ -1745,7 +1764,7 @@ public static function WMpictureTypeLookup($WMpictureType) {
* @return array
*/
public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) {
// http://msdn.microsoft.com/en-us/library/bb643323.aspx
// https://web.archive.org/web/20140419205228/http://msdn.microsoft.com/en-us/library/bb643323.aspx

$offset = 0;
$objectOffset = 0;
Expand Down Expand Up @@ -1809,8 +1828,8 @@ public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_dat
$thisObject['stream_language_id_index'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;

$thisObject['average_time_per_frame'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4));
$offset += 4;
$thisObject['average_time_per_frame'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 8));
$offset += 8;

$thisObject['stream_name_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
Expand All @@ -1827,7 +1846,7 @@ public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_dat
$streamName['stream_name_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;

$streamName['stream_name'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, $streamName['stream_name_length']));
$streamName['stream_name'] = substr($asf_header_extension_object_data, $offset, $streamName['stream_name_length']);
$offset += $streamName['stream_name_length'];

$thisObject['stream_names'][$i] = $streamName;
Expand All @@ -1849,14 +1868,48 @@ public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_dat
$payloadExtensionSystem['extension_system_info_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4));
$offset += 4;

$payloadExtensionSystem['extension_system_info_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, $payloadExtensionSystem['extension_system_info_length']));
$payloadExtensionSystem['extension_system_info'] = substr($asf_header_extension_object_data, $offset, $payloadExtensionSystem['extension_system_info_length']);
$offset += $payloadExtensionSystem['extension_system_info_length'];

$thisObject['payload_extension_systems'][$i] = $payloadExtensionSystem;
}

break;

case GETID3_ASF_Advanced_Mutual_Exclusion_Object:
$thisObject['exclusion_type'] = substr($asf_header_extension_object_data, $offset, 16);
$offset += 16;
$thisObject['exclusion_type_text'] = $this->BytestringToGUID($thisObject['exclusion_type']);

$thisObject['stream_numbers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;

for ($i = 0; $i < $thisObject['stream_numbers_count']; $i++) {
$thisObject['stream_numbers'][$i] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
}

break;

case GETID3_ASF_Stream_Prioritization_Object:
$thisObject['priority_records_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;

for ($i = 0; $i < $thisObject['priority_records_count']; $i++) {
$priorityRecord = array();

$priorityRecord['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;

$priorityRecord['flags_raw'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
$priorityRecord['flags']['mandatory'] = (bool) $priorityRecord['flags_raw'] & 0x00000001;

$thisObject['priority_records'][$i] = $priorityRecord;
}

break;

case GETID3_ASF_Padding_Object:
// padding, skip it
break;
Expand Down Expand Up @@ -1974,6 +2027,103 @@ public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_dat
}
break;

case GETID3_ASF_Index_Parameters_Object:
$thisObject['index_entry_time_interval'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4));
$offset += 4;

$thisObject['index_specifiers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;

for ($i = 0; $i < $thisObject['index_specifiers_count']; $i++) {
$indexSpecifier = array();

$indexSpecifier['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;

$indexSpecifier['index_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
$indexSpecifier['index_type_text'] = isset(static::$ASFIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']])
? static::$ASFIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']]
: 'invalid'
;

$thisObject['index_specifiers'][$i] = $indexSpecifier;
}

break;

case GETID3_ASF_Media_Object_Index_Parameters_Object:
$thisObject['index_entry_count_interval'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4));
$offset += 4;

$thisObject['index_specifiers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;

for ($i = 0; $i < $thisObject['index_specifiers_count']; $i++) {
$indexSpecifier = array();

$indexSpecifier['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;

$indexSpecifier['index_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
$indexSpecifier['index_type_text'] = isset(static::$ASFMediaObjectIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']])
? static::$ASFMediaObjectIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']]
: 'invalid'
;

$thisObject['index_specifiers'][$i] = $indexSpecifier;
}

break;

case GETID3_ASF_Timecode_Index_Parameters_Object:
// 4.11 Timecode Index Parameters Object (mandatory only if TIMECODE index is present in file, 0 or 1)
// Field name Field type Size (bits)
// Object ID GUID 128 // GUID for the Timecode Index Parameters Object - ASF_Timecode_Index_Parameters_Object
// Object Size QWORD 64 // Specifies the size, in bytes, of the Timecode Index Parameters Object. Valid values are at least 34 bytes.
// Index Entry Count Interval DWORD 32 // This value is ignored for the Timecode Index Parameters Object.
// Index Specifiers Count WORD 16 // Specifies the number of entries in the Index Specifiers list. Valid values are 1 and greater.
// Index Specifiers array of: varies //
// * Stream Number WORD 16 // Specifies the stream number that the Index Specifiers refer to. Valid values are between 1 and 127.
// * Index Type WORD 16 // Specifies the type of index. Values are defined as follows (1 is not a valid value):
// 2 = Nearest Past Media Object - indexes point to the closest data packet containing an entire video frame or the first fragment of a video frame
// 3 = Nearest Past Cleanpoint - indexes point to the closest data packet containing an entire video frame (or first fragment of a video frame) that is a key frame.
// Nearest Past Media Object is the most common value

$thisObject['index_entry_count_interval'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4));
$offset += 4;

$thisObject['index_specifiers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;

for ($i = 0; $i < $thisObject['index_specifiers_count']; $i++) {
$indexSpecifier = array();

$indexSpecifier['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;

$indexSpecifier['index_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
$indexSpecifier['index_type_text'] = isset(static::$ASFTimecodeIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']])
? static::$ASFTimecodeIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']]
: 'invalid'
;

$thisObject['index_specifiers'][$i] = $indexSpecifier;
}

break;

case GETID3_ASF_Compatibility_Object:
$thisObject['profile'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 1));
$offset += 1;

$thisObject['mode'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 1));
$offset += 1;

break;

default:
$unhandled_sections++;
if ($this->GUIDname($thisObject['guid_text'])) {
Expand Down

0 comments on commit a461450

Please sign in to comment.