getid3_asf::BytestringToGUID()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 21
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 24
rs 9.584
1
<?php
2
// +----------------------------------------------------------------------+
3
// | PHP version 5                                                        |
4
// +----------------------------------------------------------------------+
5
// | Copyright (c) 2002-2006 James Heinrich, Allan Hansen                 |
6
// +----------------------------------------------------------------------+
7
// | This source file is subject to version 2 of the GPL license,         |
8
// | that is bundled with this package in the file license.txt and is     |
9
// | available through the world-wide-web at the following url:           |
10
// | http://www.gnu.org/copyleft/gpl.html                                 |
11
// +----------------------------------------------------------------------+
12
// | getID3() - http://getid3.sourceforge.net or http://www.getid3.org    |
13
// +----------------------------------------------------------------------+
14
// | Authors: James Heinrich <info�getid3*org>                            |
15
// |          Allan Hansen <ah�artemis*dk>                                |
16
// +----------------------------------------------------------------------+
17
// | module.audio-video.php                                               |
18
// | Module for analyzing Microsoft ASF, WMA and WMV files.               |
19
// | dependencies: module.audio-video.riff.php                            |
20
// +----------------------------------------------------------------------+
21
//
22
// $Id: module.audio-video.asf.php,v 1.7 2006/12/01 22:39:48 ah Exp $
23
24
class getid3_asf extends getid3_handler
25
{
26
27
    const Extended_Stream_Properties_Object = '14E6A5CB-C672-4332-8399-A96952065B5A';
28
    const Padding_Object = '1806D474-CADF-4509-A4BA-9AABCB96AAE8';
29
    const Payload_Ext_Syst_Pixel_Aspect_Ratio = '1B1EE554-F9EA-4BC8-821A-376B74E4C4B8';
30
    const Script_Command_Object = '1EFB1A30-0B62-11D0-A39B-00A0C90348F6';
31
    const No_Error_Correction = '20FB5700-5B55-11CF-A8FD-00805F5C442B';
32
    const Content_Branding_Object = '2211B3FA-BD23-11D2-B4B7-00A0C955FC6E';
33
    const Content_Encryption_Object = '2211B3FB-BD23-11D2-B4B7-00A0C955FC6E';
34
    const Digital_Signature_Object = '2211B3FC-BD23-11D2-B4B7-00A0C955FC6E';
35
    const Extended_Content_Encryption_Object = '298AE614-2622-4C17-B935-DAE07EE9289C';
36
    const Simple_Index_Object = '33000890-E5B1-11CF-89F4-00A0C90349CB';
37
    const Degradable_JPEG_Media = '35907DE0-E415-11CF-A917-00805F5C442B';
38
    const Payload_Extension_System_Timecode = '399595EC-8667-4E2D-8FDB-98814CE76C1E';
39
    const Binary_Media = '3AFB65E2-47EF-40F2-AC2C-70A90D71D343';
40
    const Timecode_Index_Object = '3CB73FD0-0C4A-4803-953D-EDF7B6228F0C';
41
    const Metadata_Library_Object = '44231C94-9498-49D1-A141-1D134E457054';
42
    const Reserved_3 = '4B1ACBE3-100B-11D0-A39B-00A0C90348F6';
43
    const Reserved_4 = '4CFEDB20-75F6-11CF-9C0F-00A0C90349CB';
44
    const Command_Media = '59DACFC0-59E6-11D0-A3AC-00A0C90348F6';
45
    const Header_Extension_Object = '5FBF03B5-A92E-11CF-8EE3-00C00C205365';
46
    const Media_Object_Index_Parameters_Obj = '6B203BAD-3F11-4E84-ACA8-D7613DE2CFA7';
47
    const Header_Object = '75B22630-668E-11CF-A6D9-00AA0062CE6C';
48
    const Content_Description_Object = '75B22633-668E-11CF-A6D9-00AA0062CE6C';
49
    const Error_Correction_Object = '75B22635-668E-11CF-A6D9-00AA0062CE6C';
50
    const Data_Object = '75B22636-668E-11CF-A6D9-00AA0062CE6C';
51
    const Web_Stream_Media_Subtype = '776257D4-C627-41CB-8F81-7AC7FF1C40CC';
52
    const Stream_Bitrate_Properties_Object = '7BF875CE-468D-11D1-8D82-006097C9A2B2';
53
    const Language_List_Object = '7C4346A9-EFE0-4BFC-B229-393EDE415C85';
54
    const Codec_List_Object = '86D15240-311D-11D0-A3A4-00A0C90348F6';
55
    const Reserved_2 = '86D15241-311D-11D0-A3A4-00A0C90348F6';
56
    const File_Properties_Object = '8CABDCA1-A947-11CF-8EE4-00C00C205365';
57
    const File_Transfer_Media = '91BD222C-F21C-497A-8B6D-5AA86BFC0185';
58
    const Old_RTP_Extension_Data = '96800C63-4C94-11D1-837B-0080C7A37F95';
59
    const Advanced_Mutual_Exclusion_Object = 'A08649CF-4775-4670-8A16-6E35357566CD';
60
    const Bandwidth_Sharing_Object = 'A69609E6-517B-11D2-B6AF-00C04FD908E9';
61
    const Reserved_1 = 'ABD3D211-A9BA-11CF-8EE6-00C00C205365';
62
    const Bandwidth_Sharing_Exclusive = 'AF6060AA-5197-11D2-B6AF-00C04FD908E9';
63
    const Bandwidth_Sharing_Partial = 'AF6060AB-5197-11D2-B6AF-00C04FD908E9';
64
    const JFIF_Media = 'B61BE100-5B4E-11CF-A8FD-00805F5C442B';
65
    const Stream_Properties_Object = 'B7DC0791-A9B7-11CF-8EE6-00C00C205365';
66
    const Video_Media = 'BC19EFC0-5B4D-11CF-A8FD-00805F5C442B';
67
    const Audio_Spread = 'BFC3CD50-618F-11CF-8BB2-00AA00B4E220';
68
    const Metadata_Object = 'C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA';
69
    const Payload_Ext_Syst_Sample_Duration = 'C6BD9450-867F-4907-83A3-C77921B733AD';
70
    const Group_Mutual_Exclusion_Object = 'D1465A40-5A79-4338-B71B-E36B8FD6C249';
71
    const Extended_Content_Description_Object = 'D2D0A440-E307-11D2-97F0-00A0C95EA850';
72
    const Stream_Prioritization_Object = 'D4FED15B-88D3-454F-81F0-ED5C45999E24';
73
    const Payload_Ext_System_Content_Type = 'D590DC20-07BC-436C-9CF7-F3BBFBF1A4DC';
74
    const Old_File_Properties_Object = 'D6E229D0-35DA-11D1-9034-00A0C90349BE';
75
    const Old_ASF_Header_Object = 'D6E229D1-35DA-11D1-9034-00A0C90349BE';
76
    const Old_ASF_Data_Object = 'D6E229D2-35DA-11D1-9034-00A0C90349BE';
77
    const Index_Object = 'D6E229D3-35DA-11D1-9034-00A0C90349BE';
78
    const Old_Stream_Properties_Object = 'D6E229D4-35DA-11D1-9034-00A0C90349BE';
79
    const Old_Content_Description_Object = 'D6E229D5-35DA-11D1-9034-00A0C90349BE';
80
    const Old_Script_Command_Object = 'D6E229D6-35DA-11D1-9034-00A0C90349BE';
81
    const Old_Marker_Object = 'D6E229D7-35DA-11D1-9034-00A0C90349BE';
82
    const Old_Component_Download_Object = 'D6E229D8-35DA-11D1-9034-00A0C90349BE';
83
    const Old_Stream_Group_Object = 'D6E229D9-35DA-11D1-9034-00A0C90349BE';
84
    const Old_Scalable_Object = 'D6E229DA-35DA-11D1-9034-00A0C90349BE';
85
    const Old_Prioritization_Object = 'D6E229DB-35DA-11D1-9034-00A0C90349BE';
86
    const Bitrate_Mutual_Exclusion_Object = 'D6E229DC-35DA-11D1-9034-00A0C90349BE';
87
    const Old_Inter_Media_Dependency_Object = 'D6E229DD-35DA-11D1-9034-00A0C90349BE';
88
    const Old_Rating_Object = 'D6E229DE-35DA-11D1-9034-00A0C90349BE';
89
    const Index_Parameters_Object = 'D6E229DF-35DA-11D1-9034-00A0C90349BE';
90
    const Old_Color_Table_Object = 'D6E229E0-35DA-11D1-9034-00A0C90349BE';
91
    const Old_Language_List_Object = 'D6E229E1-35DA-11D1-9034-00A0C90349BE';
92
    const Old_Audio_Media = 'D6E229E2-35DA-11D1-9034-00A0C90349BE';
93
    const Old_Video_Media = 'D6E229E3-35DA-11D1-9034-00A0C90349BE';
94
    const Old_Image_Media = 'D6E229E4-35DA-11D1-9034-00A0C90349BE';
95
    const Old_Timecode_Media = 'D6E229E5-35DA-11D1-9034-00A0C90349BE';
96
    const Old_Text_Media = 'D6E229E6-35DA-11D1-9034-00A0C90349BE';
97
    const Old_MIDI_Media = 'D6E229E7-35DA-11D1-9034-00A0C90349BE';
98
    const Old_Command_Media = 'D6E229E8-35DA-11D1-9034-00A0C90349BE';
99
    const Old_No_Error_Concealment = 'D6E229EA-35DA-11D1-9034-00A0C90349BE';
100
    const Old_Scrambled_Audio = 'D6E229EB-35DA-11D1-9034-00A0C90349BE';
101
    const Old_No_Color_Table = 'D6E229EC-35DA-11D1-9034-00A0C90349BE';
102
    const Old_SMPTE_Time = 'D6E229ED-35DA-11D1-9034-00A0C90349BE';
103
    const Old_ASCII_Text = 'D6E229EE-35DA-11D1-9034-00A0C90349BE';
104
    const Old_Unicode_Text = 'D6E229EF-35DA-11D1-9034-00A0C90349BE';
105
    const Old_HTML_Text = 'D6E229F0-35DA-11D1-9034-00A0C90349BE';
106
    const Old_URL_Command = 'D6E229F1-35DA-11D1-9034-00A0C90349BE';
107
    const Old_Filename_Command = 'D6E229F2-35DA-11D1-9034-00A0C90349BE';
108
    const Old_ACM_Codec = 'D6E229F3-35DA-11D1-9034-00A0C90349BE';
109
    const Old_VCM_Codec = 'D6E229F4-35DA-11D1-9034-00A0C90349BE';
110
    const Old_QuickTime_Codec = 'D6E229F5-35DA-11D1-9034-00A0C90349BE';
111
    const Old_DirectShow_Transform_Filter = 'D6E229F6-35DA-11D1-9034-00A0C90349BE';
112
    const Old_DirectShow_Rendering_Filter = 'D6E229F7-35DA-11D1-9034-00A0C90349BE';
113
    const Old_No_Enhancement = 'D6E229F8-35DA-11D1-9034-00A0C90349BE';
114
    const Old_Unknown_Enhancement_Type = 'D6E229F9-35DA-11D1-9034-00A0C90349BE';
115
    const Old_Temporal_Enhancement = 'D6E229FA-35DA-11D1-9034-00A0C90349BE';
116
    const Old_Spatial_Enhancement = 'D6E229FB-35DA-11D1-9034-00A0C90349BE';
117
    const Old_Quality_Enhancement = 'D6E229FC-35DA-11D1-9034-00A0C90349BE';
118
    const Old_Number_of_Channels_Enhancement = 'D6E229FD-35DA-11D1-9034-00A0C90349BE';
119
    const Old_Frequency_Response_Enhancement = 'D6E229FE-35DA-11D1-9034-00A0C90349BE';
120
    const Old_Media_Object = 'D6E229FF-35DA-11D1-9034-00A0C90349BE';
121
    const Mutex_Language = 'D6E22A00-35DA-11D1-9034-00A0C90349BE';
122
    const Mutex_Bitrate = 'D6E22A01-35DA-11D1-9034-00A0C90349BE';
123
    const Mutex_Unknown = 'D6E22A02-35DA-11D1-9034-00A0C90349BE';
124
    const Old_ASF_Placeholder_Object = 'D6E22A0E-35DA-11D1-9034-00A0C90349BE';
125
    const Old_Data_Unit_Extension_Object = 'D6E22A0F-35DA-11D1-9034-00A0C90349BE';
126
    const Web_Stream_Format = 'DA1E6B13-8359-4050-B398-388E965BF00C';
127
    const Payload_Ext_System_File_Name = 'E165EC0E-19ED-45D7-B4A7-25CBD1E28E9B';
128
    const Marker_Object = 'F487CD01-A951-11CF-8EE6-00C00C205365';
129
    const Timecode_Index_Parameters_Object = 'F55E496D-9797-4B5D-8C8B-604DFE9BFB24';
130
    const Audio_Media = 'F8699E40-5B4D-11CF-A8FD-00805F5C442B';
131
    const Media_Object_Index_Object = 'FEB103F8-12AD-4C64-840F-2A1D2F7AD48C';
132
    const Alt_Extended_Content_Encryption_Obj = 'FF889EF1-ADEE-40DA-9E71-98704BB928CE';
133
134
    public function Analyze()
135
    {
136
        $getid3 = $this->getid3;
137
138
        $getid3->include_module('audio-video.riff');
139
140
        !isset($getid3->info['audio']) and $getid3->info['audio'] = [];
141
        !isset($getid3->info['video']) and $getid3->info['video'] = [];
142
        $getid3->info['asf']['comments'] = $getid3->info['asf']['header_object'] = [];
143
144
        $info_audio             = &$getid3->info['audio'];
145
        $info_video             = &$getid3->info['video'];
146
        $info_asf               = &$getid3->info['asf'];
147
        $info_asf_comments      = &$info_asf['comments'];
148
        $info_asf_header_object = &$info_asf['header_object'];
149
150
        // ASF structure:
151
        // * Header Object [required]
152
        //   * File Properties Object [required]   (global file attributes)
153
        //   * Stream Properties Object [required] (defines media stream & characteristics)
154
        //   * Header Extension Object [required]  (additional functionality)
155
        //   * Content Description Object          (bibliographic information)
156
        //   * Script Command Object               (commands for during playback)
157
        //   * Marker Object                       (named jumped points within the file)
158
        // * Data Object [required]
159
        //   * Data Packets
160
        // * Index Object
161
162
        // Header Object: (mandatory, one only)
163
        // Field Name                   Field Type   Size (bits)
164
        // Object ID                    GUID         128             // GUID for header object - getid3_asf::Header_Object
165
        // Object Size                  QWORD        64              // size of header object, including 30 bytes of Header Object header
166
        // Number of Header Objects     DWORD        32              // number of objects in header object
167
        // Reserved1                    BYTE         8               // hardcoded: 0x01
168
        // Reserved2                    BYTE         8               // hardcoded: 0x02
169
170
        $getid3->info['fileformat'] = 'asf';
171
172
        fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET);
173
        $header_object_data = fread($getid3->fp, 30);
174
175
        $info_asf_header_object['objectid_guid'] = getid3_asf::BytestringToGUID(substr($header_object_data, 0, 16));
176
177
        if ($info_asf_header_object['objectid_guid'] != getid3_asf::Header_Object) {
178
            throw new getid3_exception('ASF header GUID {' . $info_asf_header_object['objectid_guid'] . '} does not match expected "getid3_asf::Header_Object" GUID {' . getid3_asf::Header_Object . '}');
179
        }
180
181
        getid3_lib::ReadSequence(
182
            'LittleEndian2Int',
183
            $info_asf_header_object,
184
            $header_object_data,
185
            16,
186
            [
187
                'objectsize'    => 8,
188
                'headerobjects' => 4,
189
                'reserved1'     => 1,
190
                'reserved2'     => 1
191
            ]
192
        );
193
194
        $asf_header_data = fread($getid3->fp, $info_asf_header_object['objectsize'] - 30);
195
        $offset          = 0;
196
197
        for ($header_objects_counter = 0; $header_objects_counter < $info_asf_header_object['headerobjects']; $header_objects_counter++) {
198
            $next_object_guid = substr($asf_header_data, $offset, 16);
199
            $offset           += 16;
200
201
            $next_object_size = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 8));
202
            $offset           += 8;
203
204
            $next_object_guidtext = getid3_asf::BytestringToGUID($next_object_guid);
205
206
            switch ($next_object_guidtext) {
207
                case getid3_asf::File_Properties_Object:
208
209
                    // File Properties Object: (mandatory, one only)
210
                    // Field Name                   Field Type   Size (bits)
211
                    // Object ID                    GUID         128             // GUID for file properties object - getid3_asf::File_Properties_Object
212
                    // Object Size                  QWORD        64              // size of file properties object, including 104 bytes of File Properties Object header
213
                    // File ID                      GUID         128             // unique ID - identical to File ID in Data Object
214
                    // File Size                    QWORD        64              // entire file in bytes. Invalid if Broadcast Flag == 1
215
                    // Creation Date                QWORD        64              // date & time of file creation. Maybe invalid if Broadcast Flag == 1
216
                    // Data Packets Count           QWORD        64              // number of data packets in Data Object. Invalid if Broadcast Flag == 1
217
                    // Play Duration                QWORD        64              // playtime, in 100-nanosecond units. Invalid if Broadcast Flag == 1
218
                    // Send Duration                QWORD        64              // time needed to send file, in 100-nanosecond units. Players can ignore this value. Invalid if Broadcast Flag == 1
219
                    // Preroll                      QWORD        64              // time to buffer data before starting to play file, in 1-millisecond units. If <> 0, PlayDuration and PresentationTime have been offset by this amount
220
                    // Flags                        DWORD        32              //
221
                    // * Broadcast Flag             bits         1  (0x01)       // file is currently being written, some header values are invalid
222
                    // * Seekable Flag              bits         1  (0x02)       // is file seekable
223
                    // * Reserved                   bits         30 (0xFFFFFFFC) // reserved - set to zero
224
                    // Minimum Data Packet Size     DWORD        32              // in bytes. should be same as Maximum Data Packet Size. Invalid if Broadcast Flag == 1
225
                    // Maximum Data Packet Size     DWORD        32              // in bytes. should be same as Minimum Data Packet Size. Invalid if Broadcast Flag == 1
226
                    // Maximum Bitrate              DWORD        32              // maximum instantaneous bitrate in bits per second for entire file, including all data streams and ASF overhead
227
228
                    $info_asf['file_properties_object'] = [];
229
                    $info_asf_file_properties_object    = &$info_asf['file_properties_object'];
230
231
                    $info_asf_file_properties_object['objectid_guid'] = $next_object_guidtext;
232
                    $info_asf_file_properties_object['objectsize']    = $next_object_size;
233
234
                    $info_asf_file_properties_object['fileid_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
235
                    $offset                                         += 16;
236
237
                    getid3_lib::ReadSequence(
238
                        'LittleEndian2Int',
239
                        $info_asf_file_properties_object,
240
                        $asf_header_data,
241
                        $offset,
242
                        [
243
                            'filesize'        => 8,
244
                            'creation_date'   => 8,
245
                            'data_packets'    => 8,
246
                            'play_duration'   => 8,
247
                            'send_duration'   => 8,
248
                            'preroll'         => 8,
249
                            'flags_raw'       => 4,
250
                            'min_packet_size' => 4,
251
                            'max_packet_size' => 4,
252
                            'max_bitrate'     => 4
253
                        ]
254
                    );
255
256
                    $offset += 64;
257
258
                    $info_asf_file_properties_object['creation_date_unix'] = getid3_asf::FiletimeToUNIXtime($info_asf_file_properties_object['creation_date']);
259
                    $info_asf_file_properties_object['flags']['broadcast'] = (bool)($info_asf_file_properties_object['flags_raw'] & 0x0001);
260
                    $info_asf_file_properties_object['flags']['seekable']  = (bool)($info_asf_file_properties_object['flags_raw'] & 0x0002);
261
262
                    $getid3->info['playtime_seconds'] = ($info_asf_file_properties_object['play_duration'] / 10000000) - ($info_asf_file_properties_object['preroll'] / 1000);
263
                    $getid3->info['bitrate']          = ($info_asf_file_properties_object['filesize'] * 8) / $getid3->info['playtime_seconds'];
264
                    break;
265
266
                case getid3_asf::Stream_Properties_Object:
267
268
                    // Stream Properties Object: (mandatory, one per media stream)
269
                    // Field Name                   Field Type   Size (bits)
270
                    // Object ID                    GUID         128             // GUID for stream properties object - getid3_asf::Stream_Properties_Object
271
                    // Object Size                  QWORD        64              // size of stream properties object, including 78 bytes of Stream Properties Object header
272
                    // Stream Type                  GUID         128             // getid3_asf::Audio_Media, getid3_asf::Video_Media or getid3_asf::Command_Media
273
                    // Error Correction Type        GUID         128             // getid3_asf::Audio_Spread for audio-only streams, getid3_asf::No_Error_Correction for other stream types
274
                    // Time Offset                  QWORD        64              // 100-nanosecond units. typically zero. added to all timestamps of samples in the stream
275
                    // Type-Specific Data Length    DWORD        32              // number of bytes for Type-Specific Data field
276
                    // Error Correction Data Length DWORD        32              // number of bytes for Error Correction Data field
277
                    // Flags                        WORD         16              //
278
                    // * Stream Number              bits         7 (0x007F)      // number of this stream.  1 <= valid <= 127
279
                    // * Reserved                   bits         8 (0x7F80)      // reserved - set to zero
280
                    // * Encrypted Content Flag     bits         1 (0x8000)      // stream contents encrypted if set
281
                    // Reserved                     DWORD        32              // reserved - set to zero
282
                    // Type-Specific Data           BYTESTREAM   variable        // type-specific format data, depending on value of Stream Type
283
                    // Error Correction Data        BYTESTREAM   variable        // error-correction-specific format data, depending on value of Error Correct Type
284
285
                    // There is one getid3_asf::Stream_Properties_Object for each stream (audio, video) but the
286
                    // stream number isn't known until halfway through decoding the structure, hence it
287
                    // it is decoded to a temporary variable and then stuck in the appropriate index later
288
289
                    $stream_properties_object_data['objectid_guid'] = $next_object_guidtext;
290
                    $stream_properties_object_data['objectsize']    = $next_object_size;
291
292
                    getid3_lib::ReadSequence(
293
                        'LittleEndian2Int',
294
                        $stream_properties_object_data,
295
                        $asf_header_data,
296
                        $offset,
297
                        [
298
                            'stream_type'        => -16,
299
                            'error_correct_type' => -16,
300
                            'time_offset'        => 8,
301
                            'type_data_length'   => 4,
302
                            'error_data_length'  => 4,
303
                            'flags_raw'          => 2
304
                        ]
305
                    );
306
307
                    $stream_properties_stream_number                     = $stream_properties_object_data['flags_raw'] & 0x007F;
308
                    $stream_properties_object_data['flags']['encrypted'] = (bool)($stream_properties_object_data['flags_raw'] & 0x8000);
309
310
                    $stream_properties_object_data['stream_type_guid']   = getid3_asf::BytestringToGUID($stream_properties_object_data['stream_type']);
311
                    $stream_properties_object_data['error_correct_guid'] = getid3_asf::BytestringToGUID($stream_properties_object_data['error_correct_type']);
312
313
                    $offset += 54; // 50 bytes + 4 bytes reserved - DWORD
314
315
                    $stream_properties_object_data['type_specific_data'] = substr($asf_header_data, $offset, $stream_properties_object_data['type_data_length']);
316
                    $offset                                              += $stream_properties_object_data['type_data_length'];
317
318
                    $stream_properties_object_data['error_correct_data'] = substr($asf_header_data, $offset, $stream_properties_object_data['error_data_length']);
319
                    $offset                                              += $stream_properties_object_data['error_data_length'];
320
321
                    switch ($stream_properties_object_data['stream_type_guid']) {
322
                        case getid3_asf::Audio_Media:
323
324
                            $info_audio['dataformat']   = (@$info_audio['dataformat'] ? $info_audio['dataformat'] : 'asf');
325
                            $info_audio['bitrate_mode'] = (@$info_audio['bitrate_mode'] ? $info_audio['bitrate_mode'] : 'cbr');
326
327
                            $audiodata = getid3_riff::RIFFparseWAVEFORMATex(substr($stream_properties_object_data['type_specific_data'], 0, 16));
328
                            unset($audiodata['raw']);
329
                            $info_audio = getid3_riff::array_merge_noclobber($audiodata, $info_audio);
330
                            break;
331
332
                        case getid3_asf::Video_Media:
333
334
                            $info_video['dataformat']   = (@$info_video['dataformat'] ? $info_video['dataformat'] : 'asf');
335
                            $info_video['bitrate_mode'] = (@$info_video['bitrate_mode'] ? $info_video['bitrate_mode'] : 'cbr');
336
                            break;
337
                        /* does nothing but eat memory
338
                        case getid3_asf::Command_Media:
339
                        default:
340
                            // do nothing
341
                            break;
342
                        */
343
                    }
344
345
                    $info_asf['stream_properties_object'][$stream_properties_stream_number] = $stream_properties_object_data;
346
                    unset($stream_properties_object_data); // clear for next stream, if any
347
                    break;
348
349
                case getid3_asf::Header_Extension_Object:
350
351
                    // Header Extension Object: (mandatory, one only)
352
                    // Field Name                   Field Type   Size (bits)
353
                    // Object ID                    GUID         128             // GUID for Header Extension object - getid3_asf::Header_Extension_Object
354
                    // Object Size                  QWORD        64              // size of Header Extension object, including 46 bytes of Header Extension Object header
355
                    // Reserved Field 1             GUID         128             // hardcoded: getid3_asf::Reserved_1
356
                    // Reserved Field 2             WORD         16              // hardcoded: 0x00000006
357
                    // Header Extension Data Size   DWORD        32              // in bytes. valid: 0, or > 24. equals object size minus 46
358
                    // Header Extension Data        BYTESTREAM   variable        // array of zero or more extended header objects
359
360
                    $info_asf['header_extension_object'] = [];
361
                    $info_asf_header_extension_object    = &$info_asf['header_extension_object'];
362
363
                    $info_asf_header_extension_object['objectid_guid']   = $next_object_guidtext;
364
                    $info_asf_header_extension_object['objectsize']      = $next_object_size;
365
                    $info_asf_header_extension_object['reserved_1_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
366
                    $offset                                              += 16;
367
368
                    if ($info_asf_header_extension_object['reserved_1_guid'] != getid3_asf::Reserved_1) {
369
                        $getid3->warning('header_extension_object.reserved_1 GUID (' . $info_asf_header_extension_object['reserved_1_guid'] . ') does not match expected "getid3_asf::Reserved_1" GUID (' . getid3_asf::Reserved_1 . ')');
370
                        break;
371
                    }
372
373
                    $info_asf_header_extension_object['reserved_2'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
374
                    $offset                                         += 2;
375
376
                    if (6 != $info_asf_header_extension_object['reserved_2']) {
377
                        $getid3->warning('header_extension_object.reserved_2 (' . getid3_lib::PrintHexBytes($info_asf_header_extension_object['reserved_2']) . ') does not match expected value of "6"');
378
                        break;
379
                    }
380
381
                    $info_asf_header_extension_object['extension_data_size'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
382
                    $offset                                                  += 4;
383
384
                    $info_asf_header_extension_object['extension_data'] = substr($asf_header_data, $offset, $info_asf_header_extension_object['extension_data_size']);
385
                    $offset                                             += $info_asf_header_extension_object['extension_data_size'];
386
                    break;
387
388
                case getid3_asf::Codec_List_Object:
389
390
                    // Codec List Object: (optional, one only)
391
                    // Field Name                   Field Type   Size (bits)
392
                    // Object ID                    GUID         128             // GUID for Codec List object - getid3_asf::Codec_List_Object
393
                    // Object Size                  QWORD        64              // size of Codec List object, including 44 bytes of Codec List Object header
394
                    // Reserved                     GUID         128             // hardcoded: 86D15241-311D-11D0-A3A4-00A0C90348F6
395
                    // Codec Entries Count          DWORD        32              // number of entries in Codec Entries array
396
                    // Codec Entries                array of:    variable        //
397
                    // * Type                       WORD         16              // 0x0001 = Video Codec, 0x0002 = Audio Codec, 0xFFFF = Unknown Codec
398
                    // * Codec Name Length          WORD         16              // number of Unicode characters stored in the Codec Name field
399
                    // * Codec Name                 WCHAR        variable        // array of Unicode characters - name of codec used to create the content
400
                    // * Codec Description Length   WORD         16              // number of Unicode characters stored in the Codec Description field
401
                    // * Codec Description          WCHAR        variable        // array of Unicode characters - description of format used to create the content
402
                    // * Codec Information Length   WORD         16              // number of Unicode characters stored in the Codec Information field
403
                    // * Codec Information          BYTESTREAM   variable        // opaque array of information bytes about the codec used to create the content
404
405
                    $info_asf['codec_list_object'] = [];
406
                    $info_asf_codec_list_object    = &$info_asf['codec_list_object'];
407
408
                    $info_asf_codec_list_object['objectid_guid'] = $next_object_guidtext;
409
                    $info_asf_codec_list_object['objectsize']    = $next_object_size;
410
411
                    $info_asf_codec_list_object['reserved_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
412
                    $offset                                      += 16;
413
414
                    if ('86D15241-311D-11D0-A3A4-00A0C90348F6' != $info_asf_codec_list_object['reserved_guid']) {
415
                        $getid3->warning('codec_list_object.reserved GUID {' . $info_asf_codec_list_object['reserved_guid'] . '} does not match expected "getid3_asf::Reserved_1" GUID {86D15241-311D-11D0-A3A4-00A0C90348F6}');
416
                        break;
417
                    }
418
419
                    $info_asf_codec_list_object['codec_entries_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
420
                    $offset                                            += 4;
421
422
                    for ($codec_entry_counter = 0; $codec_entry_counter < $info_asf_codec_list_object['codec_entries_count']; $codec_entry_counter++) {
423
                        $info_asf_codec_list_object['codec_entries'][$codec_entry_counter] = [];
424
                        $info_asf_codec_list_object_codecentries_current                   = &$info_asf_codec_list_object['codec_entries'][$codec_entry_counter];
425
426
                        $info_asf_codec_list_object_codecentries_current['type_raw'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
427
                        $offset                                                      += 2;
428
429
                        $info_asf_codec_list_object_codecentries_current['type'] = getid3_asf::ASFCodecListObjectTypeLookup($info_asf_codec_list_object_codecentries_current['type_raw']);
430
431
                        $codec_name_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2)) * 2; // 2 bytes per character
432
                        $offset            += 2;
433
434
                        $info_asf_codec_list_object_codecentries_current['name'] = substr($asf_header_data, $offset, $codec_name_length);
435
                        $offset                                                  += $codec_name_length;
436
437
                        $codec_description_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2)) * 2; // 2 bytes per character
438
                        $offset                   += 2;
439
440
                        $info_asf_codec_list_object_codecentries_current['description'] = substr($asf_header_data, $offset, $codec_description_length);
441
                        $offset                                                         += $codec_description_length;
442
443
                        $codec_information_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
444
                        $offset                   += 2;
445
446
                        $info_asf_codec_list_object_codecentries_current['information'] = substr($asf_header_data, $offset, $codec_information_length);
447
                        $offset                                                         += $codec_information_length;
448
449
                        if (2 == $info_asf_codec_list_object_codecentries_current['type_raw']) {
450
                            // audio codec
451
                            if (false === strpos($info_asf_codec_list_object_codecentries_current['description'], ',')) {
452
                                throw new getid3_exception('[asf][codec_list_object][codec_entries][' . $codec_entry_counter . '][description] expected to contain comma-seperated list of parameters: "' . $info_asf_codec_list_object_codecentries_current['description'] . '"');
453
                            }
454
                            list($audio_codec_bitrate, $audio_codec_frequency, $audio_codec_channels) = explode(',', $this->TrimConvert($info_asf_codec_list_object_codecentries_current['description']));
455
                            $info_audio['codec'] = $this->TrimConvert($info_asf_codec_list_object_codecentries_current['name']);
456
457
                            if (!isset($info_audio['bitrate']) && strstr($audio_codec_bitrate, 'kbps')) {
458
                                $info_audio['bitrate'] = (int)(trim(str_replace('kbps', '', $audio_codec_bitrate)) * 1000);
459
                            }
460
461
                            if (!isset($info_video['bitrate']) && isset($info_audio['bitrate']) && isset($info_asf['file_properties_object']['max_bitrate']) && ($info_asf_codec_list_object['codec_entries_count'] > 1)) {
462
                                $info_video['bitrate'] = $info_asf['file_properties_object']['max_bitrate'] - $info_audio['bitrate'];
463
                            }
464
465
                            if (!@$info_video['bitrate'] && @$info_audio['bitrate'] && @$getid3->info['bitrate']) {
466
                                $info_video['bitrate'] = $getid3->info['bitrate'] - $info_audio['bitrate'];
467
                            }
468
469
                            $audio_codec_frequency = (int)trim(str_replace('kHz', '', $audio_codec_frequency));
470
471
                            static $sample_rate_lookup = [
472
                                8     => 8000,
473
                                8000  => 8000,
474
                                11    => 11025,
475
                                11025 => 11025,
476
                                12    => 12000,
477
                                12000 => 12000,
478
                                16    => 16000,
479
                                16000 => 16000,
480
                                22    => 22050,
481
                                22050 => 22050,
482
                                24    => 24000,
483
                                24000 => 24000,
484
                                32    => 32000,
485
                                32000 => 32000,
486
                                44    => 44100,
487
                                44100 => 44100,
488
                                48    => 48000,
489
                                48000 => 48000,
490
                            ];
491
492
                            $info_audio['sample_rate'] = @$sample_rate_lookup[$audio_codec_frequency];
493
494
                            if (!$info_audio['sample_rate']) {
495
                                $getid3->warning('unknown frequency: "' . $audio_codec_frequency . '" (' . $this->TrimConvert($info_asf_codec_list_object_codecentries_current['description']) . ')');
496
                                break;
497
                            }
498
499
                            if (!isset($info_audio['channels'])) {
500
                                if (strstr($audio_codec_channels, 'stereo')) {
501
                                    $info_audio['channels'] = 2;
502
                                } elseif (strstr($audio_codec_channels, 'mono')) {
503
                                    $info_audio['channels'] = 1;
504
                                }
505
                            }
506
                        }
507
                    }
508
                    break;
509
510
                case getid3_asf::Script_Command_Object:
511
512
                    // Script Command Object: (optional, one only)
513
                    // Field Name                   Field Type   Size (bits)
514
                    // Object ID                    GUID         128             // GUID for Script Command object - getid3_asf::Script_Command_Object
515
                    // Object Size                  QWORD        64              // size of Script Command object, including 44 bytes of Script Command Object header
516
                    // Reserved                     GUID         128             // hardcoded: 4B1ACBE3-100B-11D0-A39B-00A0C90348F6
517
                    // Commands Count               WORD         16              // number of Commands structures in the Script Commands Objects
518
                    // Command Types Count          WORD         16              // number of Command Types structures in the Script Commands Objects
519
                    // Command Types                array of:    variable        //
520
                    // * Command Type Name Length   WORD         16              // number of Unicode characters for Command Type Name
521
                    // * Command Type Name          WCHAR        variable        // array of Unicode characters - name of a type of command
522
                    // Commands                     array of:    variable        //
523
                    // * Presentation Time          DWORD        32              // presentation time of that command, in milliseconds
524
                    // * Type Index                 WORD         16              // type of this command, as a zero-based index into the array of Command Types of this object
525
                    // * Command Name Length        WORD         16              // number of Unicode characters for Command Name
526
                    // * Command Name               WCHAR        variable        // array of Unicode characters - name of this command
527
528
                    // shortcut
529
                    $info_asf['script_command_object'] = [];
530
                    $info_asf_script_command_object    = &$info_asf['script_command_object'];
531
532
                    $info_asf_script_command_object['objectid_guid'] = $next_object_guidtext;
533
                    $info_asf_script_command_object['objectsize']    = $next_object_size;
534
                    $info_asf_script_command_object['reserved_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
535
                    $offset                                          += 16;
536
537
                    if ('4B1ACBE3-100B-11D0-A39B-00A0C90348F6' != $info_asf_script_command_object['reserved_guid']) {
538
                        $getid3->warning('script_command_object.reserved GUID {' . $info_asf_script_command_object['reserved_guid'] . '} does not match expected GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}');
539
                        break;
540
                    }
541
542
                    $info_asf_script_command_object['commands_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
543
                    $offset                                           += 2;
544
545
                    $info_asf_script_command_object['command_types_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
546
                    $offset                                                += 2;
547
548
                    for ($command_types_counter = 0; $command_types_counter < $info_asf_script_command_object['command_types_count']; $command_types_counter++) {
549
                        $command_type_name_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2)) * 2; // 2 bytes per character
550
                        $offset                   += 2;
551
552
                        $info_asf_script_command_object['command_types'][$command_types_counter]['name'] = substr($asf_header_data, $offset, $command_type_name_length);
553
                        $offset                                                                          += $command_type_name_length;
554
                    }
555
556
                    for ($commands_counter = 0; $commands_counter < $info_asf_script_command_object['commands_count']; $commands_counter++) {
557
                        $info_asf_script_command_object['commands'][$commands_counter]['presentation_time'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
558
                        $offset                                                                             += 4;
559
560
                        $info_asf_script_command_object['commands'][$commands_counter]['type_index'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
561
                        $offset                                                                      += 2;
562
563
                        $command_type_name_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2)) * 2; // 2 bytes per character
564
                        $offset                   += 2;
565
566
                        $info_asf_script_command_object['commands'][$commands_counter]['name'] = substr($asf_header_data, $offset, $command_type_name_length);
567
                        $offset                                                                += $command_type_name_length;
568
                    }
569
                    break;
570
571
                case getid3_asf::Marker_Object:
572
573
                    // Marker Object: (optional, one only)
574
                    // Field Name                   Field Type   Size (bits)
575
                    // Object ID                    GUID         128             // GUID for Marker object - getid3_asf::Marker_Object
576
                    // Object Size                  QWORD        64              // size of Marker object, including 48 bytes of Marker Object header
577
                    // Reserved                     GUID         128             // hardcoded: 4CFEDB20-75F6-11CF-9C0F-00A0C90349CB
578
                    // Markers Count                DWORD        32              // number of Marker structures in Marker Object
579
                    // Reserved                     WORD         16              // hardcoded: 0x0000
580
                    // Name Length                  WORD         16              // number of bytes in the Name field
581
                    // Name                         WCHAR        variable        // name of the Marker Object
582
                    // Markers                      array of:    variable        //
583
                    // * Offset                     QWORD        64              // byte offset into Data Object
584
                    // * Presentation Time          QWORD        64              // in 100-nanosecond units
585
                    // * Entry Length               WORD         16              // length in bytes of (Send Time + Flags + Marker Description Length + Marker Description + Padding)
586
                    // * Send Time                  DWORD        32              // in milliseconds
587
                    // * Flags                      DWORD        32              // hardcoded: 0x00000000
588
                    // * Marker Description Length  DWORD        32              // number of bytes in Marker Description field
589
                    // * Marker Description         WCHAR        variable        // array of Unicode characters - description of marker entry
590
                    // * Padding                    BYTESTREAM   variable        // optional padding bytes
591
592
                    $info_asf['marker_object'] = [];
593
                    $info_asf_marker_object    = &$info_asf['marker_object'];
594
595
                    $info_asf_marker_object['objectid_guid'] = $next_object_guidtext;
596
                    $info_asf_marker_object['objectsize']    = $next_object_size;
597
                    $info_asf_marker_object['reserved_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
598
                    $offset                                  += 16;
599
600
                    if ('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB' != $info_asf_marker_object['reserved_guid']) {
601
                        $getid3->warning('marker_object.reserved GUID {' . $info_asf_marker_object['reserved_guid'] . '} does not match expected GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}');
602
                        break;
603
                    }
604
605
                    $info_asf_marker_object['markers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
606
                    $offset                                  += 4;
607
608
                    $info_asf_marker_object['reserved_2'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
609
                    $offset                               += 2;
610
611
                    if (0 != $info_asf_marker_object['reserved_2']) {
612
                        $getid3->warning('marker_object.reserved_2 (' . getid3_lib::PrintHexBytes($info_asf_marker_object['reserved_2']) . ') does not match expected value of "0"');
613
                        break;
614
                    }
615
616
                    $info_asf_marker_object['name_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
617
                    $offset                                += 2;
618
619
                    $info_asf_marker_object['name'] = substr($asf_header_data, $offset, $info_asf_marker_object['name_length']);
620
                    $offset                         += $info_asf_marker_object['name_length'];
621
622
                    for ($markers_counter = 0; $markers_counter < $info_asf_marker_object['markers_count']; $markers_counter++) {
623
                        getid3_lib::ReadSequence(
624
                            'LittleEndian2Int',
625
                            $info_asf_marker_object['markers'][$markers_counter],
626
                            $asf_header_data,
627
                            $offset,
628
                            [
629
                                'offset'                    => 8,
630
                                'presentation_time'         => 8,
631
                                'entry_length'              => 2,
632
                                'send_time'                 => 4,
633
                                'flags'                     => 4,
634
                                'marker_description_length' => 4
635
                            ]
636
                        );
637
                        $offset += 30;
638
639
                        $info_asf_marker_object['markers'][$markers_counter]['marker_description'] = substr($asf_header_data, $offset, $info_asf_marker_object['markers'][$markers_counter]['marker_description_length']);
640
                        $offset                                                                    += $info_asf_marker_object['markers'][$markers_counter]['marker_description_length'];
641
642
                        $padding_length = $info_asf_marker_object['markers'][$markers_counter]['entry_length'] - 4 - 4 - 4 - $info_asf_marker_object['markers'][$markers_counter]['marker_description_length'];
643
                        if ($padding_length > 0) {
644
                            $info_asf_marker_object['markers'][$markers_counter]['padding'] = substr($asf_header_data, $offset, $padding_length);
645
                            $offset                                                         += $padding_length;
646
                        }
647
                    }
648
                    break;
649
650
                case getid3_asf::Bitrate_Mutual_Exclusion_Object:
651
652
                    // Bitrate Mutual Exclusion Object: (optional)
653
                    // Field Name                   Field Type   Size (bits)
654
                    // Object ID                    GUID         128             // GUID for Bitrate Mutual Exclusion object - getid3_asf::Bitrate_Mutual_Exclusion_Object
655
                    // Object Size                  QWORD        64              // size of Bitrate Mutual Exclusion object, including 42 bytes of Bitrate Mutual Exclusion Object header
656
                    // Exlusion Type                GUID         128             // nature of mutual exclusion relationship. one of: (getid3_asf::Mutex_Bitrate, getid3_asf::Mutex_Unknown)
657
                    // Stream Numbers Count         WORD         16              // number of video streams
658
                    // Stream Numbers               WORD         variable        // array of mutually exclusive video stream numbers. 1 <= valid <= 127
659
660
                    // shortcut
661
                    $info_asf['bitrate_mutual_exclusion_object'] = [];
662
                    $info_asf_bitrate_mutual_exclusion_object    = &$info_asf['bitrate_mutual_exclusion_object'];
663
664
                    $info_asf_bitrate_mutual_exclusion_object['objectid_guid'] = $next_object_guidtext;
665
                    $info_asf_bitrate_mutual_exclusion_object['objectsize']    = $next_object_size;
666
                    $info_asf_bitrate_mutual_exclusion_object['reserved_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
667
                    $offset                                                    += 16;
668
669
                    if ($info_asf_bitrate_mutual_exclusion_object['reserved_guid'] != getid3_asf::Mutex_Bitrate && $info_asf_bitrate_mutual_exclusion_object['reserved_guid'] != getid3_asf::Mutex_Unknown) {
670
                        $getid3->warning(
671
                            'bitrate_mutual_exclusion_object.reserved GUID {'
672
                            . $info_asf_bitrate_mutual_exclusion_object['reserved_guid']
673
                            . '} does not match expected "getid3_asf::Mutex_Bitrate" GUID {'
674
                            . getid3_asf::Mutex_Bitrate
675
                            . '} or  "getid3_asf::Mutex_Unknown" GUID {'
676
                            . getid3_asf::Mutex_Unknown
677
                            . '}'
678
                        );
679
                        break;
680
                    }
681
682
                    $info_asf_bitrate_mutual_exclusion_object['stream_numbers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
683
                    $offset                                                           += 2;
684
685
                    for ($stream_number_counter = 0; $stream_number_counter < $info_asf_bitrate_mutual_exclusion_object['stream_numbers_count']; $stream_number_counter++) {
686
                        $info_asf_bitrate_mutual_exclusion_object['stream_numbers'][$stream_number_counter] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
687
                        $offset                                                                             += 2;
688
                    }
689
                    break;
690
691
                case getid3_asf::Error_Correction_Object:
692
693
                    // Error Correction Object: (optional, one only)
694
                    // Field Name                   Field Type   Size (bits)
695
                    // Object ID                    GUID         128             // GUID for Error Correction object - getid3_asf::Error_Correction_Object
696
                    // Object Size                  QWORD        64              // size of Error Correction object, including 44 bytes of Error Correction Object header
697
                    // Error Correction Type        GUID         128             // type of error correction. one of: (getid3_asf::No_Error_Correction, getid3_asf::Audio_Spread)
698
                    // Error Correction Data Length DWORD        32              // number of bytes in Error Correction Data field
699
                    // Error Correction Data        BYTESTREAM   variable        // structure depends on value of Error Correction Type field
700
701
                    $info_asf['error_correction_object'] = [];
702
                    $info_asf_error_correction_object    = &$info_asf['error_correction_object'];
703
704
                    $info_asf_error_correction_object['objectid_guid']         = $next_object_guidtext;
705
                    $info_asf_error_correction_object['objectsize']            = $next_object_size;
706
                    $info_asf_error_correction_object['error_correction_type'] = substr($asf_header_data, $offset, 16);
707
                    $offset                                                    += 16;
708
709
                    $info_asf_error_correction_object['error_correction_guid']        = getid3_asf::BytestringToGUID($info_asf_error_correction_object['error_correction_type']);
710
                    $info_asf_error_correction_object['error_correction_data_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
711
                    $offset                                                           += 4;
712
713
                    switch ($info_asf_error_correction_object['error_correction_type_guid']) {
714
                        case getid3_asf::No_Error_Correction:
715
716
                            // should be no data, but just in case there is, skip to the end of the field
717
                            $offset += $info_asf_error_correction_object['error_correction_data_length'];
718
                            break;
719
720
                        case getid3_asf::Audio_Spread:
721
722
                            // Field Name                   Field Type   Size (bits)
723
                            // Span                         BYTE         8               // number of packets over which audio will be spread.
724
                            // Virtual Packet Length        WORD         16              // size of largest audio payload found in audio stream
725
                            // Virtual Chunk Length         WORD         16              // size of largest audio payload found in audio stream
726
                            // Silence Data Length          WORD         16              // number of bytes in Silence Data field
727
                            // Silence Data                 BYTESTREAM   variable        // hardcoded: 0x00 * (Silence Data Length) bytes
728
729
                            getid3_lib::ReadSequence(
730
                                'LittleEndian2Int',
731
                                $info_asf_error_correction_object,
732
                                $asf_header_data,
733
                                $offset,
734
                                [
735
                                    'span'                  => 1,
736
                                    'virtual_packet_length' => 2,
737
                                    'virtual_chunk_length'  => 2,
738
                                    'silence_data_length'   => 2
739
                                ]
740
                            );
741
                            $offset += 7;
742
743
                            $info_asf_error_correction_object['silence_data'] = substr($asf_header_data, $offset, $info_asf_error_correction_object['silence_data_length']);
744
                            $offset                                           += $info_asf_error_correction_object['silence_data_length'];
745
                            break;
746
747
                        default:
748
                            $getid3->warning(
749
                                'error_correction_object.error_correction_type GUID {'
750
                                . $info_asf_error_correction_object['reserved_guid']
751
                                . '} does not match expected "getid3_asf::No_Error_Correction" GUID {'
752
                                . getid3_asf::No_Error_Correction
753
                                . '} or  "getid3_asf::Audio_Spread" GUID {'
754
                                . getid3_asf::Audio_Spread
755
                                . '}'
756
                            );
757
                            break;
758
                    }
759
760
                    break;
761
762
                case getid3_asf::Content_Description_Object:
763
764
                    // Content Description Object: (optional, one only)
765
                    // Field Name                   Field Type   Size (bits)
766
                    // Object ID                    GUID         128             // GUID for Content Description object - getid3_asf::Content_Description_Object
767
                    // Object Size                  QWORD        64              // size of Content Description object, including 34 bytes of Content Description Object header
768
                    // Title Length                 WORD         16              // number of bytes in Title field
769
                    // Author Length                WORD         16              // number of bytes in Author field
770
                    // Copyright Length             WORD         16              // number of bytes in Copyright field
771
                    // Description Length           WORD         16              // number of bytes in Description field
772
                    // Rating Length                WORD         16              // number of bytes in Rating field
773
                    // Title                        WCHAR        16              // array of Unicode characters - Title
774
                    // Author                       WCHAR        16              // array of Unicode characters - Author
775
                    // Copyright                    WCHAR        16              // array of Unicode characters - Copyright
776
                    // Description                  WCHAR        16              // array of Unicode characters - Description
777
                    // Rating                       WCHAR        16              // array of Unicode characters - Rating
778
779
                    $info_asf['content_description_object'] = [];
780
                    $info_asf_content_description_object    = &$info_asf['content_description_object'];
781
782
                    $info_asf_content_description_object['objectid_guid'] = $next_object_guidtext;
783
                    $info_asf_content_description_object['objectsize']    = $next_object_size;
784
785
                    getid3_lib::ReadSequence(
786
                        'LittleEndian2Int',
787
                        $info_asf_content_description_object,
788
                        $asf_header_data,
789
                        $offset,
790
                        [
791
                            'title_length'       => 2,
792
                            'author_length'      => 2,
793
                            'copyright_length'   => 2,
794
                            'description_length' => 2,
795
                            'rating_length'      => 2
796
                        ]
797
                    );
798
                    $offset += 10;
799
800
                    $info_asf_content_description_object['title'] = substr($asf_header_data, $offset, $info_asf_content_description_object['title_length']);
801
                    $offset                                       += $info_asf_content_description_object['title_length'];
802
803
                    $info_asf_content_description_object['author'] = substr($asf_header_data, $offset, $info_asf_content_description_object['author_length']);
804
                    $offset                                        += $info_asf_content_description_object['author_length'];
805
806
                    $info_asf_content_description_object['copyright'] = substr($asf_header_data, $offset, $info_asf_content_description_object['copyright_length']);
807
                    $offset                                           += $info_asf_content_description_object['copyright_length'];
808
809
                    $info_asf_content_description_object['description'] = substr($asf_header_data, $offset, $info_asf_content_description_object['description_length']);
810
                    $offset                                             += $info_asf_content_description_object['description_length'];
811
812
                    $info_asf_content_description_object['rating'] = substr($asf_header_data, $offset, $info_asf_content_description_object['rating_length']);
813
                    $offset                                        += $info_asf_content_description_object['rating_length'];
814
815
                    foreach (['title' => 'title', 'author' => 'artist', 'copyright' => 'copyright', 'description' => 'comment', 'rating' => 'rating'] as $key_to_copy_from => $key_to_copy_to) {
816
                        if (!empty($info_asf_content_description_object[$key_to_copy_from])) {
817
                            $info_asf_comments[$key_to_copy_to][] = getid3_asf::TrimTerm($info_asf_content_description_object[$key_to_copy_from]);
818
                        }
819
                    }
820
                    break;
821
822
                case getid3_asf::Extended_Content_Description_Object:
823
824
                    // Extended Content Description Object: (optional, one only)
825
                    // Field Name                   Field Type   Size (bits)
826
                    // Object ID                    GUID         128             // GUID for Extended Content Description object - getid3_asf::Extended_Content_Description_Object
827
                    // Object Size                  QWORD        64              // size of ExtendedContent Description object, including 26 bytes of Extended Content Description Object header
828
                    // Content Descriptors Count    WORD         16              // number of entries in Content Descriptors list
829
                    // Content Descriptors          array of:    variable        //
830
                    // * Descriptor Name Length     WORD         16              // size in bytes of Descriptor Name field
831
                    // * Descriptor Name            WCHAR        variable        // array of Unicode characters - Descriptor Name
832
                    // * Descriptor Value Data Type WORD         16              // Lookup array:
833
                    // 0x0000 = Unicode String (variable length)
834
                    // 0x0001 = BYTE array     (variable length)
835
                    // 0x0002 = BOOL           (DWORD, 32 bits)
836
                    // 0x0003 = DWORD          (DWORD, 32 bits)
837
                    // 0x0004 = QWORD          (QWORD, 64 bits)
838
                    // 0x0005 = WORD           (WORD,  16 bits)
839
                    // * Descriptor Value Length    WORD         16              // number of bytes stored in Descriptor Value field
840
                    // * Descriptor Value           variable     variable        // value for Content Descriptor
841
842
                    $info_asf['extended_content_description_object'] = [];
843
                    $info_asf_extended_content_description_object    = &$info_asf['extended_content_description_object'];
844
845
                    $info_asf_extended_content_description_object['objectid_guid']             = $next_object_guidtext;
846
                    $info_asf_extended_content_description_object['objectsize']                = $next_object_size;
847
                    $info_asf_extended_content_description_object['content_descriptors_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
848
                    $offset                                                                    += 2;
849
850
                    for ($extended_content_descriptors_counter = 0; $extended_content_descriptors_counter < $info_asf_extended_content_description_object['content_descriptors_count']; $extended_content_descriptors_counter++) {
851
                        $info_asf_extended_content_description_object['content_descriptors'][$extended_content_descriptors_counter] = [];
852
                        $info_asf_extended_content_description_object_content_descriptor_current                                    = &$info_asf_extended_content_description_object['content_descriptors'][$extended_content_descriptors_counter];
853
854
                        $info_asf_extended_content_description_object_content_descriptor_current['base_offset'] = $offset + 30;
855
                        $info_asf_extended_content_description_object_content_descriptor_current['name_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
856
                        $offset                                                                                 += 2;
857
858
                        $info_asf_extended_content_description_object_content_descriptor_current['name'] = substr($asf_header_data, $offset, $info_asf_extended_content_description_object_content_descriptor_current['name_length']);
859
                        $offset                                                                          += $info_asf_extended_content_description_object_content_descriptor_current['name_length'];
860
861
                        $info_asf_extended_content_description_object_content_descriptor_current['value_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
862
                        $offset                                                                                += 2;
863
864
                        $info_asf_extended_content_description_object_content_descriptor_current['value_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
865
                        $offset                                                                                  += 2;
866
867
                        $info_asf_extended_content_description_object_content_descriptor_current['value'] = substr($asf_header_data, $offset, $info_asf_extended_content_description_object_content_descriptor_current['value_length']);
868
                        $offset                                                                           += $info_asf_extended_content_description_object_content_descriptor_current['value_length'];
869
870
                        switch ($info_asf_extended_content_description_object_content_descriptor_current['value_type']) {
871
                            case 0x0000: // Unicode string
872
                                break;
873
874
                            case 0x0001: // BYTE array
875
                                // do nothing
876
                                break;
877
878
                            case 0x0002: // BOOL
879
                                $info_asf_extended_content_description_object_content_descriptor_current['value'] = (bool)getid3_lib::LittleEndian2Int($info_asf_extended_content_description_object_content_descriptor_current['value']);
880
                                break;
881
882
                            case 0x0003: // DWORD
883
                            case 0x0004: // QWORD
884
                            case 0x0005: // WORD
885
                                $info_asf_extended_content_description_object_content_descriptor_current['value'] = getid3_lib::LittleEndian2Int($info_asf_extended_content_description_object_content_descriptor_current['value']);
886
                                break;
887
888
                            default:
889
                                $getid3->warning('extended_content_description.content_descriptors.' . $extended_content_descriptors_counter . '.value_type is invalid (' . $info_asf_extended_content_description_object_content_descriptor_current['value_type'] . ')');
890
                                break;
891
                        }
892
893
                        switch ($this->TrimConvert(strtolower($info_asf_extended_content_description_object_content_descriptor_current['name']))) {
894
                            case 'wm/albumartist':
895
                            case 'artist':
896
                                $info_asf_comments['artist'] = [getid3_asf::TrimTerm($info_asf_extended_content_description_object_content_descriptor_current['value'])];
897
                                break;
898
899
                            case 'wm/albumtitle':
900
                            case 'album':
901
                                $info_asf_comments['album'] = [getid3_asf::TrimTerm($info_asf_extended_content_description_object_content_descriptor_current['value'])];
902
                                break;
903
904
                            case 'wm/genre':
905
                            case 'genre':
906
                                $genre                      = getid3_asf::TrimTerm($info_asf_extended_content_description_object_content_descriptor_current['value']);
907
                                $info_asf_comments['genre'] = [$genre];
908
                                break;
909
910
                            case 'wm/tracknumber':
911
                            case 'tracknumber':
912
                                $info_asf_comments['track'] = [intval(getid3_asf::TrimTerm($info_asf_extended_content_description_object_content_descriptor_current['value']))];
913
                                break;
914
915
                            case 'wm/track':
916
                                if (empty($info_asf_comments['track'])) {
917
                                    $info_asf_comments['track'] = [1 + $this->TrimConvert($info_asf_extended_content_description_object_content_descriptor_current['value'])];
918
                                }
919
                                break;
920
921
                            case 'wm/year':
922
                            case 'year':
923
                            case 'date':
924
                                $info_asf_comments['year'] = [getid3_asf::TrimTerm($info_asf_extended_content_description_object_content_descriptor_current['value'])];
925
                                break;
926
927
                            case 'wm/lyrics':
928
                            case 'lyrics':
929
                                $info_asf_comments['lyrics'] = [getid3_asf::TrimTerm($info_asf_extended_content_description_object_content_descriptor_current['value'])];
930
                                break;
931
932
                            case 'isvbr':
933
                                if ($info_asf_extended_content_description_object_content_descriptor_current['value']) {
934
                                    $info_audio['bitrate_mode'] = 'vbr';
935
                                    $info_video['bitrate_mode'] = 'vbr';
936
                                }
937
                                break;
938
939
                            case 'id3':
940
941
                                // id3v2 parsing might not be enabled
942
                                if (class_exists('getid3_id3v2')) {
943
                                    // Clone getid3
944
                                    $clone = clone $getid3;
945
946
                                    // Analyse clone by string
947
                                    $id3v2 = new getid3_id3v2($clone);
948
                                    $id3v2->AnalyzeString($info_asf_extended_content_description_object_content_descriptor_current['value']);
949
950
                                    // Import from clone and destroy
951
                                    $getid3->info['id3v2'] = $clone->info['id3v2'];
952
                                    $getid3->warnings($clone->warnings());
0 ignored issues
show
Unused Code introduced by
The call to getid3::warnings() has too many arguments starting with $clone->warnings(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

952
                                    $getid3->/** @scrutinizer ignore-call */ 
953
                                             warnings($clone->warnings());

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
953
                                    unset($clone);
954
                                }
955
                                break;
956
957
                            case 'wm/encodingtime':
958
                                $info_asf_extended_content_description_object_content_descriptor_current['encoding_time_unix'] = getid3_asf::FiletimeToUNIXtime($info_asf_extended_content_description_object_content_descriptor_current['value']);
959
                                $info_asf_comments['encoding_time_unix']                                                       = [$info_asf_extended_content_description_object_content_descriptor_current['encoding_time_unix']];
960
                                break;
961
962
                            case 'wm/picture':
963
964
                                //typedef struct _WMPicture{
965
                                //  LPWSTR  pwszMIMEType;
966
                                //  BYTE  bPictureType;
967
                                //  LPWSTR  pwszDescription;
968
                                //  DWORD  dwDataLen;
969
                                //  BYTE*  pbData;
970
                                //} WM_PICTURE;
971
972
                                $info_asf_extended_content_description_object_content_descriptor_current['image_type_id'] = getid3_lib::LittleEndian2Int($info_asf_extended_content_description_object_content_descriptor_current['value']{0});
973
                                $info_asf_extended_content_description_object_content_descriptor_current['image_type']    = getid3_asf::WMpictureTypeLookup($info_asf_extended_content_description_object_content_descriptor_current['image_type_id']);
0 ignored issues
show
Bug Best Practice introduced by
The method getid3_asf::WMpictureTypeLookup() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

973
                                /** @scrutinizer ignore-call */ 
974
                                $info_asf_extended_content_description_object_content_descriptor_current['image_type']    = getid3_asf::WMpictureTypeLookup($info_asf_extended_content_description_object_content_descriptor_current['image_type_id']);
Loading history...
974
                                $info_asf_extended_content_description_object_content_descriptor_current['image_size']    = getid3_lib::LittleEndian2Int(substr($info_asf_extended_content_description_object_content_descriptor_current['value'], 1, 4));
975
                                $info_asf_extended_content_description_object_content_descriptor_current['image_mime']    = '';
976
977
                                $wm_picture_offset = 5;
978
979
                                do {
980
                                    $next_byte_pair                                                                        = substr($info_asf_extended_content_description_object_content_descriptor_current['value'], $wm_picture_offset, 2);
981
                                    $wm_picture_offset                                                                     += 2;
982
                                    $info_asf_extended_content_description_object_content_descriptor_current['image_mime'] .= $next_byte_pair;
983
                                } while ("\x00\x00" !== $next_byte_pair);
984
985
                                $info_asf_extended_content_description_object_content_descriptor_current['image_description'] = '';
986
987
                                do {
988
                                    $next_byte_pair                                                                               = substr($info_asf_extended_content_description_object_content_descriptor_current['value'], $wm_picture_offset, 2);
989
                                    $wm_picture_offset                                                                            += 2;
990
                                    $info_asf_extended_content_description_object_content_descriptor_current['image_description'] .= $next_byte_pair;
991
                                } while ("\x00\x00" !== $next_byte_pair);
992
993
                                $info_asf_extended_content_description_object_content_descriptor_current['dataoffset'] = $wm_picture_offset;
994
                                $info_asf_extended_content_description_object_content_descriptor_current['data']       = substr($info_asf_extended_content_description_object_content_descriptor_current['value'], $wm_picture_offset);
995
                                unset($info_asf_extended_content_description_object_content_descriptor_current['value']);
996
                                break;
997
998
                            default:
999
                                switch ($info_asf_extended_content_description_object_content_descriptor_current['value_type']) {
1000
                                    case 0: // Unicode string
1001
                                        if ('WM/' == substr($this->TrimConvert($info_asf_extended_content_description_object_content_descriptor_current['name']), 0, 3)) {
1002
                                            $info_asf_comments[str_replace('wm/', '', strtolower($this->TrimConvert($info_asf_extended_content_description_object_content_descriptor_current['name'])))] = [
1003
                                                getid3_asf::TrimTerm(
1004
                                                    $info_asf_extended_content_description_object_content_descriptor_current['value']
1005
                                                )
1006
                                            ];
1007
                                        }
1008
                                        break;
1009
1010
                                    case 1:
1011
                                        break;
1012
                                }
1013
                                break;
1014
                        }
1015
                    }
1016
                    break;
1017
1018
                case getid3_asf::Stream_Bitrate_Properties_Object:
1019
1020
                    // Stream Bitrate Properties Object: (optional, one only)
1021
                    // Field Name                   Field Type   Size (bits)
1022
                    // Object ID                    GUID         128             // GUID for Stream Bitrate Properties object - getid3_asf::Stream_Bitrate_Properties_Object
1023
                    // Object Size                  QWORD        64              // size of Extended Content Description object, including 26 bytes of Stream Bitrate Properties Object header
1024
                    // Bitrate Records Count        WORD         16              // number of records in Bitrate Records
1025
                    // Bitrate Records              array of:    variable        //
1026
                    // * Flags                      WORD         16              //
1027
                    // * * Stream Number            bits         7  (0x007F)     // number of this stream
1028
                    // * * Reserved                 bits         9  (0xFF80)     // hardcoded: 0
1029
                    // * Average Bitrate            DWORD        32              // in bits per second
1030
1031
                    // shortcut
1032
                    $info_asf['stream_bitrate_properties_object'] = [];
1033
                    $info_asf_stream_bitrate_properties_object    = &$info_asf['stream_bitrate_properties_object'];
1034
1035
                    $info_asf_stream_bitrate_properties_object['objectid_guid']         = $next_object_guidtext;
1036
                    $info_asf_stream_bitrate_properties_object['objectsize']            = $next_object_size;
1037
                    $info_asf_stream_bitrate_properties_object['bitrate_records_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
1038
                    $offset                                                             += 2;
1039
1040
                    for ($bitrate_records_counter = 0; $bitrate_records_counter < $info_asf_stream_bitrate_properties_object['bitrate_records_count']; $bitrate_records_counter++) {
1041
                        $info_asf_stream_bitrate_properties_object['bitrate_records'][$bitrate_records_counter]['flags_raw'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
1042
                        $offset                                                                                              += 2;
1043
1044
                        $info_asf_stream_bitrate_properties_object['bitrate_records'][$bitrate_records_counter]['flags']['stream_number'] = $info_asf_stream_bitrate_properties_object['bitrate_records'][$bitrate_records_counter]['flags_raw'] & 0x007F;
1045
1046
                        $info_asf_stream_bitrate_properties_object['bitrate_records'][$bitrate_records_counter]['bitrate'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
1047
                        $offset                                                                                            += 4;
1048
                    }
1049
                    break;
1050
1051
                case getid3_asf::Padding_Object:
1052
1053
                    // Padding Object: (optional)
1054
                    // Field Name                   Field Type   Size (bits)
1055
                    // Object ID                    GUID         128             // GUID for Padding object - getid3_asf::Padding_Object
1056
                    // Object Size                  QWORD        64              // size of Padding object, including 24 bytes of ASF Padding Object header
1057
                    // Padding Data                 BYTESTREAM   variable        // ignore
1058
1059
                    // shortcut
1060
                    $info_asf['padding_object'] = [];
1061
                    $info_asf_paddingobject     = &$info_asf['padding_object'];
1062
1063
                    $info_asf_paddingobject['objectid_guid']  = $next_object_guidtext;
1064
                    $info_asf_paddingobject['objectsize']     = $next_object_size;
1065
                    $info_asf_paddingobject['padding_length'] = $info_asf_paddingobject['objectsize'] - 16 - 8;
1066
                    $info_asf_paddingobject['padding']        = substr($asf_header_data, $offset, $info_asf_paddingobject['padding_length']);
1067
                    $offset                                   += ($next_object_size - 16 - 8);
1068
                    break;
1069
1070
                case getid3_asf::Extended_Content_Encryption_Object:
1071
                case getid3_asf::Content_Encryption_Object:
1072
1073
                    // WMA DRM - just ignore
1074
                    $offset += ($next_object_size - 16 - 8);
1075
                    break;
1076
1077
                default:
1078
1079
                    // Implementations shall ignore any standard or non-standard object that they do not know how to handle.
1080
                    if (getid3_asf::GUIDname($next_object_guidtext)) {
1081
                        $getid3->warning('unhandled GUID "' . getid3_asf::GUIDname($next_object_guidtext) . '" {' . $next_object_guidtext . '} in ASF header at offset ' . ($offset - 16 - 8));
1082
                    } else {
1083
                        $getid3->warning('unknown GUID {' . $next_object_guidtext . '} in ASF header at offset ' . ($offset - 16 - 8));
1084
                    }
1085
                    $offset += ($next_object_size - 16 - 8);
1086
                    break;
1087
            }
1088
        }
1089
1090
        if (isset($info_asf_stream_bitrate_properties['bitrate_records_count'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $info_asf_stream_bitrate_properties does not exist. Did you maybe mean $info_asf_stream_bitrate_properties_object?
Loading history...
1091
            $asf_bitrate_audio = 0;
1092
            $asf_bitrate_video = 0;
1093
1094
            for ($bitrate_records_counter = 0; $bitrate_records_counter < $info_asf_stream_bitrate_properties['bitrate_records_count']; $bitrate_records_counter++) {
1095
                if (isset($info_asf_codec_list_object['codec_entries'][$bitrate_records_counter])) {
1096
                    switch ($info_asf_codec_list_object['codec_entries'][$bitrate_records_counter]['type_raw']) {
1097
                        case 1:
1098
                            $asf_bitrate_video += $info_asf_stream_bitrate_properties['bitrate_records'][$bitrate_records_counter]['bitrate'];
1099
                            break;
1100
1101
                        case 2:
1102
                            $asf_bitrate_audio += $info_asf_stream_bitrate_properties['bitrate_records'][$bitrate_records_counter]['bitrate'];
1103
                            break;
1104
                    }
1105
                }
1106
            }
1107
            if ($asf_bitrate_audio > 0) {
1108
                $info_audio['bitrate'] = $asf_bitrate_audio;
1109
            }
1110
            if ($asf_bitrate_video > 0) {
1111
                $info_video['bitrate'] = $asf_bitrate_video;
1112
            }
1113
        }
1114
1115
        if (isset($info_asf['stream_properties_object']) && is_array($info_asf['stream_properties_object'])) {
1116
            $info_audio['bitrate'] = 0;
1117
            $info_video['bitrate'] = 0;
1118
1119
            foreach ($info_asf['stream_properties_object'] as $stream_number => $stream_data) {
1120
                switch ($stream_data['stream_type_guid']) {
1121
                    case getid3_asf::Audio_Media:
1122
1123
                        // Field Name                   Field Type   Size (bits)
1124
                        // Codec ID / Format Tag        WORD         16              // unique ID of audio codec - defined as wFormatTag field of WAVEFORMATEX structure
1125
                        // Number of Channels           WORD         16              // number of channels of audio - defined as nChannels field of WAVEFORMATEX structure
1126
                        // Samples Per Second           DWORD        32              // in Hertz - defined as nSamplesPerSec field of WAVEFORMATEX structure
1127
                        // Average number of Bytes/sec  DWORD        32              // bytes/sec of audio stream  - defined as nAvgBytesPerSec field of WAVEFORMATEX structure
1128
                        // Block Alignment              WORD         16              // block size in bytes of audio codec - defined as nBlockAlign field of WAVEFORMATEX structure
1129
                        // Bits per sample              WORD         16              // bits per sample of mono data. set to zero for variable bitrate codecs. defined as wBitsPerSample field of WAVEFORMATEX structure
1130
                        // Codec Specific Data Size     WORD         16              // size in bytes of Codec Specific Data buffer - defined as cbSize field of WAVEFORMATEX structure
1131
                        // Codec Specific Data          BYTESTREAM   variable        // array of codec-specific data bytes
1132
1133
                        // shortcut
1134
                        $info_asf['audio_media'][$stream_number] = [];
1135
                        $info_asf_audio_media_current_stream     = &$info_asf['audio_media'][$stream_number];
1136
1137
                        $audio_media_offset = 0;
1138
1139
                        $info_asf_audio_media_current_stream = getid3_riff::RIFFparseWAVEFORMATex(substr($stream_data['type_specific_data'], $audio_media_offset, 16));
1140
1141
                        $audio_media_offset += 16;
1142
1143
                        $info_audio['lossless'] = false;
1144
                        switch ($info_asf_audio_media_current_stream['raw']['wFormatTag']) {
1145
                            case 0x0001: // PCM
1146
                            case 0x0163: // WMA9 Lossless
1147
                                $info_audio['lossless'] = true;
1148
                                break;
1149
                        }
1150
1151
                        if (!empty($info_asf['stream_bitrate_properties_object']['bitrate_records'])) {
1152
                            foreach ($info_asf['stream_bitrate_properties_object']['bitrate_records'] as $data_array) {
1153
                                if (@$data_array['flags']['stream_number'] == $stream_number) {
1154
                                    $info_asf_audio_media_current_stream['bitrate'] = $data_array['bitrate'];
1155
                                    $info_audio['bitrate']                          += $data_array['bitrate'];
1156
                                    break;
1157
                                }
1158
                            }
1159
                        } else {
1160
                            if (@$info_asf_audio_media_current_stream['bytes_sec']) {
1161
                                $info_audio['bitrate'] += $info_asf_audio_media_current_stream['bytes_sec'] * 8;
1162
                            } elseif (@$info_asf_audio_media_current_stream['bitrate']) {
1163
                                $info_audio['bitrate'] += $info_asf_audio_media_current_stream['bitrate'];
1164
                            }
1165
                        }
1166
1167
                        $info_audio['streams'][$stream_number]               = $info_asf_audio_media_current_stream;
1168
                        $info_audio['streams'][$stream_number]['wformattag'] = $info_asf_audio_media_current_stream['raw']['wFormatTag'];
1169
                        $info_audio['streams'][$stream_number]['lossless']   = $info_audio['lossless'];
1170
                        $info_audio['streams'][$stream_number]['bitrate']    = $info_audio['bitrate'];
1171
                        unset($info_audio['streams'][$stream_number]['raw']);
1172
1173
                        $info_asf_audio_media_current_stream['codec_data_size'] = getid3_lib::LittleEndian2Int(substr($stream_data['type_specific_data'], $audio_media_offset, 2));
1174
                        $audio_media_offset                                     += 2;
1175
1176
                        $info_asf_audio_media_current_stream['codec_data'] = substr($stream_data['type_specific_data'], $audio_media_offset, $info_asf_audio_media_current_stream['codec_data_size']);
1177
                        $audio_media_offset                                += $info_asf_audio_media_current_stream['codec_data_size'];
1178
                        break;
1179
1180
                    case getid3_asf::Video_Media:
1181
1182
                        // Field Name                   Field Type   Size (bits)
1183
                        // Encoded Image Width          DWORD        32              // width of image in pixels
1184
                        // Encoded Image Height         DWORD        32              // height of image in pixels
1185
                        // Reserved Flags               BYTE         8               // hardcoded: 0x02
1186
                        // Format Data Size             WORD         16              // size of Format Data field in bytes
1187
                        // Format Data                  array of:    variable        //
1188
                        // * Format Data Size           DWORD        32              // number of bytes in Format Data field, in bytes - defined as biSize field of BITMAPINFOHEADER structure
1189
                        // * Image Width                LONG         32              // width of encoded image in pixels - defined as biWidth field of BITMAPINFOHEADER structure
1190
                        // * Image Height               LONG         32              // height of encoded image in pixels - defined as biHeight field of BITMAPINFOHEADER structure
1191
                        // * Reserved                   WORD         16              // hardcoded: 0x0001 - defined as biPlanes field of BITMAPINFOHEADER structure
1192
                        // * Bits Per Pixel Count       WORD         16              // bits per pixel - defined as biBitCount field of BITMAPINFOHEADER structure
1193
                        // * Compression ID             FOURCC       32              // fourcc of video codec - defined as biCompression field of BITMAPINFOHEADER structure
1194
                        // * Image Size                 DWORD        32              // image size in bytes - defined as biSizeImage field of BITMAPINFOHEADER structure
1195
                        // * Horizontal Pixels / Meter  DWORD        32              // horizontal resolution of target device in pixels per meter - defined as biXPelsPerMeter field of BITMAPINFOHEADER structure
1196
                        // * Vertical Pixels / Meter    DWORD        32              // vertical resolution of target device in pixels per meter - defined as biYPelsPerMeter field of BITMAPINFOHEADER structure
1197
                        // * Colors Used Count          DWORD        32              // number of color indexes in the color table that are actually used - defined as biClrUsed field of BITMAPINFOHEADER structure
1198
                        // * Important Colors Count     DWORD        32              // number of color index required for displaying bitmap. if zero, all colors are required. defined as biClrImportant field of BITMAPINFOHEADER structure
1199
                        // * Codec Specific Data        BYTESTREAM   variable        // array of codec-specific data bytes
1200
1201
                        $info_asf['video_media'][$stream_number] = [];
1202
                        $info_asf_video_media_current_stream     = &$info_asf['video_media'][$stream_number];
1203
1204
                        getid3_lib::ReadSequence(
1205
                            'LittleEndian2Int',
1206
                            $info_asf_video_media_current_stream,
1207
                            $stream_data['type_specific_data'],
1208
                            0,
1209
                            [
1210
                                'image_width'      => 4,
1211
                                'image_height'     => 4,
1212
                                'flags'            => 1,
1213
                                'format_data_size' => 2
1214
                            ]
1215
                        );
1216
1217
                        getid3_lib::ReadSequence(
1218
                            'LittleEndian2Int',
1219
                            $info_asf_video_media_current_stream['format_data'],
1220
                            $stream_data['type_specific_data'],
1221
                            11,
1222
                            [
1223
                                'format_data_size' => 4,
1224
                                'image_width'      => 4,
1225
                                'image_height'     => 4,
1226
                                'reserved'         => 2,
1227
                                'bits_per_pixel'   => 2,
1228
                                'codec_fourcc'     => -4,
1229
                                'image_size'       => 4,
1230
                                'horizontal_pels'  => 4,
1231
                                'vertical_pels'    => 4,
1232
                                'colors_used'      => 4,
1233
                                'colors_important' => 4
1234
                            ]
1235
                        );
1236
1237
                        $info_asf_video_media_current_stream['format_data']['codec_data'] = substr($stream_data['type_specific_data'], 51);
1238
1239
                        if (!empty($info_asf['stream_bitrate_properties_object']['bitrate_records'])) {
1240
                            foreach ($info_asf['stream_bitrate_properties_object']['bitrate_records'] as $data_array) {
1241
                                if (@$data_array['flags']['stream_number'] == $stream_number) {
1242
                                    $info_asf_video_media_current_stream['bitrate']   = $data_array['bitrate'];
1243
                                    $info_video['streams'][$stream_number]['bitrate'] = $data_array['bitrate'];
1244
                                    $info_video['bitrate']                            += $data_array['bitrate'];
1245
1246
                                    break;
1247
                                }
1248
                            }
1249
                        }
1250
1251
                        $info_asf_video_media_current_stream['format_data']['codec'] = getid3_riff::RIFFfourccLookup($info_asf_video_media_current_stream['format_data']['codec_fourcc']);
1252
1253
                        $info_video['streams'][$stream_number]['fourcc']          = $info_asf_video_media_current_stream['format_data']['codec_fourcc'];
1254
                        $info_video['streams'][$stream_number]['codec']           = $info_asf_video_media_current_stream['format_data']['codec'];
1255
                        $info_video['streams'][$stream_number]['resolution_x']    = $info_asf_video_media_current_stream['image_width'];
1256
                        $info_video['streams'][$stream_number]['resolution_y']    = $info_asf_video_media_current_stream['image_height'];
1257
                        $info_video['streams'][$stream_number]['bits_per_sample'] = $info_asf_video_media_current_stream['format_data']['bits_per_pixel'];
1258
                        break;
1259
1260
                    default:
1261
                        break;
1262
                }
1263
            }
1264
        }
1265
1266
        while (ftell($getid3->fp) < $getid3->info['avdataend']) {
1267
            $next_object_data_header = fread($getid3->fp, 24);
1268
            $offset                  = 0;
1269
1270
            $next_object_guid = substr($next_object_data_header, 0, 16);
1271
            $offset           += 16;
1272
1273
            $next_object_guidtext = getid3_asf::BytestringToGUID($next_object_guid);
1274
            $next_object_size     = getid3_lib::LittleEndian2Int(substr($next_object_data_header, $offset, 8));
1275
            $offset               += 8;
1276
1277
            switch ($next_object_guidtext) {
1278
                case getid3_asf::Data_Object:
1279
1280
                    // Data Object: (mandatory, one only)
1281
                    // Field Name                       Field Type   Size (bits)
1282
                    // Object ID                        GUID         128             // GUID for Data object - getid3_asf::Data_Object
1283
                    // Object Size                      QWORD        64              // size of Data object, including 50 bytes of Data Object header. may be 0 if FilePropertiesObject.BroadcastFlag == 1
1284
                    // File ID                          GUID         128             // unique identifier. identical to File ID field in Header Object
1285
                    // Total Data Packets               QWORD        64              // number of Data Packet entries in Data Object. invalid if FilePropertiesObject.BroadcastFlag == 1
1286
                    // Reserved                         WORD         16              // hardcoded: 0x0101
1287
1288
                    // shortcut
1289
                    $info_asf['data_object'] = [];
1290
                    $info_asf_data_object    = &$info_asf['data_object'];
1291
1292
                    $data_object_data = $next_object_data_header . fread($getid3->fp, 50 - 24);
1293
                    $offset           = 24;
1294
1295
                    $info_asf_data_object['objectid_guid'] = $next_object_guidtext;
1296
                    $info_asf_data_object['objectsize']    = $next_object_size;
1297
1298
                    $info_asf_data_object['fileid_guid'] = getid3_asf::BytestringToGUID(substr($data_object_data, $offset, 16));
1299
                    $offset                              += 16;
1300
1301
                    $info_asf_data_object['total_data_packets'] = getid3_lib::LittleEndian2Int(substr($data_object_data, $offset, 8));
1302
                    $offset                                     += 8;
1303
1304
                    $info_asf_data_object['reserved'] = getid3_lib::LittleEndian2Int(substr($data_object_data, $offset, 2));
1305
                    $offset                           += 2;
1306
1307
                    if (0x0101 != $info_asf_data_object['reserved']) {
1308
                        $getid3->warning('data_object.reserved (' . getid3_lib::PrintHexBytes($info_asf_data_object['reserved']) . ') does not match expected value of "0x0101"');
1309
                        break;
1310
                    }
1311
1312
                    // Data Packets                     array of:    variable        //
1313
                    // * Error Correction Flags         BYTE         8               //
1314
                    // * * Error Correction Data Length bits         4               // if Error Correction Length Type == 00, size of Error Correction Data in bytes, else hardcoded: 0000
1315
                    // * * Opaque Data Present          bits         1               //
1316
                    // * * Error Correction Length Type bits         2               // number of bits for size of the error correction data. hardcoded: 00
1317
                    // * * Error Correction Present     bits         1               // If set, use Opaque Data Packet structure, else use Payload structure
1318
                    // * Error Correction Data
1319
1320
                    $getid3->info['avdataoffset'] = ftell($getid3->fp);
1321
                    fseek($getid3->fp, ($info_asf_data_object['objectsize'] - 50), SEEK_CUR); // skip actual audio/video data
1322
                    $getid3->info['avdataend'] = ftell($getid3->fp);
1323
                    break;
1324
1325
                case getid3_asf::Simple_Index_Object:
1326
1327
                    // Simple Index Object: (optional, recommended, one per video stream)
1328
                    // Field Name                       Field Type   Size (bits)
1329
                    // Object ID                        GUID         128             // GUID for Simple Index object - getid3_asf::Data_Object
1330
                    // Object Size                      QWORD        64              // size of Simple Index object, including 56 bytes of Simple Index Object header
1331
                    // File ID                          GUID         128             // unique identifier. may be zero or identical to File ID field in Data Object and Header Object
1332
                    // Index Entry Time Interval        QWORD        64              // interval between index entries in 100-nanosecond units
1333
                    // Maximum Packet Count             DWORD        32              // maximum packet count for all index entries
1334
                    // Index Entries Count              DWORD        32              // number of Index Entries structures
1335
                    // Index Entries                    array of:    variable        //
1336
                    // * Packet Number                  DWORD        32              // number of the Data Packet associated with this index entry
1337
                    // * Packet Count                   WORD         16              // number of Data Packets to sent at this index entry
1338
1339
                    // shortcut
1340
                    $info_asf['simple_index_object'] = [];
1341
                    $info_asf_simple_index_object    = &$info_asf['simple_index_object'];
1342
1343
                    $info_asf_simple_index_object['objectid_guid'] = $next_object_guidtext;
1344
                    $info_asf_simple_index_object['objectsize']    = $next_object_size;
1345
1346
                    $simple_index_object_data = $next_object_data_header . fread($getid3->fp, 56 - 24);
1347
1348
                    $info_asf_simple_index_object['fileid_guid'] = getid3_asf::BytestringToGUID(substr($simple_index_object_data, 24, 16));
1349
1350
                    getid3_lib::ReadSequence(
1351
                        'LittleEndian2Int',
1352
                        $info_asf_simple_index_object,
1353
                        $simple_index_object_data,
1354
                        40,
1355
                        [
1356
                            'index_entry_time_interval' => 8,
1357
                            'maximum_packet_count'      => 4,
1358
                            'index_entries_count'       => 4
1359
                        ]
1360
                    );
1361
1362
                    $offset = 56;
1363
1364
                    $index_entries_data = $simple_index_object_data . fread($getid3->fp, 6 * $info_asf_simple_index_object['index_entries_count']);
1365
                    for ($index_entries_counter = 0; $index_entries_counter < $info_asf_simple_index_object['index_entries_count']; $index_entries_counter++) {
1366
                        $info_asf_simple_index_object['index_entries'][$index_entries_counter]['packet_number'] = getid3_lib::LittleEndian2Int(substr($index_entries_data, $offset, 4));
1367
                        $offset                                                                                 += 4;
1368
1369
                        $info_asf_simple_index_object['index_entries'][$index_entries_counter]['packet_count'] = getid3_lib::LittleEndian2Int(substr($index_entries_data, $offset, 4));
1370
                        $offset                                                                                += 2;
1371
                    }
1372
                    break;
1373
1374
                case getid3_asf::Index_Object:
1375
1376
                    // 6.2 ASF top-level Index Object (optional but recommended when appropriate, 0 or 1)
1377
                    // Field Name                       Field Type   Size (bits)
1378
                    // Object ID                        GUID         128             // GUID for the Index Object - getid3_asf::Index_Object
1379
                    // Object Size                      QWORD        64              // Specifies the size, in bytes, of the Index Object, including at least 34 bytes of Index Object header
1380
                    // Index Entry Time Interval        DWORD        32              // Specifies the time interval between each index entry in ms.
1381
                    // Index Specifiers Count           WORD         16              // Specifies the number of Index Specifiers structures in this Index Object.
1382
                    // Index Blocks Count               DWORD        32              // Specifies the number of Index Blocks structures in this Index Object.
1383
1384
                    // Index Entry Time Interval        DWORD        32              // Specifies the time interval between index entries in milliseconds.  This value cannot be 0.
1385
                    // Index Specifiers Count           WORD         16              // Specifies the number of entries in the Index Specifiers list.  Valid values are 1 and greater.
1386
                    // Index Specifiers                 array of:    varies          //
1387
                    // * Stream Number                  WORD         16              // Specifies the stream number that the Index Specifiers refer to. Valid values are between 1 and 127.
1388
                    // * Index Type                     WORD         16              // Specifies Index Type values as follows:
1389
                    //   1 = Nearest Past Data Packet - indexes point to the data packet whose presentation time is closest to the index entry time.
1390
                    //   2 = Nearest Past Media Object - indexes point to the closest data packet containing an entire object or first fragment of an object.
1391
                    //   3 = Nearest Past Cleanpoint. - indexes point to the closest data packet containing an entire object (or first fragment of an object) that has the Cleanpoint Flag set.
1392
                    //   Nearest Past Cleanpoint is the most common type of index.
1393
                    // Index Entry Count                DWORD        32              // Specifies the number of Index Entries in the block.
1394
                    // * Block Positions                QWORD        varies          // Specifies a list of byte offsets of the beginnings of the blocks relative to the beginning of the first Data Packet (i.e., the beginning of the Data Object + 50 bytes). The number of entries in this list is specified by the value of the Index Specifiers Count field. The order of those byte offsets is tied to the order in which Index Specifiers are listed.
1395
                    // * Index Entries                  array of:    varies          //
1396
                    // * * Offsets                      DWORD        varies          // An offset value of 0xffffffff indicates an invalid offset value
1397
1398
                    // shortcut
1399
                    $info_asf['asf_index_object'] = [];
1400
                    $info_asf_asf_index_object    = &$info_asf['asf_index_object'];
1401
1402
                    $asf_index_object_data = $next_object_data_header . fread($getid3->fp, 34 - 24);
1403
1404
                    $info_asf_asf_index_object['objectid_guid'] = $next_object_guidtext;
1405
                    $info_asf_asf_index_object['objectsize']    = $next_object_size;
1406
1407
                    getid3_lib::ReadSequence(
1408
                        'LittleEndian2Int',
1409
                        $info_asf_asf_index_object,
1410
                        $asf_index_object_data,
1411
                        24,
1412
                        [
1413
                            'entry_time_interval'    => 4,
1414
                            'index_specifiers_count' => 2,
1415
                            'index_blocks_count'     => 4
1416
                        ]
1417
                    );
1418
1419
                    $offset = 34;
1420
1421
                    $asf_index_object_data .= fread($getid3->fp, 4 * $info_asf_asf_index_object['index_specifiers_count']);
1422
1423
                    for ($index_specifiers_counter = 0; $index_specifiers_counter < $info_asf_asf_index_object['index_specifiers_count']; $index_specifiers_counter++) {
1424
                        $index_specifier_stream_number = getid3_lib::LittleEndian2Int(substr($asf_index_object_data, $offset, 2));
1425
                        $offset                        += 2;
1426
1427
                        $info_asf_asf_index_object['index_specifiers'][$index_specifiers_counter]['stream_number'] = $index_specifier_stream_number;
1428
1429
                        $info_asf_asf_index_object['index_specifiers'][$index_specifiers_counter]['index_type'] = getid3_lib::LittleEndian2Int(substr($asf_index_object_data, $offset, 2));
1430
                        $offset                                                                                 += 2;
1431
1432
                        $info_asf_asf_index_object['index_specifiers'][$index_specifiers_counter]['index_type_text'] = getid3_asf::ASFIndexObjectIndexTypeLookup($info_asf_asf_index_object['index_specifiers'][$index_specifiers_counter]['index_type']);
1433
                    }
1434
1435
                    $asf_index_object_data                          .= fread($getid3->fp, 4);
1436
                    $info_asf_asf_index_object['index_entry_count'] = getid3_lib::LittleEndian2Int(substr($asf_index_object_data, $offset, 4));
1437
                    $offset                                         += 4;
1438
1439
                    $asf_index_object_data .= fread($getid3->fp, 8 * $info_asf_asf_index_object['index_specifiers_count']);
1440
1441
                    for ($index_specifiers_counter = 0; $index_specifiers_counter < $info_asf_asf_index_object['index_specifiers_count']; $index_specifiers_counter++) {
1442
                        $info_asf_asf_index_object['block_positions'][$index_specifiers_counter] = getid3_lib::LittleEndian2Int(substr($asf_index_object_data, $offset, 8));
1443
                        $offset                                                                  += 8;
1444
                    }
1445
1446
                    $asf_index_object_data .= fread($getid3->fp, 4 * $info_asf_asf_index_object['index_specifiers_count'] * $info_asf_asf_index_object['index_entry_count']);
1447
1448
                    for ($index_entry_counter = 0; $index_entry_counter < $info_asf_asf_index_object['index_entry_count']; $index_entry_counter++) {
1449
                        for ($index_specifiers_counter = 0; $index_specifiers_counter < $info_asf_asf_index_object['index_specifiers_count']; $index_specifiers_counter++) {
1450
                            $info_asf_asf_index_object['offsets'][$index_specifiers_counter][$index_entry_counter] = getid3_lib::LittleEndian2Int(substr($asf_index_object_data, $offset, 4));
1451
                            $offset                                                                                += 4;
1452
                        }
1453
                    }
1454
                    break;
1455
1456
                default:
1457
1458
                    // Implementations shall ignore any standard or non-standard object that they do not know how to handle.
1459
                    if (getid3_asf::GUIDname($next_object_guidtext)) {
1460
                        $getid3->warning('unhandled GUID "' . getid3_asf::GUIDname($next_object_guidtext) . '" {' . $next_object_guidtext . '} in ASF body at offset ' . ($offset - 16 - 8));
1461
                    } else {
1462
                        $getid3->warning('unknown GUID {' . $next_object_guidtext . '} in ASF body at offset ' . (ftell($getid3->fp) - 16 - 8));
1463
                    }
1464
                    fseek($getid3->fp, ($next_object_size - 16 - 8), SEEK_CUR);
1465
                    break;
1466
            }
1467
        }
1468
1469
        if (isset($info_asf_codec_list_object['codec_entries']) && is_array($info_asf_codec_list_object['codec_entries'])) {
1470
            foreach ($info_asf_codec_list_object['codec_entries'] as $stream_number => $stream_data) {
1471
                switch ($stream_data['information']) {
1472
                    case 'WMV1':
1473
                    case 'WMV2':
1474
                    case 'WMV3':
1475
                    case 'MSS1':
1476
                    case 'MSS2':
1477
                    case 'WMVA':
1478
                    case 'WVC1':
1479
                    case 'WMVP':
1480
                    case 'WVP2':
1481
                        $info_video['dataformat']  = 'wmv';
1482
                        $getid3->info['mime_type'] = 'video/x-ms-wmv';
1483
                        break;
1484
1485
                    case 'MP42':
1486
                    case 'MP43':
1487
                    case 'MP4S':
1488
                    case 'mp4s':
1489
                        $info_video['dataformat']  = 'asf';
1490
                        $getid3->info['mime_type'] = 'video/x-ms-asf';
1491
                        break;
1492
1493
                    default:
1494
                        switch ($stream_data['type_raw']) {
1495
                            case 1:
1496
                                if (strstr($this->TrimConvert($stream_data['name']), 'Windows Media')) {
1497
                                    $info_video['dataformat'] = 'wmv';
1498
                                    if ('video/x-ms-asf' == $getid3->info['mime_type']) {
1499
                                        $getid3->info['mime_type'] = 'video/x-ms-wmv';
1500
                                    }
1501
                                }
1502
                                break;
1503
1504
                            case 2:
1505
                                if (strstr($this->TrimConvert($stream_data['name']), 'Windows Media')) {
1506
                                    $info_audio['dataformat'] = 'wma';
1507
                                    if ('video/x-ms-asf' == $getid3->info['mime_type']) {
1508
                                        $getid3->info['mime_type'] = 'audio/x-ms-wma';
1509
                                    }
1510
                                }
1511
                                break;
1512
                        }
1513
                        break;
1514
                }
1515
            }
1516
        }
1517
1518
        switch (@$info_audio['codec']) {
1519
            case 'MPEG Layer-3':
1520
                $info_audio['dataformat'] = 'mp3';
1521
                break;
1522
1523
            default:
1524
                break;
1525
        }
1526
1527
        if (isset($info_asf_codec_list_object['codec_entries'])) {
1528
            foreach ($info_asf_codec_list_object['codec_entries'] as $stream_number => $stream_data) {
1529
                switch ($stream_data['type_raw']) {
1530
                    case 1: // video
1531
                        $info_video['encoder'] = $this->TrimConvert($info_asf_codec_list_object['codec_entries'][$stream_number]['name']);
1532
                        break;
1533
1534
                    case 2: // audio
1535
                        $info_audio['encoder']         = $this->TrimConvert($info_asf_codec_list_object['codec_entries'][$stream_number]['name']);
1536
                        $info_audio['encoder_options'] = $this->TrimConvert($info_asf_codec_list_object['codec_entries'][0]['description']);
1537
                        $info_audio['codec']           = $info_audio['encoder'];
1538
                        break;
1539
1540
                    default:
1541
                        $getid3->warning('Unknown streamtype: [codec_list_object][codec_entries][' . $stream_number . '][type_raw] == ' . $stream_data['type_raw']);
1542
                        break;
1543
                }
1544
            }
1545
        }
1546
1547
        if (isset($getid3->info['audio'])) {
1548
            $info_audio['lossless']   = (isset($info_audio['lossless']) ? $info_audio['lossless'] : false);
1549
            $info_audio['dataformat'] = (!empty($info_audio['dataformat']) ? $info_audio['dataformat'] : 'asf');
1550
        }
1551
1552
        if (!empty($info_video['dataformat'])) {
1553
            $info_video['lossless']           = (isset($info_audio['lossless']) ? $info_audio['lossless'] : false);
1554
            $info_video['pixel_aspect_ratio'] = (isset($info_audio['pixel_aspect_ratio']) ? $info_audio['pixel_aspect_ratio'] : (float)1);
1555
            $info_video['dataformat']         = (!empty($info_video['dataformat']) ? $info_video['dataformat'] : 'asf');
1556
        }
1557
1558
        $getid3->info['bitrate'] = @$info_audio['bitrate'] + @$info_video['bitrate'];
1559
1560
        if (empty($info_audio)) {
1561
            unset($getid3->info['audio']);
1562
        }
1563
1564
        if (empty($info_video)) {
1565
            unset($getid3->info['video']);
1566
        }
1567
1568
        return true;
1569
    }
1570
1571
    // Remove terminator 00 00 and convert UNICODE to Latin-1
1572
    private function TrimConvert($string)
1573
    {
1574
        // remove terminator, only if present (it should be, but...)
1575
        if ("\x00\x00" == substr($string, strlen($string) - 2, 2)) {
1576
            $string = substr($string, 0, strlen($string) - 2);
1577
        }
1578
1579
        // convert
1580
        return trim($this->getid3->iconv('UTF-16LE', 'ISO-8859-1', $string), ' ');
0 ignored issues
show
Bug introduced by
It seems like $this->getid3->iconv('UT... 'ISO-8859-1', $string) can also be of type null; however, parameter $string of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1580
        return trim(/** @scrutinizer ignore-type */ $this->getid3->iconv('UTF-16LE', 'ISO-8859-1', $string), ' ');
Loading history...
1581
    }
1582
1583
    private function WMpictureTypeLookup($wm_picture_type)
1584
    {
1585
        static $lookup = [
1586
            0x03 => 'Front Cover',
1587
            0x04 => 'Back Cover',
1588
            0x00 => 'User Defined',
1589
            0x05 => 'Leaflet Page',
1590
            0x06 => 'Media Label',
1591
            0x07 => 'Lead Artist',
1592
            0x08 => 'Artist',
1593
            0x09 => 'Conductor',
1594
            0x0A => 'Band',
1595
            0x0B => 'Composer',
1596
            0x0C => 'Lyricist',
1597
            0x0D => 'Recording Location',
1598
            0x0E => 'During Recording',
1599
            0x0F => 'During Performance',
1600
            0x10 => 'Video Screen Capture',
1601
            0x12 => 'Illustration',
1602
            0x13 => 'Band Logotype',
1603
            0x14 => 'Publisher Logotype'
1604
        ];
1605
1606
        return isset($lookup[$wm_picture_type]) ? $this->getid3->iconv('ISO-8859-1', 'UTF-16LE', $lookup[$wm_picture_type]) : '';
1607
    }
1608
1609
    public static function ASFCodecListObjectTypeLookup($codec_list_type)
1610
    {
1611
        static $lookup = [
1612
            0x0001 => 'Video Codec',
1613
            0x0002 => 'Audio Codec',
1614
            0xFFFF => 'Unknown Codec'
1615
        ];
1616
1617
        return (isset($lookup[$codec_list_type]) ? $lookup[$codec_list_type] : 'Invalid Codec Type');
1618
    }
1619
1620
    public static function GUIDname($guid_string)
1621
    {
1622
        static $lookup = [
1623
            getid3_asf::Extended_Stream_Properties_Object   => 'Extended_Stream_Properties_Object',
1624
            getid3_asf::Padding_Object                      => 'Padding_Object',
1625
            getid3_asf::Payload_Ext_Syst_Pixel_Aspect_Ratio => 'Payload_Ext_Syst_Pixel_Aspect_Ratio',
1626
            getid3_asf::Script_Command_Object               => 'Script_Command_Object',
1627
            getid3_asf::No_Error_Correction                 => 'No_Error_Correction',
1628
            getid3_asf::Content_Branding_Object             => 'Content_Branding_Object',
1629
            getid3_asf::Content_Encryption_Object           => 'Content_Encryption_Object',
1630
            getid3_asf::Digital_Signature_Object            => 'Digital_Signature_Object',
1631
            getid3_asf::Extended_Content_Encryption_Object  => 'Extended_Content_Encryption_Object',
1632
            getid3_asf::Simple_Index_Object                 => 'Simple_Index_Object',
1633
            getid3_asf::Degradable_JPEG_Media               => 'Degradable_JPEG_Media',
1634
            getid3_asf::Payload_Extension_System_Timecode   => 'Payload_Extension_System_Timecode',
1635
            getid3_asf::Binary_Media                        => 'Binary_Media',
1636
            getid3_asf::Timecode_Index_Object               => 'Timecode_Index_Object',
1637
            getid3_asf::Metadata_Library_Object             => 'Metadata_Library_Object',
1638
            getid3_asf::Reserved_3                          => 'Reserved_3',
1639
            getid3_asf::Reserved_4                          => 'Reserved_4',
1640
            getid3_asf::Command_Media                       => 'Command_Media',
1641
            getid3_asf::Header_Extension_Object             => 'Header_Extension_Object',
1642
            getid3_asf::Media_Object_Index_Parameters_Obj   => 'Media_Object_Index_Parameters_Obj',
1643
            getid3_asf::Header_Object                       => 'Header_Object',
1644
            getid3_asf::Content_Description_Object          => 'Content_Description_Object',
1645
            getid3_asf::Error_Correction_Object             => 'Error_Correction_Object',
1646
            getid3_asf::Data_Object                         => 'Data_Object',
1647
            getid3_asf::Web_Stream_Media_Subtype            => 'Web_Stream_Media_Subtype',
1648
            getid3_asf::Stream_Bitrate_Properties_Object    => 'Stream_Bitrate_Properties_Object',
1649
            getid3_asf::Language_List_Object                => 'Language_List_Object',
1650
            getid3_asf::Codec_List_Object                   => 'Codec_List_Object',
1651
            getid3_asf::Reserved_2                          => 'Reserved_2',
1652
            getid3_asf::File_Properties_Object              => 'File_Properties_Object',
1653
            getid3_asf::File_Transfer_Media                 => 'File_Transfer_Media',
1654
            getid3_asf::Old_RTP_Extension_Data              => 'Old_RTP_Extension_Data',
1655
            getid3_asf::Advanced_Mutual_Exclusion_Object    => 'Advanced_Mutual_Exclusion_Object',
1656
            getid3_asf::Bandwidth_Sharing_Object            => 'Bandwidth_Sharing_Object',
1657
            getid3_asf::Reserved_1                          => 'Reserved_1',
1658
            getid3_asf::Bandwidth_Sharing_Exclusive         => 'Bandwidth_Sharing_Exclusive',
1659
            getid3_asf::Bandwidth_Sharing_Partial           => 'Bandwidth_Sharing_Partial',
1660
            getid3_asf::JFIF_Media                          => 'JFIF_Media',
1661
            getid3_asf::Stream_Properties_Object            => 'Stream_Properties_Object',
1662
            getid3_asf::Video_Media                         => 'Video_Media',
1663
            getid3_asf::Audio_Spread                        => 'Audio_Spread',
1664
            getid3_asf::Metadata_Object                     => 'Metadata_Object',
1665
            getid3_asf::Payload_Ext_Syst_Sample_Duration    => 'Payload_Ext_Syst_Sample_Duration',
1666
            getid3_asf::Group_Mutual_Exclusion_Object       => 'Group_Mutual_Exclusion_Object',
1667
            getid3_asf::Extended_Content_Description_Object => 'Extended_Content_Description_Object',
1668
            getid3_asf::Stream_Prioritization_Object        => 'Stream_Prioritization_Object',
1669
            getid3_asf::Payload_Ext_System_Content_Type     => 'Payload_Ext_System_Content_Type',
1670
            getid3_asf::Old_File_Properties_Object          => 'Old_File_Properties_Object',
1671
            getid3_asf::Old_ASF_Header_Object               => 'Old_ASF_Header_Object',
1672
            getid3_asf::Old_ASF_Data_Object                 => 'Old_ASF_Data_Object',
1673
            getid3_asf::Index_Object                        => 'Index_Object',
1674
            getid3_asf::Old_Stream_Properties_Object        => 'Old_Stream_Properties_Object',
1675
            getid3_asf::Old_Content_Description_Object      => 'Old_Content_Description_Object',
1676
            getid3_asf::Old_Script_Command_Object           => 'Old_Script_Command_Object',
1677
            getid3_asf::Old_Marker_Object                   => 'Old_Marker_Object',
1678
            getid3_asf::Old_Component_Download_Object       => 'Old_Component_Download_Object',
1679
            getid3_asf::Old_Stream_Group_Object             => 'Old_Stream_Group_Object',
1680
            getid3_asf::Old_Scalable_Object                 => 'Old_Scalable_Object',
1681
            getid3_asf::Old_Prioritization_Object           => 'Old_Prioritization_Object',
1682
            getid3_asf::Bitrate_Mutual_Exclusion_Object     => 'Bitrate_Mutual_Exclusion_Object',
1683
            getid3_asf::Old_Inter_Media_Dependency_Object   => 'Old_Inter_Media_Dependency_Object',
1684
            getid3_asf::Old_Rating_Object                   => 'Old_Rating_Object',
1685
            getid3_asf::Index_Parameters_Object             => 'Index_Parameters_Object',
1686
            getid3_asf::Old_Color_Table_Object              => 'Old_Color_Table_Object',
1687
            getid3_asf::Old_Language_List_Object            => 'Old_Language_List_Object',
1688
            getid3_asf::Old_Audio_Media                     => 'Old_Audio_Media',
1689
            getid3_asf::Old_Video_Media                     => 'Old_Video_Media',
1690
            getid3_asf::Old_Image_Media                     => 'Old_Image_Media',
1691
            getid3_asf::Old_Timecode_Media                  => 'Old_Timecode_Media',
1692
            getid3_asf::Old_Text_Media                      => 'Old_Text_Media',
1693
            getid3_asf::Old_MIDI_Media                      => 'Old_MIDI_Media',
1694
            getid3_asf::Old_Command_Media                   => 'Old_Command_Media',
1695
            getid3_asf::Old_No_Error_Concealment            => 'Old_No_Error_Concealment',
1696
            getid3_asf::Old_Scrambled_Audio                 => 'Old_Scrambled_Audio',
1697
            getid3_asf::Old_No_Color_Table                  => 'Old_No_Color_Table',
1698
            getid3_asf::Old_SMPTE_Time                      => 'Old_SMPTE_Time',
1699
            getid3_asf::Old_ASCII_Text                      => 'Old_ASCII_Text',
1700
            getid3_asf::Old_Unicode_Text                    => 'Old_Unicode_Text',
1701
            getid3_asf::Old_HTML_Text                       => 'Old_HTML_Text',
1702
            getid3_asf::Old_URL_Command                     => 'Old_URL_Command',
1703
            getid3_asf::Old_Filename_Command                => 'Old_Filename_Command',
1704
            getid3_asf::Old_ACM_Codec                       => 'Old_ACM_Codec',
1705
            getid3_asf::Old_VCM_Codec                       => 'Old_VCM_Codec',
1706
            getid3_asf::Old_QuickTime_Codec                 => 'Old_QuickTime_Codec',
1707
            getid3_asf::Old_DirectShow_Transform_Filter     => 'Old_DirectShow_Transform_Filter',
1708
            getid3_asf::Old_DirectShow_Rendering_Filter     => 'Old_DirectShow_Rendering_Filter',
1709
            getid3_asf::Old_No_Enhancement                  => 'Old_No_Enhancement',
1710
            getid3_asf::Old_Unknown_Enhancement_Type        => 'Old_Unknown_Enhancement_Type',
1711
            getid3_asf::Old_Temporal_Enhancement            => 'Old_Temporal_Enhancement',
1712
            getid3_asf::Old_Spatial_Enhancement             => 'Old_Spatial_Enhancement',
1713
            getid3_asf::Old_Quality_Enhancement             => 'Old_Quality_Enhancement',
1714
            getid3_asf::Old_Number_of_Channels_Enhancement  => 'Old_Number_of_Channels_Enhancement',
1715
            getid3_asf::Old_Frequency_Response_Enhancement  => 'Old_Frequency_Response_Enhancement',
1716
            getid3_asf::Old_Media_Object                    => 'Old_Media_Object',
1717
            getid3_asf::Mutex_Language                      => 'Mutex_Language',
1718
            getid3_asf::Mutex_Bitrate                       => 'Mutex_Bitrate',
1719
            getid3_asf::Mutex_Unknown                       => 'Mutex_Unknown',
1720
            getid3_asf::Old_ASF_Placeholder_Object          => 'Old_ASF_Placeholder_Object',
1721
            getid3_asf::Old_Data_Unit_Extension_Object      => 'Old_Data_Unit_Extension_Object',
1722
            getid3_asf::Web_Stream_Format                   => 'Web_Stream_Format',
1723
            getid3_asf::Payload_Ext_System_File_Name        => 'Payload_Ext_System_File_Name',
1724
            getid3_asf::Marker_Object                       => 'Marker_Object',
1725
            getid3_asf::Timecode_Index_Parameters_Object    => 'Timecode_Index_Parameters_Object',
1726
            getid3_asf::Audio_Media                         => 'Audio_Media',
1727
            getid3_asf::Media_Object_Index_Object           => 'Media_Object_Index_Object',
1728
            getid3_asf::Alt_Extended_Content_Encryption_Obj => 'Alt_Extended_Content_Encryption_Obj'
1729
        ];
1730
1731
        return @$lookup[$guid_string];
1732
    }
1733
1734
    public static function ASFIndexObjectIndexTypeLookup($id)
1735
    {
1736
        static $lookup = [
1737
            1 => 'Nearest Past Data Packet',
1738
            2 => 'Nearest Past Media Object',
1739
            3 => 'Nearest Past Cleanpoint'
1740
        ];
1741
1742
        return (isset($lookup[$id]) ? $lookup[$id] : 'invalid');
1743
    }
1744
1745
    public static function GUIDtoBytestring($guid_string)
1746
    {
1747
        // Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way:
1748
        // first 4 bytes are in little-endian order
1749
        // next 2 bytes are appended in little-endian order
1750
        // next 2 bytes are appended in little-endian order
1751
        // next 2 bytes are appended in big-endian order
1752
        // next 6 bytes are appended in big-endian order
1753
1754
        // AaBbCcDd-EeFf-GgHh-IiJj-KkLlMmNnOoPp is stored as this 16-byte string:
1755
        // $Dd $Cc $Bb $Aa $Ff $Ee $Hh $Gg $Ii $Jj $Kk $Ll $Mm $Nn $Oo $Pp
1756
1757
        $hex_byte_char_string = chr(hexdec(substr($guid_string, 6, 2)));
0 ignored issues
show
Bug introduced by
It seems like hexdec(substr($guid_string, 6, 2)) can also be of type double; however, parameter $codepoint of chr() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1757
        $hex_byte_char_string = chr(/** @scrutinizer ignore-type */ hexdec(substr($guid_string, 6, 2)));
Loading history...
1758
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 4, 2)));
1759
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 2, 2)));
1760
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 0, 2)));
1761
1762
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 11, 2)));
1763
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 9, 2)));
1764
1765
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 16, 2)));
1766
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 14, 2)));
1767
1768
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 19, 2)));
1769
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 21, 2)));
1770
1771
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 24, 2)));
1772
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 26, 2)));
1773
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 28, 2)));
1774
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 30, 2)));
1775
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 32, 2)));
1776
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 34, 2)));
1777
1778
        return $hex_byte_char_string;
1779
    }
1780
1781
    public static function BytestringToGUID($byte_string)
1782
    {
1783
        $guid_string = str_pad(dechex(ord($byte_string{3})), 2, '0', STR_PAD_LEFT);
1784
        $guid_string .= str_pad(dechex(ord($byte_string{2})), 2, '0', STR_PAD_LEFT);
1785
        $guid_string .= str_pad(dechex(ord($byte_string{1})), 2, '0', STR_PAD_LEFT);
1786
        $guid_string .= str_pad(dechex(ord($byte_string{0})), 2, '0', STR_PAD_LEFT);
1787
        $guid_string .= '-';
1788
        $guid_string .= str_pad(dechex(ord($byte_string{5})), 2, '0', STR_PAD_LEFT);
1789
        $guid_string .= str_pad(dechex(ord($byte_string{4})), 2, '0', STR_PAD_LEFT);
1790
        $guid_string .= '-';
1791
        $guid_string .= str_pad(dechex(ord($byte_string{7})), 2, '0', STR_PAD_LEFT);
1792
        $guid_string .= str_pad(dechex(ord($byte_string{6})), 2, '0', STR_PAD_LEFT);
1793
        $guid_string .= '-';
1794
        $guid_string .= str_pad(dechex(ord($byte_string{8})), 2, '0', STR_PAD_LEFT);
1795
        $guid_string .= str_pad(dechex(ord($byte_string{9})), 2, '0', STR_PAD_LEFT);
1796
        $guid_string .= '-';
1797
        $guid_string .= str_pad(dechex(ord($byte_string{10})), 2, '0', STR_PAD_LEFT);
1798
        $guid_string .= str_pad(dechex(ord($byte_string{11})), 2, '0', STR_PAD_LEFT);
1799
        $guid_string .= str_pad(dechex(ord($byte_string{12})), 2, '0', STR_PAD_LEFT);
1800
        $guid_string .= str_pad(dechex(ord($byte_string{13})), 2, '0', STR_PAD_LEFT);
1801
        $guid_string .= str_pad(dechex(ord($byte_string{14})), 2, '0', STR_PAD_LEFT);
1802
        $guid_string .= str_pad(dechex(ord($byte_string{15})), 2, '0', STR_PAD_LEFT);
1803
1804
        return strtoupper($guid_string);
1805
    }
1806
1807
    public static function FiletimeToUNIXtime($file_time, $round = true)
1808
    {
1809
        // FILETIME is a 64-bit unsigned integer representing
1810
        // the number of 100-nanosecond intervals since January 1, 1601
1811
        // UNIX timestamp is number of seconds since January 1, 1970
1812
        // 116444736000000000 = 10000000 * 60 * 60 * 24 * 365 * 369 + 89 leap days
1813
1814
        $time = ($file_time - 116444736000000000) / 10000000;
1815
1816
        if ($round) {
1817
            return intval(round($time));
1818
        }
1819
1820
        return $time;
1821
    }
1822
1823
    public static function TrimTerm($string)
1824
    {
1825
        // remove terminator, only if present (it should be, but...)
1826
        if ("\x00\x00" == substr($string, -2)) {
1827
            $string = substr($string, 0, -2);
1828
        }
1829
        return $string;
1830
    }
1831
1832
}
1833
1834
1835