Passed
Branch master (f2d2e3)
by Michael
18:45
created

getid3_asf   F

Complexity

Total Complexity 177

Size/Duplication

Total Lines 1814
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 1814
rs 0.8
wmc 177

10 Methods

Rating   Name   Duplication   Size   Complexity  
B GUIDname() 0 112 1
A ASFIndexObjectIndexTypeLookup() 0 9 2
F Analyze() 0 1423 162
A GUIDtoBytestring() 0 34 1
A TrimTerm() 0 7 2
A WMpictureTypeLookup() 0 24 2
A TrimConvert() 0 9 2
A FiletimeToUNIXtime() 0 14 2
A ASFCodecListObjectTypeLookup() 0 9 2
A BytestringToGUID() 0 24 1

How to fix   Complexity   

Complex Class

Complex classes like getid3_asf often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use getid3_asf, and based on these observations, apply Extract Interface, too.

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
        
25
        
26
class getid3_asf extends getid3_handler
27
{
28
29
    const Extended_Stream_Properties_Object   = '14E6A5CB-C672-4332-8399-A96952065B5A';
30
    const Padding_Object                      = '1806D474-CADF-4509-A4BA-9AABCB96AAE8';
31
    const Payload_Ext_Syst_Pixel_Aspect_Ratio = '1B1EE554-F9EA-4BC8-821A-376B74E4C4B8';
32
    const Script_Command_Object               = '1EFB1A30-0B62-11D0-A39B-00A0C90348F6';
33
    const No_Error_Correction                 = '20FB5700-5B55-11CF-A8FD-00805F5C442B';
34
    const Content_Branding_Object             = '2211B3FA-BD23-11D2-B4B7-00A0C955FC6E';
35
    const Content_Encryption_Object           = '2211B3FB-BD23-11D2-B4B7-00A0C955FC6E';
36
    const Digital_Signature_Object            = '2211B3FC-BD23-11D2-B4B7-00A0C955FC6E';
37
    const Extended_Content_Encryption_Object  = '298AE614-2622-4C17-B935-DAE07EE9289C';
38
    const Simple_Index_Object                 = '33000890-E5B1-11CF-89F4-00A0C90349CB';
39
    const Degradable_JPEG_Media               = '35907DE0-E415-11CF-A917-00805F5C442B';
40
    const Payload_Extension_System_Timecode   = '399595EC-8667-4E2D-8FDB-98814CE76C1E';
41
    const Binary_Media                        = '3AFB65E2-47EF-40F2-AC2C-70A90D71D343';
42
    const Timecode_Index_Object               = '3CB73FD0-0C4A-4803-953D-EDF7B6228F0C';
43
    const Metadata_Library_Object             = '44231C94-9498-49D1-A141-1D134E457054';
44
    const Reserved_3                          = '4B1ACBE3-100B-11D0-A39B-00A0C90348F6';
45
    const Reserved_4                          = '4CFEDB20-75F6-11CF-9C0F-00A0C90349CB';
46
    const Command_Media                       = '59DACFC0-59E6-11D0-A3AC-00A0C90348F6';
47
    const Header_Extension_Object             = '5FBF03B5-A92E-11CF-8EE3-00C00C205365';
48
    const Media_Object_Index_Parameters_Obj   = '6B203BAD-3F11-4E84-ACA8-D7613DE2CFA7';
49
    const Header_Object                       = '75B22630-668E-11CF-A6D9-00AA0062CE6C';
50
    const Content_Description_Object          = '75B22633-668E-11CF-A6D9-00AA0062CE6C';
51
    const Error_Correction_Object             = '75B22635-668E-11CF-A6D9-00AA0062CE6C';
52
    const Data_Object                         = '75B22636-668E-11CF-A6D9-00AA0062CE6C';
53
    const Web_Stream_Media_Subtype            = '776257D4-C627-41CB-8F81-7AC7FF1C40CC';
54
    const Stream_Bitrate_Properties_Object    = '7BF875CE-468D-11D1-8D82-006097C9A2B2';
55
    const Language_List_Object                = '7C4346A9-EFE0-4BFC-B229-393EDE415C85';
56
    const Codec_List_Object                   = '86D15240-311D-11D0-A3A4-00A0C90348F6';
57
    const Reserved_2                          = '86D15241-311D-11D0-A3A4-00A0C90348F6';
58
    const File_Properties_Object              = '8CABDCA1-A947-11CF-8EE4-00C00C205365';
59
    const File_Transfer_Media                 = '91BD222C-F21C-497A-8B6D-5AA86BFC0185';
60
    const Old_RTP_Extension_Data              = '96800C63-4C94-11D1-837B-0080C7A37F95';
61
    const Advanced_Mutual_Exclusion_Object    = 'A08649CF-4775-4670-8A16-6E35357566CD';
62
    const Bandwidth_Sharing_Object            = 'A69609E6-517B-11D2-B6AF-00C04FD908E9';
63
    const Reserved_1                          = 'ABD3D211-A9BA-11CF-8EE6-00C00C205365';
64
    const Bandwidth_Sharing_Exclusive         = 'AF6060AA-5197-11D2-B6AF-00C04FD908E9';
65
    const Bandwidth_Sharing_Partial           = 'AF6060AB-5197-11D2-B6AF-00C04FD908E9';
66
    const JFIF_Media                          = 'B61BE100-5B4E-11CF-A8FD-00805F5C442B';
67
    const Stream_Properties_Object            = 'B7DC0791-A9B7-11CF-8EE6-00C00C205365';
68
    const Video_Media                         = 'BC19EFC0-5B4D-11CF-A8FD-00805F5C442B';
69
    const Audio_Spread                        = 'BFC3CD50-618F-11CF-8BB2-00AA00B4E220';
70
    const Metadata_Object                     = 'C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA';
71
    const Payload_Ext_Syst_Sample_Duration    = 'C6BD9450-867F-4907-83A3-C77921B733AD';
72
    const Group_Mutual_Exclusion_Object       = 'D1465A40-5A79-4338-B71B-E36B8FD6C249';
73
    const Extended_Content_Description_Object = 'D2D0A440-E307-11D2-97F0-00A0C95EA850';
74
    const Stream_Prioritization_Object        = 'D4FED15B-88D3-454F-81F0-ED5C45999E24';
75
    const Payload_Ext_System_Content_Type     = 'D590DC20-07BC-436C-9CF7-F3BBFBF1A4DC';
76
    const Old_File_Properties_Object          = 'D6E229D0-35DA-11D1-9034-00A0C90349BE';
77
    const Old_ASF_Header_Object               = 'D6E229D1-35DA-11D1-9034-00A0C90349BE';
78
    const Old_ASF_Data_Object                 = 'D6E229D2-35DA-11D1-9034-00A0C90349BE';
79
    const Index_Object                        = 'D6E229D3-35DA-11D1-9034-00A0C90349BE';
80
    const Old_Stream_Properties_Object        = 'D6E229D4-35DA-11D1-9034-00A0C90349BE';
81
    const Old_Content_Description_Object      = 'D6E229D5-35DA-11D1-9034-00A0C90349BE';
82
    const Old_Script_Command_Object           = 'D6E229D6-35DA-11D1-9034-00A0C90349BE';
83
    const Old_Marker_Object                   = 'D6E229D7-35DA-11D1-9034-00A0C90349BE';
84
    const Old_Component_Download_Object       = 'D6E229D8-35DA-11D1-9034-00A0C90349BE';
85
    const Old_Stream_Group_Object             = 'D6E229D9-35DA-11D1-9034-00A0C90349BE';
86
    const Old_Scalable_Object                 = 'D6E229DA-35DA-11D1-9034-00A0C90349BE';
87
    const Old_Prioritization_Object           = 'D6E229DB-35DA-11D1-9034-00A0C90349BE';
88
    const Bitrate_Mutual_Exclusion_Object     = 'D6E229DC-35DA-11D1-9034-00A0C90349BE';
89
    const Old_Inter_Media_Dependency_Object   = 'D6E229DD-35DA-11D1-9034-00A0C90349BE';
90
    const Old_Rating_Object                   = 'D6E229DE-35DA-11D1-9034-00A0C90349BE';
91
    const Index_Parameters_Object             = 'D6E229DF-35DA-11D1-9034-00A0C90349BE';
92
    const Old_Color_Table_Object              = 'D6E229E0-35DA-11D1-9034-00A0C90349BE';
93
    const Old_Language_List_Object            = 'D6E229E1-35DA-11D1-9034-00A0C90349BE';
94
    const Old_Audio_Media                     = 'D6E229E2-35DA-11D1-9034-00A0C90349BE';
95
    const Old_Video_Media                     = 'D6E229E3-35DA-11D1-9034-00A0C90349BE';
96
    const Old_Image_Media                     = 'D6E229E4-35DA-11D1-9034-00A0C90349BE';
97
    const Old_Timecode_Media                  = 'D6E229E5-35DA-11D1-9034-00A0C90349BE';
98
    const Old_Text_Media                      = 'D6E229E6-35DA-11D1-9034-00A0C90349BE';
99
    const Old_MIDI_Media                      = 'D6E229E7-35DA-11D1-9034-00A0C90349BE';
100
    const Old_Command_Media                   = 'D6E229E8-35DA-11D1-9034-00A0C90349BE';
101
    const Old_No_Error_Concealment            = 'D6E229EA-35DA-11D1-9034-00A0C90349BE';
102
    const Old_Scrambled_Audio                 = 'D6E229EB-35DA-11D1-9034-00A0C90349BE';
103
    const Old_No_Color_Table                  = 'D6E229EC-35DA-11D1-9034-00A0C90349BE';
104
    const Old_SMPTE_Time                      = 'D6E229ED-35DA-11D1-9034-00A0C90349BE';
105
    const Old_ASCII_Text                      = 'D6E229EE-35DA-11D1-9034-00A0C90349BE';
106
    const Old_Unicode_Text                    = 'D6E229EF-35DA-11D1-9034-00A0C90349BE';
107
    const Old_HTML_Text                       = 'D6E229F0-35DA-11D1-9034-00A0C90349BE';
108
    const Old_URL_Command                     = 'D6E229F1-35DA-11D1-9034-00A0C90349BE';
109
    const Old_Filename_Command                = 'D6E229F2-35DA-11D1-9034-00A0C90349BE';
110
    const Old_ACM_Codec                       = 'D6E229F3-35DA-11D1-9034-00A0C90349BE';
111
    const Old_VCM_Codec                       = 'D6E229F4-35DA-11D1-9034-00A0C90349BE';
112
    const Old_QuickTime_Codec                 = 'D6E229F5-35DA-11D1-9034-00A0C90349BE';
113
    const Old_DirectShow_Transform_Filter     = 'D6E229F6-35DA-11D1-9034-00A0C90349BE';
114
    const Old_DirectShow_Rendering_Filter     = 'D6E229F7-35DA-11D1-9034-00A0C90349BE';
115
    const Old_No_Enhancement                  = 'D6E229F8-35DA-11D1-9034-00A0C90349BE';
116
    const Old_Unknown_Enhancement_Type        = 'D6E229F9-35DA-11D1-9034-00A0C90349BE';
117
    const Old_Temporal_Enhancement            = 'D6E229FA-35DA-11D1-9034-00A0C90349BE';
118
    const Old_Spatial_Enhancement             = 'D6E229FB-35DA-11D1-9034-00A0C90349BE';
119
    const Old_Quality_Enhancement             = 'D6E229FC-35DA-11D1-9034-00A0C90349BE';
120
    const Old_Number_of_Channels_Enhancement  = 'D6E229FD-35DA-11D1-9034-00A0C90349BE';
121
    const Old_Frequency_Response_Enhancement  = 'D6E229FE-35DA-11D1-9034-00A0C90349BE';
122
    const Old_Media_Object                    = 'D6E229FF-35DA-11D1-9034-00A0C90349BE';
123
    const Mutex_Language                      = 'D6E22A00-35DA-11D1-9034-00A0C90349BE';
124
    const Mutex_Bitrate                       = 'D6E22A01-35DA-11D1-9034-00A0C90349BE';
125
    const Mutex_Unknown                       = 'D6E22A02-35DA-11D1-9034-00A0C90349BE';
126
    const Old_ASF_Placeholder_Object          = 'D6E22A0E-35DA-11D1-9034-00A0C90349BE';
127
    const Old_Data_Unit_Extension_Object      = 'D6E22A0F-35DA-11D1-9034-00A0C90349BE';
128
    const Web_Stream_Format                   = 'DA1E6B13-8359-4050-B398-388E965BF00C';
129
    const Payload_Ext_System_File_Name        = 'E165EC0E-19ED-45D7-B4A7-25CBD1E28E9B';
130
    const Marker_Object                       = 'F487CD01-A951-11CF-8EE6-00C00C205365';
131
    const Timecode_Index_Parameters_Object    = 'F55E496D-9797-4B5D-8C8B-604DFE9BFB24';
132
    const Audio_Media                         = 'F8699E40-5B4D-11CF-A8FD-00805F5C442B';
133
    const Media_Object_Index_Object           = 'FEB103F8-12AD-4C64-840F-2A1D2F7AD48C';
134
    const Alt_Extended_Content_Encryption_Obj = 'FF889EF1-ADEE-40DA-9E71-98704BB928CE';
135
136
137
138
    public function Analyze() {
139
140
        $getid3 = $this->getid3;
141
        
142
        $getid3->include_module('audio-video.riff');
143
144
        !isset($getid3->info['audio']) and $getid3->info['audio'] = array ();
145
        !isset($getid3->info['video']) and $getid3->info['video'] = array ();
146
        $getid3->info['asf']['comments'] = $getid3->info['asf']['header_object'] = array ();
147
            
148
        $info_audio             = &$getid3->info['audio'];
149
        $info_video             = &$getid3->info['video'];
150
        $info_asf               = &$getid3->info['asf'];
151
        $info_asf_comments      = &$info_asf['comments'];
152
        $info_asf_header_object = &$info_asf['header_object'];
153
154
        // ASF structure:
155
        // * Header Object [required]
156
        //   * File Properties Object [required]   (global file attributes)
157
        //   * Stream Properties Object [required] (defines media stream & characteristics)
158
        //   * Header Extension Object [required]  (additional functionality)
159
        //   * Content Description Object          (bibliographic information)
160
        //   * Script Command Object               (commands for during playback)
161
        //   * Marker Object                       (named jumped points within the file)
162
        // * Data Object [required]
163
        //   * Data Packets
164
        // * Index Object
165
166
        // Header Object: (mandatory, one only)
167
        // Field Name                   Field Type   Size (bits)
168
        // Object ID                    GUID         128             // GUID for header object - getid3_asf::Header_Object
169
        // Object Size                  QWORD        64              // size of header object, including 30 bytes of Header Object header
170
        // Number of Header Objects     DWORD        32              // number of objects in header object
171
        // Reserved1                    BYTE         8               // hardcoded: 0x01
172
        // Reserved2                    BYTE         8               // hardcoded: 0x02
173
174
        $getid3->info['fileformat'] = 'asf';
175
176
        fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET);
177
        $header_object_data = fread($getid3->fp, 30);
178
179
        $info_asf_header_object['objectid_guid'] = getid3_asf::BytestringToGUID(substr($header_object_data, 0, 16));
180
        
181
        if ($info_asf_header_object['objectid_guid'] != getid3_asf::Header_Object) {
182
            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.'}');
183
        }
184
        
185
        getid3_lib::ReadSequence('LittleEndian2Int', $info_asf_header_object, $header_object_data, 16,
186
            array (
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
            
199
            $next_object_guid = substr($asf_header_data, $offset, 16);
200
            $offset += 16;
201
            
202
            $next_object_size = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 8));
203
            $offset += 8;
204
            
205
            $next_object_guidtext = getid3_asf::BytestringToGUID($next_object_guid);
206
            
207
            switch ($next_object_guidtext) {
208
209
                case getid3_asf::File_Properties_Object:
210
                
211
                    // File Properties Object: (mandatory, one only)
212
                    // Field Name                   Field Type   Size (bits)
213
                    // Object ID                    GUID         128             // GUID for file properties object - getid3_asf::File_Properties_Object
214
                    // Object Size                  QWORD        64              // size of file properties object, including 104 bytes of File Properties Object header
215
                    // File ID                      GUID         128             // unique ID - identical to File ID in Data Object
216
                    // File Size                    QWORD        64              // entire file in bytes. Invalid if Broadcast Flag == 1
217
                    // Creation Date                QWORD        64              // date & time of file creation. Maybe invalid if Broadcast Flag == 1
218
                    // Data Packets Count           QWORD        64              // number of data packets in Data Object. Invalid if Broadcast Flag == 1
219
                    // Play Duration                QWORD        64              // playtime, in 100-nanosecond units. Invalid if Broadcast Flag == 1
220
                    // Send Duration                QWORD        64              // time needed to send file, in 100-nanosecond units. Players can ignore this value. Invalid if Broadcast Flag == 1
221
                    // 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
222
                    // Flags                        DWORD        32              //
223
                    // * Broadcast Flag             bits         1  (0x01)       // file is currently being written, some header values are invalid
224
                    // * Seekable Flag              bits         1  (0x02)       // is file seekable
225
                    // * Reserved                   bits         30 (0xFFFFFFFC) // reserved - set to zero
226
                    // Minimum Data Packet Size     DWORD        32              // in bytes. should be same as Maximum Data Packet Size. Invalid if Broadcast Flag == 1
227
                    // Maximum Data Packet Size     DWORD        32              // in bytes. should be same as Minimum Data Packet Size. Invalid if Broadcast Flag == 1
228
                    // Maximum Bitrate              DWORD        32              // maximum instantaneous bitrate in bits per second for entire file, including all data streams and ASF overhead
229
230
                    $info_asf['file_properties_object'] = array ();
231
                    $info_asf_file_properties_object = &$info_asf['file_properties_object'];
232
233
                    $info_asf_file_properties_object['objectid_guid']      = $next_object_guidtext;
234
                    $info_asf_file_properties_object['objectsize']         = $next_object_size;
235
                    
236
                    $info_asf_file_properties_object['fileid_guid']        = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
237
                    $offset += 16;
238
239
                    getid3_lib::ReadSequence('LittleEndian2Int', $info_asf_file_properties_object, $asf_header_data, $offset,
240
                        array (
241
                            'filesize'        => 8,
242
                            'creation_date'   => 8,
243
                            'data_packets'    => 8,
244
                            'play_duration'   => 8,
245
                            'send_duration'   => 8,
246
                            'preroll'         => 8,
247
                            'flags_raw'       => 4,
248
                            'min_packet_size' => 4,
249
                            'max_packet_size' => 4,
250
                            'max_bitrate'     => 4
251
                        )
252
                    );
253
                    
254
                    $offset += 64   ;
255
                    
256
                    $info_asf_file_properties_object['creation_date_unix'] = getid3_asf::FiletimeToUNIXtime($info_asf_file_properties_object['creation_date']);
257
                    $info_asf_file_properties_object['flags']['broadcast'] = (bool)($info_asf_file_properties_object['flags_raw'] & 0x0001);
258
                    $info_asf_file_properties_object['flags']['seekable']  = (bool)($info_asf_file_properties_object['flags_raw'] & 0x0002);
259
260
                    $getid3->info['playtime_seconds'] = ($info_asf_file_properties_object['play_duration'] / 10000000) - ($info_asf_file_properties_object['preroll'] / 1000);
261
                    $getid3->info['bitrate']          = ($info_asf_file_properties_object['filesize'] * 8) / $getid3->info['playtime_seconds'];
262
                    break;
263
264
265
                case getid3_asf::Stream_Properties_Object:
266
                    
267
                    // Stream Properties Object: (mandatory, one per media stream)
268
                    // Field Name                   Field Type   Size (bits)
269
                    // Object ID                    GUID         128             // GUID for stream properties object - getid3_asf::Stream_Properties_Object
270
                    // Object Size                  QWORD        64              // size of stream properties object, including 78 bytes of Stream Properties Object header
271
                    // Stream Type                  GUID         128             // getid3_asf::Audio_Media, getid3_asf::Video_Media or getid3_asf::Command_Media
272
                    // Error Correction Type        GUID         128             // getid3_asf::Audio_Spread for audio-only streams, getid3_asf::No_Error_Correction for other stream types
273
                    // Time Offset                  QWORD        64              // 100-nanosecond units. typically zero. added to all timestamps of samples in the stream
274
                    // Type-Specific Data Length    DWORD        32              // number of bytes for Type-Specific Data field
275
                    // Error Correction Data Length DWORD        32              // number of bytes for Error Correction Data field
276
                    // Flags                        WORD         16              //
277
                    // * Stream Number              bits         7 (0x007F)      // number of this stream.  1 <= valid <= 127
278
                    // * Reserved                   bits         8 (0x7F80)      // reserved - set to zero
279
                    // * Encrypted Content Flag     bits         1 (0x8000)      // stream contents encrypted if set
280
                    // Reserved                     DWORD        32              // reserved - set to zero
281
                    // Type-Specific Data           BYTESTREAM   variable        // type-specific format data, depending on value of Stream Type
282
                    // Error Correction Data        BYTESTREAM   variable        // error-correction-specific format data, depending on value of Error Correct Type
283
284
                    // There is one getid3_asf::Stream_Properties_Object for each stream (audio, video) but the
285
                    // stream number isn't known until halfway through decoding the structure, hence it
286
                    // it is decoded to a temporary variable and then stuck in the appropriate index later
287
288
                    $stream_properties_object_data['objectid_guid']      = $next_object_guidtext;
289
                    $stream_properties_object_data['objectsize']         = $next_object_size;
290
                    
291
                    getid3_lib::ReadSequence('LittleEndian2Int', $stream_properties_object_data, $asf_header_data, $offset,
292
                        array (
293
                            'stream_type'        => -16,
294
                            'error_correct_type' => -16,
295
                            'time_offset'        => 8,
296
                            'type_data_length'   => 4,
297
                            'error_data_length'  => 4,
298
                            'flags_raw'          => 2
299
                        )
300
                    );
301
302
                    $stream_properties_stream_number                     =        $stream_properties_object_data['flags_raw'] & 0x007F;
303
                    $stream_properties_object_data['flags']['encrypted'] = (bool)($stream_properties_object_data['flags_raw'] & 0x8000);
304
305
                    $stream_properties_object_data['stream_type_guid']   = getid3_asf::BytestringToGUID($stream_properties_object_data['stream_type']);
306
                    $stream_properties_object_data['error_correct_guid'] = getid3_asf::BytestringToGUID($stream_properties_object_data['error_correct_type']);
307
308
                    $offset += 54; // 50 bytes + 4 bytes reserved - DWORD
309
                    
310
                    $stream_properties_object_data['type_specific_data'] = substr($asf_header_data, $offset, $stream_properties_object_data['type_data_length']);
311
                    $offset += $stream_properties_object_data['type_data_length'];
312
                    
313
                    $stream_properties_object_data['error_correct_data'] = substr($asf_header_data, $offset, $stream_properties_object_data['error_data_length']);
314
                    $offset += $stream_properties_object_data['error_data_length'];
315
316
                    switch ($stream_properties_object_data['stream_type_guid']) {
317
318
                        case getid3_asf::Audio_Media:
319
                    
320
                            $info_audio['dataformat']   = (@$info_audio['dataformat']   ? $info_audio['dataformat']   : 'asf');
321
                            $info_audio['bitrate_mode'] = (@$info_audio['bitrate_mode'] ? $info_audio['bitrate_mode'] : 'cbr');
322
323
                            $audiodata = getid3_riff::RIFFparseWAVEFORMATex(substr($stream_properties_object_data['type_specific_data'], 0, 16));
324
                            unset($audiodata['raw']);
325
                            $info_audio = getid3_riff::array_merge_noclobber($audiodata, $info_audio);
326
                            break;
327
328
329
                        case getid3_asf::Video_Media:
330
331
                            $info_video['dataformat']   = (@$info_video['dataformat']   ? $info_video['dataformat']   : 'asf');
332
                            $info_video['bitrate_mode'] = (@$info_video['bitrate_mode'] ? $info_video['bitrate_mode'] : 'cbr');
333
                            break;
334
335
336
                        /* does nothing but eat memory
337
                        case getid3_asf::Command_Media:
338
                        default:
339
                            // do nothing
340
                            break;
341
                        */
342
                    }
343
344
                    $info_asf['stream_properties_object'][$stream_properties_stream_number] = $stream_properties_object_data;
345
                    unset($stream_properties_object_data); // clear for next stream, if any
346
                    break;
347
                    
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'] = array ();
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 ($info_asf_header_extension_object['reserved_2'] != 6) {
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
389
                case getid3_asf::Codec_List_Object:
390
                    
391
                    // Codec List Object: (optional, one only)
392
                    // Field Name                   Field Type   Size (bits)
393
                    // Object ID                    GUID         128             // GUID for Codec List object - getid3_asf::Codec_List_Object
394
                    // Object Size                  QWORD        64              // size of Codec List object, including 44 bytes of Codec List Object header
395
                    // Reserved                     GUID         128             // hardcoded: 86D15241-311D-11D0-A3A4-00A0C90348F6
396
                    // Codec Entries Count          DWORD        32              // number of entries in Codec Entries array
397
                    // Codec Entries                array of:    variable        //
398
                    // * Type                       WORD         16              // 0x0001 = Video Codec, 0x0002 = Audio Codec, 0xFFFF = Unknown Codec
399
                    // * Codec Name Length          WORD         16              // number of Unicode characters stored in the Codec Name field
400
                    // * Codec Name                 WCHAR        variable        // array of Unicode characters - name of codec used to create the content
401
                    // * Codec Description Length   WORD         16              // number of Unicode characters stored in the Codec Description field
402
                    // * Codec Description          WCHAR        variable        // array of Unicode characters - description of format used to create the content
403
                    // * Codec Information Length   WORD         16              // number of Unicode characters stored in the Codec Information field
404
                    // * Codec Information          BYTESTREAM   variable        // opaque array of information bytes about the codec used to create the content
405
406
                    $info_asf['codec_list_object'] = array ();
407
                    $info_asf_codec_list_object      = &$info_asf['codec_list_object'];
408
409
                    $info_asf_codec_list_object['objectid_guid'] = $next_object_guidtext;
410
                    $info_asf_codec_list_object['objectsize']    = $next_object_size;
411
                    
412
                    $info_asf_codec_list_object['reserved_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
413
                    $offset += 16;
414
                    
415
                    if ($info_asf_codec_list_object['reserved_guid'] != '86D15241-311D-11D0-A3A4-00A0C90348F6') {
416
                        $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}');
417
                        break;
418
                    }
419
                    
420
                    $info_asf_codec_list_object['codec_entries_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
421
                    $offset += 4;
422
                    
423
                    for ($codec_entry_counter = 0; $codec_entry_counter < $info_asf_codec_list_object['codec_entries_count']; $codec_entry_counter++) {
424
                        
425
                        $info_asf_codec_list_object['codec_entries'][$codec_entry_counter] = array ();
426
                        $info_asf_codec_list_object_codecentries_current = &$info_asf_codec_list_object['codec_entries'][$codec_entry_counter];
427
428
                        $info_asf_codec_list_object_codecentries_current['type_raw'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
429
                        $offset += 2;
430
                        
431
                        $info_asf_codec_list_object_codecentries_current['type'] = getid3_asf::ASFCodecListObjectTypeLookup($info_asf_codec_list_object_codecentries_current['type_raw']);
432
433
                        $codec_name_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2)) * 2; // 2 bytes per character
434
                        $offset += 2;
435
                        
436
                        $info_asf_codec_list_object_codecentries_current['name'] = substr($asf_header_data, $offset, $codec_name_length);
437
                        $offset += $codec_name_length;
438
439
                        $codec_description_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2)) * 2; // 2 bytes per character
440
                        $offset += 2;
441
                        
442
                        $info_asf_codec_list_object_codecentries_current['description'] = substr($asf_header_data, $offset, $codec_description_length);
443
                        $offset += $codec_description_length;
444
445
                        $codec_information_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
446
                        $offset += 2;
447
                        
448
                        $info_asf_codec_list_object_codecentries_current['information'] = substr($asf_header_data, $offset, $codec_information_length);
449
                        $offset += $codec_information_length;
450
451
                        if ($info_asf_codec_list_object_codecentries_current['type_raw'] == 2) {
452
                            
453
                            // audio codec
454
                            if (strpos($info_asf_codec_list_object_codecentries_current['description'], ',') === false) {
455
                                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'].'"');
456
                            }
457
                            list($audio_codec_bitrate, $audio_codec_frequency, $audio_codec_channels) = explode(',', $this->TrimConvert($info_asf_codec_list_object_codecentries_current['description']));
458
                            $info_audio['codec'] = $this->TrimConvert($info_asf_codec_list_object_codecentries_current['name']);
459
460
                            if (!isset($info_audio['bitrate']) && strstr($audio_codec_bitrate, 'kbps')) {
461
                                $info_audio['bitrate'] = (int)(trim(str_replace('kbps', '', $audio_codec_bitrate)) * 1000);
462
                            }
463
464
                            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)) {
465
                                $info_video['bitrate'] = $info_asf['file_properties_object']['max_bitrate'] - $info_audio['bitrate'];
466
                            }
467
                            
468
                            if (!@$info_video['bitrate'] && @$info_audio['bitrate'] && @$getid3->info['bitrate']) {
469
								$info_video['bitrate'] = $getid3->info['bitrate'] - $info_audio['bitrate'];
470
							}
471
472
                            $audio_codec_frequency = (int)trim(str_replace('kHz', '', $audio_codec_frequency));
473
474
                            static $sample_rate_lookup = array (
475
                                8  =>  8000,    8000 =>  8000,
476
                                11 => 11025,   11025 => 11025,
477
                                12 => 12000,   12000 => 12000,
478
                                16 => 16000,   16000 => 16000,
479
                                22 => 22050,   22050 => 22050,
480
                                24 => 24000,   24000 => 24000,
481
                                32 => 32000,   32000 => 32000,
482
                                44 => 44100,   44100 => 44100,
483
                                48 => 48000,   48000 => 48000,
484
                            );
485
486
                            $info_audio['sample_rate'] = @$sample_rate_lookup[$audio_codec_frequency];
487
488
                            if (!$info_audio['sample_rate']) {
489
                                $getid3->warning('unknown frequency: "'.$audio_codec_frequency.'" ('.$this->TrimConvert($info_asf_codec_list_object_codecentries_current['description']).')');
490
                                break;
491
                            }
492
493
                            if (!isset($info_audio['channels'])) {
494
                                if (strstr($audio_codec_channels, 'stereo')) {
495
                                    $info_audio['channels'] = 2;
496
                                } elseif (strstr($audio_codec_channels, 'mono')) {
497
                                    $info_audio['channels'] = 1;
498
                                }
499
                            }
500
                        }
501
                    }
502
                    break;
503
504
505
                case getid3_asf::Script_Command_Object:
506
507
                    // Script Command Object: (optional, one only)
508
                    // Field Name                   Field Type   Size (bits)
509
                    // Object ID                    GUID         128             // GUID for Script Command object - getid3_asf::Script_Command_Object
510
                    // Object Size                  QWORD        64              // size of Script Command object, including 44 bytes of Script Command Object header
511
                    // Reserved                     GUID         128             // hardcoded: 4B1ACBE3-100B-11D0-A39B-00A0C90348F6
512
                    // Commands Count               WORD         16              // number of Commands structures in the Script Commands Objects
513
                    // Command Types Count          WORD         16              // number of Command Types structures in the Script Commands Objects
514
                    // Command Types                array of:    variable        //
515
                    // * Command Type Name Length   WORD         16              // number of Unicode characters for Command Type Name
516
                    // * Command Type Name          WCHAR        variable        // array of Unicode characters - name of a type of command
517
                    // Commands                     array of:    variable        //
518
                    // * Presentation Time          DWORD        32              // presentation time of that command, in milliseconds
519
                    // * Type Index                 WORD         16              // type of this command, as a zero-based index into the array of Command Types of this object
520
                    // * Command Name Length        WORD         16              // number of Unicode characters for Command Name
521
                    // * Command Name               WCHAR        variable        // array of Unicode characters - name of this command
522
523
                    // shortcut
524
                    $info_asf['script_command_object'] = array ();
525
                    $info_asf_script_command_object    = &$info_asf['script_command_object'];
526
527
                    $info_asf_script_command_object['objectid_guid'] = $next_object_guidtext;
528
                    $info_asf_script_command_object['objectsize']    = $next_object_size;
529
                    $info_asf_script_command_object['reserved_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
530
                    $offset += 16;
531
                    
532
                    if ($info_asf_script_command_object['reserved_guid'] != '4B1ACBE3-100B-11D0-A39B-00A0C90348F6') {
533
                        $getid3->warning('script_command_object.reserved GUID {'.$info_asf_script_command_object['reserved_guid'].'} does not match expected GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}');
534
                        break;
535
                    }
536
                    
537
                    $info_asf_script_command_object['commands_count']       = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
538
                    $offset += 2;
539
                    
540
                    $info_asf_script_command_object['command_types_count']  = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
541
                    $offset += 2;
542
                    
543
                    for ($command_types_counter = 0; $command_types_counter < $info_asf_script_command_object['command_types_count']; $command_types_counter++) {
544
                        
545
                        $command_type_name_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2)) * 2; // 2 bytes per character
546
                        $offset += 2;
547
                        
548
                        $info_asf_script_command_object['command_types'][$command_types_counter]['name'] = substr($asf_header_data, $offset, $command_type_name_length);
549
                        $offset += $command_type_name_length;
550
                    }
551
                    
552
                    for ($commands_counter = 0; $commands_counter < $info_asf_script_command_object['commands_count']; $commands_counter++) {
553
                        
554
                        $info_asf_script_command_object['commands'][$commands_counter]['presentation_time'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
555
                        $offset += 4;
556
                        
557
                        $info_asf_script_command_object['commands'][$commands_counter]['type_index']        = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
558
                        $offset += 2;
559
560
                        $command_type_name_length                                                           = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2)) * 2; // 2 bytes per character
561
                        $offset += 2;
562
                        
563
                        $info_asf_script_command_object['commands'][$commands_counter]['name']              = substr($asf_header_data, $offset, $command_type_name_length);
564
                        $offset += $command_type_name_length;
565
                    }
566
                    break;
567
568
569
                case getid3_asf::Marker_Object:
570
571
                    // Marker Object: (optional, one only)
572
                    // Field Name                   Field Type   Size (bits)
573
                    // Object ID                    GUID         128             // GUID for Marker object - getid3_asf::Marker_Object
574
                    // Object Size                  QWORD        64              // size of Marker object, including 48 bytes of Marker Object header
575
                    // Reserved                     GUID         128             // hardcoded: 4CFEDB20-75F6-11CF-9C0F-00A0C90349CB
576
                    // Markers Count                DWORD        32              // number of Marker structures in Marker Object
577
                    // Reserved                     WORD         16              // hardcoded: 0x0000
578
                    // Name Length                  WORD         16              // number of bytes in the Name field
579
                    // Name                         WCHAR        variable        // name of the Marker Object
580
                    // Markers                      array of:    variable        //
581
                    // * Offset                     QWORD        64              // byte offset into Data Object
582
                    // * Presentation Time          QWORD        64              // in 100-nanosecond units
583
                    // * Entry Length               WORD         16              // length in bytes of (Send Time + Flags + Marker Description Length + Marker Description + Padding)
584
                    // * Send Time                  DWORD        32              // in milliseconds
585
                    // * Flags                      DWORD        32              // hardcoded: 0x00000000
586
                    // * Marker Description Length  DWORD        32              // number of bytes in Marker Description field
587
                    // * Marker Description         WCHAR        variable        // array of Unicode characters - description of marker entry
588
                    // * Padding                    BYTESTREAM   variable        // optional padding bytes
589
590
                    $info_asf['marker_object'] = array ();
591
                    $info_asf_marker_object    = &$info_asf['marker_object'];
592
593
                    $info_asf_marker_object['objectid_guid'] = $next_object_guidtext;
594
                    $info_asf_marker_object['objectsize']    = $next_object_size;
595
                    $info_asf_marker_object['reserved_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
596
                    $offset += 16;                           
597
                    
598
                    if ($info_asf_marker_object['reserved_guid'] != '4CFEDB20-75F6-11CF-9C0F-00A0C90349CB') {
599
                        $getid3->warning('marker_object.reserved GUID {'.$info_asf_marker_object['reserved_guid'].'} does not match expected GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}');
600
                        break;
601
                    }
602
                    
603
                    $info_asf_marker_object['markers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
604
                    $offset += 4;
605
                    
606
                    $info_asf_marker_object['reserved_2']    = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
607
                    $offset += 2;
608
                    
609
                    if ($info_asf_marker_object['reserved_2'] != 0) {
610
                        $getid3->warning('marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($info_asf_marker_object['reserved_2']).') does not match expected value of "0"');
611
                        break;
612
                    }
613
                    
614
                    $info_asf_marker_object['name_length']   = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
615
                    $offset += 2;
616
                    
617
                    $info_asf_marker_object['name'] = substr($asf_header_data, $offset, $info_asf_marker_object['name_length']);
618
                    $offset += $info_asf_marker_object['name_length'];
619
                    
620
                    for ($markers_counter = 0; $markers_counter < $info_asf_marker_object['markers_count']; $markers_counter++) {
621
                        
622
                        getid3_lib::ReadSequence('LittleEndian2Int', $info_asf_marker_object['markers'][$markers_counter], $asf_header_data, $offset,
623
                            array (
624
                                'offset'                    => 8,
625
                                'presentation_time'         => 8,
626
                                'entry_length'              => 2,
627
                                'send_time'                 => 4,
628
                                'flags'                     => 4,
629
                                'marker_description_length' => 4
630
                            )
631
                        );
632
                        $offset += 30;
633
                        
634
                        $info_asf_marker_object['markers'][$markers_counter]['marker_description'] = substr($asf_header_data, $offset, $info_asf_marker_object['markers'][$markers_counter]['marker_description_length']);
635
                        $offset += $info_asf_marker_object['markers'][$markers_counter]['marker_description_length'];
636
                        
637
                        $padding_length = $info_asf_marker_object['markers'][$markers_counter]['entry_length'] - 4 -  4 - 4 - $info_asf_marker_object['markers'][$markers_counter]['marker_description_length'];
638
                        if ($padding_length > 0) {
639
                            $info_asf_marker_object['markers'][$markers_counter]['padding'] = substr($asf_header_data, $offset, $padding_length);
640
                            $offset += $padding_length;
641
                        }
642
                    }
643
                    break;
644
                    
645
646
                case getid3_asf::Bitrate_Mutual_Exclusion_Object:
647
                    
648
                    // Bitrate Mutual Exclusion Object: (optional)
649
                    // Field Name                   Field Type   Size (bits)
650
                    // Object ID                    GUID         128             // GUID for Bitrate Mutual Exclusion object - getid3_asf::Bitrate_Mutual_Exclusion_Object
651
                    // Object Size                  QWORD        64              // size of Bitrate Mutual Exclusion object, including 42 bytes of Bitrate Mutual Exclusion Object header
652
                    // Exlusion Type                GUID         128             // nature of mutual exclusion relationship. one of: (getid3_asf::Mutex_Bitrate, getid3_asf::Mutex_Unknown)
653
                    // Stream Numbers Count         WORD         16              // number of video streams
654
                    // Stream Numbers               WORD         variable        // array of mutually exclusive video stream numbers. 1 <= valid <= 127
655
656
                    // shortcut
657
                    $info_asf['bitrate_mutual_exclusion_object'] = array ();
658
                    $info_asf_bitrate_mutual_exclusion_object    = &$info_asf['bitrate_mutual_exclusion_object'];
659
660
                    $info_asf_bitrate_mutual_exclusion_object['objectid_guid'] = $next_object_guidtext;
661
                    $info_asf_bitrate_mutual_exclusion_object['objectsize']    = $next_object_size;
662
                    $info_asf_bitrate_mutual_exclusion_object['reserved_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
663
                    $offset += 16;
664
                    
665
                    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) {
666
                        $getid3->warning('bitrate_mutual_exclusion_object.reserved GUID {'.$info_asf_bitrate_mutual_exclusion_object['reserved_guid'].'} does not match expected "getid3_asf::Mutex_Bitrate" GUID {'.getid3_asf::Mutex_Bitrate.'} or  "getid3_asf::Mutex_Unknown" GUID {'.getid3_asf::Mutex_Unknown.'}');
667
                        break;
668
                    }
669
                    
670
                    $info_asf_bitrate_mutual_exclusion_object['stream_numbers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
671
                    $offset += 2;
672
                    
673
                    for ($stream_number_counter = 0; $stream_number_counter < $info_asf_bitrate_mutual_exclusion_object['stream_numbers_count']; $stream_number_counter++) {
674
                        $info_asf_bitrate_mutual_exclusion_object['stream_numbers'][$stream_number_counter] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
675
                        $offset += 2;
676
                    }
677
                    break;
678
679
680
                case getid3_asf::Error_Correction_Object:
681
682
                    // Error Correction Object: (optional, one only)
683
                    // Field Name                   Field Type   Size (bits)
684
                    // Object ID                    GUID         128             // GUID for Error Correction object - getid3_asf::Error_Correction_Object
685
                    // Object Size                  QWORD        64              // size of Error Correction object, including 44 bytes of Error Correction Object header
686
                    // Error Correction Type        GUID         128             // type of error correction. one of: (getid3_asf::No_Error_Correction, getid3_asf::Audio_Spread)
687
                    // Error Correction Data Length DWORD        32              // number of bytes in Error Correction Data field
688
                    // Error Correction Data        BYTESTREAM   variable        // structure depends on value of Error Correction Type field
689
690
                    $info_asf['error_correction_object'] = array ();
691
                    $info_asf_error_correction_object      = &$info_asf['error_correction_object'];
692
693
                    $info_asf_error_correction_object['objectid_guid']         = $next_object_guidtext;
694
                    $info_asf_error_correction_object['objectsize']            = $next_object_size;
695
                    $info_asf_error_correction_object['error_correction_type'] = substr($asf_header_data, $offset, 16);
696
                    $offset += 16;
697
                    
698
                    $info_asf_error_correction_object['error_correction_guid']        = getid3_asf::BytestringToGUID($info_asf_error_correction_object['error_correction_type']);
699
                    $info_asf_error_correction_object['error_correction_data_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
700
                    $offset += 4;
701
                    
702
                    switch ($info_asf_error_correction_object['error_correction_type_guid']) {
703
                    
704
                        case getid3_asf::No_Error_Correction:
705
                    
706
                            // should be no data, but just in case there is, skip to the end of the field
707
                            $offset += $info_asf_error_correction_object['error_correction_data_length'];
708
                            break;
709
710
711
                        case getid3_asf::Audio_Spread:
712
713
                            // Field Name                   Field Type   Size (bits)
714
                            // Span                         BYTE         8               // number of packets over which audio will be spread.
715
                            // Virtual Packet Length        WORD         16              // size of largest audio payload found in audio stream
716
                            // Virtual Chunk Length         WORD         16              // size of largest audio payload found in audio stream
717
                            // Silence Data Length          WORD         16              // number of bytes in Silence Data field
718
                            // Silence Data                 BYTESTREAM   variable        // hardcoded: 0x00 * (Silence Data Length) bytes
719
720
                            getid3_lib::ReadSequence('LittleEndian2Int', $info_asf_error_correction_object, $asf_header_data, $offset, 
721
                                array (
722
                                    'span'                  => 1,
723
                                    'virtual_packet_length' => 2,
724
                                    'virtual_chunk_length'  => 2,
725
                                    'silence_data_length'   => 2
726
                                )
727
                            );
728
                            $offset += 7;
729
                            
730
                            $info_asf_error_correction_object['silence_data'] = substr($asf_header_data, $offset, $info_asf_error_correction_object['silence_data_length']);
731
                            $offset += $info_asf_error_correction_object['silence_data_length'];
732
                            break;
733
734
                        default:
735
                            $getid3->warning('error_correction_object.error_correction_type GUID {'.$info_asf_error_correction_object['reserved_guid'].'} does not match expected "getid3_asf::No_Error_Correction" GUID {'.getid3_asf::No_Error_Correction.'} or  "getid3_asf::Audio_Spread" GUID {'.getid3_asf::Audio_Spread.'}');
736
                            break;
737
                    }
738
739
                    break;
740
741
742
                case getid3_asf::Content_Description_Object:
743
744
                    // Content Description Object: (optional, one only)
745
                    // Field Name                   Field Type   Size (bits)
746
                    // Object ID                    GUID         128             // GUID for Content Description object - getid3_asf::Content_Description_Object
747
                    // Object Size                  QWORD        64              // size of Content Description object, including 34 bytes of Content Description Object header
748
                    // Title Length                 WORD         16              // number of bytes in Title field
749
                    // Author Length                WORD         16              // number of bytes in Author field
750
                    // Copyright Length             WORD         16              // number of bytes in Copyright field
751
                    // Description Length           WORD         16              // number of bytes in Description field
752
                    // Rating Length                WORD         16              // number of bytes in Rating field
753
                    // Title                        WCHAR        16              // array of Unicode characters - Title
754
                    // Author                       WCHAR        16              // array of Unicode characters - Author
755
                    // Copyright                    WCHAR        16              // array of Unicode characters - Copyright
756
                    // Description                  WCHAR        16              // array of Unicode characters - Description
757
                    // Rating                       WCHAR        16              // array of Unicode characters - Rating
758
759
                    $info_asf['content_description_object'] = array ();
760
                    $info_asf_content_description_object      = &$info_asf['content_description_object'];
761
762
                    $info_asf_content_description_object['objectid_guid'] = $next_object_guidtext;
763
                    $info_asf_content_description_object['objectsize']    = $next_object_size;
764
                    
765
                    getid3_lib::ReadSequence('LittleEndian2Int', $info_asf_content_description_object, $asf_header_data, $offset, 
766
                        array (
767
                            'title_length'       => 2,
768
                            'author_length'      => 2,
769
                            'copyright_length'   => 2,
770
                            'description_length' => 2,
771
                            'rating_length'      => 2
772
                        )
773
                    );
774
                    $offset += 10;
775
                    
776
                    $info_asf_content_description_object['title']       = substr($asf_header_data, $offset, $info_asf_content_description_object['title_length']);
777
                    $offset += $info_asf_content_description_object['title_length'];
778
                    
779
                    $info_asf_content_description_object['author']      = substr($asf_header_data, $offset, $info_asf_content_description_object['author_length']);
780
                    $offset += $info_asf_content_description_object['author_length'];
781
                    
782
                    $info_asf_content_description_object['copyright']   = substr($asf_header_data, $offset, $info_asf_content_description_object['copyright_length']);
783
                    $offset += $info_asf_content_description_object['copyright_length'];
784
                    
785
                    $info_asf_content_description_object['description'] = substr($asf_header_data, $offset, $info_asf_content_description_object['description_length']);
786
                    $offset += $info_asf_content_description_object['description_length'];
787
                    
788
                    $info_asf_content_description_object['rating']      = substr($asf_header_data, $offset, $info_asf_content_description_object['rating_length']);
789
                    $offset += $info_asf_content_description_object['rating_length'];
790
791
                    foreach (array ('title'=>'title', 'author'=>'artist', 'copyright'=>'copyright', 'description'=>'comment', 'rating'=>'rating') as $key_to_copy_from => $key_to_copy_to) {
792
                        if (!empty($info_asf_content_description_object[$key_to_copy_from])) {
793
                            $info_asf_comments[$key_to_copy_to][] = getid3_asf::TrimTerm($info_asf_content_description_object[$key_to_copy_from]);
794
                        }
795
                    }
796
                    break;
797
798
799
                case getid3_asf::Extended_Content_Description_Object:
800
801
                    // Extended Content Description Object: (optional, one only)
802
                    // Field Name                   Field Type   Size (bits)
803
                    // Object ID                    GUID         128             // GUID for Extended Content Description object - getid3_asf::Extended_Content_Description_Object
804
                    // Object Size                  QWORD        64              // size of ExtendedContent Description object, including 26 bytes of Extended Content Description Object header
805
                    // Content Descriptors Count    WORD         16              // number of entries in Content Descriptors list
806
                    // Content Descriptors          array of:    variable        //
807
                    // * Descriptor Name Length     WORD         16              // size in bytes of Descriptor Name field
808
                    // * Descriptor Name            WCHAR        variable        // array of Unicode characters - Descriptor Name
809
                    // * Descriptor Value Data Type WORD         16              // Lookup array:
810
                                                                                    // 0x0000 = Unicode String (variable length)
811
                                                                                    // 0x0001 = BYTE array     (variable length)
812
                                                                                    // 0x0002 = BOOL           (DWORD, 32 bits)
813
                                                                                    // 0x0003 = DWORD          (DWORD, 32 bits)
814
                                                                                    // 0x0004 = QWORD          (QWORD, 64 bits)
815
                                                                                    // 0x0005 = WORD           (WORD,  16 bits)
816
                    // * Descriptor Value Length    WORD         16              // number of bytes stored in Descriptor Value field
817
                    // * Descriptor Value           variable     variable        // value for Content Descriptor
818
819
                    $info_asf['extended_content_description_object'] = array ();
820
                    $info_asf_extended_content_description_object       = &$info_asf['extended_content_description_object'];
821
822
                    $info_asf_extended_content_description_object['objectid_guid']             = $next_object_guidtext;
823
                    $info_asf_extended_content_description_object['objectsize']                = $next_object_size;
824
                    $info_asf_extended_content_description_object['content_descriptors_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
825
                    $offset += 2;
826
                    
827
                    for ($extended_content_descriptors_counter = 0; $extended_content_descriptors_counter < $info_asf_extended_content_description_object['content_descriptors_count']; $extended_content_descriptors_counter++) {
828
                        
829
                        $info_asf_extended_content_description_object['content_descriptors'][$extended_content_descriptors_counter] = array ();
830
                        $info_asf_extended_content_description_object_content_descriptor_current                                  = &$info_asf_extended_content_description_object['content_descriptors'][$extended_content_descriptors_counter];
831
832
                        $info_asf_extended_content_description_object_content_descriptor_current['base_offset']  = $offset + 30;
833
                        $info_asf_extended_content_description_object_content_descriptor_current['name_length']  = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
834
                        $offset += 2;
835
                        
836
                        $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']);
837
                        $offset += $info_asf_extended_content_description_object_content_descriptor_current['name_length'];
838
                        
839
                        $info_asf_extended_content_description_object_content_descriptor_current['value_type']   = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
840
                        $offset += 2;
841
                        
842
                        $info_asf_extended_content_description_object_content_descriptor_current['value_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
843
                        $offset += 2;
844
                        
845
                        $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']);
846
                        $offset += $info_asf_extended_content_description_object_content_descriptor_current['value_length'];
847
                        
848
                        switch ($info_asf_extended_content_description_object_content_descriptor_current['value_type']) {
849
                            
850
                            case 0x0000: // Unicode string
851
                                break;
852
853
                            case 0x0001: // BYTE array
854
                                // do nothing
855
                                break;
856
857
                            case 0x0002: // BOOL
858
                                $info_asf_extended_content_description_object_content_descriptor_current['value'] = (bool)getid3_lib::LittleEndian2Int($info_asf_extended_content_description_object_content_descriptor_current['value']);
859
                                break;
860
861
                            case 0x0003: // DWORD
862
                            case 0x0004: // QWORD
863
                            case 0x0005: // WORD
864
                                $info_asf_extended_content_description_object_content_descriptor_current['value'] = getid3_lib::LittleEndian2Int($info_asf_extended_content_description_object_content_descriptor_current['value']);
865
                                break;
866
867
                            default:
868
                                $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'].')');
869
                                break;
870
                        }
871
                        
872
                        switch ($this->TrimConvert(strtolower($info_asf_extended_content_description_object_content_descriptor_current['name']))) {
873
874
                            case 'wm/albumartist':
875
                            case 'artist':
876
                                $info_asf_comments['artist'] = array (getid3_asf::TrimTerm($info_asf_extended_content_description_object_content_descriptor_current['value']));
877
                                break;
878
879
880
                            case 'wm/albumtitle':
881
                            case 'album':
882
                                $info_asf_comments['album']  = array (getid3_asf::TrimTerm($info_asf_extended_content_description_object_content_descriptor_current['value']));
883
                                break;
884
885
886
                            case 'wm/genre':
887
                            case 'genre':
888
                                $genre = getid3_asf::TrimTerm($info_asf_extended_content_description_object_content_descriptor_current['value']);
889
                                $info_asf_comments['genre'] = array ($genre);
890
                                break;
891
892
893
                            case 'wm/tracknumber':
894
                            case 'tracknumber':
895
                                $info_asf_comments['track'] = array (intval(getid3_asf::TrimTerm($info_asf_extended_content_description_object_content_descriptor_current['value'])));
896
                                break;
897
898
899
                            case 'wm/track':
900
                                if (empty($info_asf_comments['track'])) {
901
                                    $info_asf_comments['track'] = array (1 + $this->TrimConvert($info_asf_extended_content_description_object_content_descriptor_current['value']));
902
                                }
903
                                break;
904
905
906
                            case 'wm/year':
907
                            case 'year':
908
                            case 'date':
909
                                $info_asf_comments['year'] = array ( getid3_asf::TrimTerm($info_asf_extended_content_description_object_content_descriptor_current['value']));
910
                                break;
911
                                
912
                                
913
                            case 'wm/lyrics':
914
                            case 'lyrics':
915
                                $info_asf_comments['lyrics'] = array ( getid3_asf::TrimTerm($info_asf_extended_content_description_object_content_descriptor_current['value']));
916
  	                            break;
917
                            
918
                            
919
                            case 'isvbr':
920
                                if ($info_asf_extended_content_description_object_content_descriptor_current['value']) {
921
                                    $info_audio['bitrate_mode'] = 'vbr';
922
                                    $info_video['bitrate_mode'] = 'vbr';
923
                                }
924
                                break;
925
926
927
                            case 'id3':
928
								
929
								// id3v2 parsing might not be enabled
930
								if (class_exists('getid3_id3v2')) {
931
									
932
									// Clone getid3 
933
                                    $clone = clone $getid3;
934
                                    
935
                                    // Analyse clone by string
936
                                    $id3v2 = new getid3_id3v2($clone);
937
                                    $id3v2->AnalyzeString($info_asf_extended_content_description_object_content_descriptor_current['value']);
938
                                    
939
                                    // Import from clone and destroy
940
                                    $getid3->info['id3v2'] = $clone->info['id3v2'];
941
                                    $getid3->warnings($clone->warnings());
942
                                    unset($clone);
943
								}
944
								break;
945
946
947
                            case 'wm/encodingtime':
948
                                $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']);
949
                                $info_asf_comments['encoding_time_unix'] = array ($info_asf_extended_content_description_object_content_descriptor_current['encoding_time_unix']);
950
                                break;
951
952
953
                            case 'wm/picture':
954
                                
955
                                //typedef struct _WMPicture{
956
                                //  LPWSTR  pwszMIMEType;
957
                                //  BYTE  bPictureType;
958
                                //  LPWSTR  pwszDescription;
959
                                //  DWORD  dwDataLen;
960
                                //  BYTE*  pbData;
961
                                //} WM_PICTURE;
962
963
                                $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});
964
                                $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']);
965
                                $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));
966
                                $info_asf_extended_content_description_object_content_descriptor_current['image_mime']   = '';
967
                                
968
                                $wm_picture_offset = 5;
969
                                
970
                                do {
971
                                    $next_byte_pair = substr($info_asf_extended_content_description_object_content_descriptor_current['value'], $wm_picture_offset, 2);
972
                                    $wm_picture_offset += 2;
973
                                    $info_asf_extended_content_description_object_content_descriptor_current['image_mime'] .= $next_byte_pair;
974
                                } while ($next_byte_pair !== "\x00\x00");
975
976
                                $info_asf_extended_content_description_object_content_descriptor_current['image_description'] = '';
977
                                
978
                                do {
979
                                    $next_byte_pair = substr($info_asf_extended_content_description_object_content_descriptor_current['value'], $wm_picture_offset, 2);
980
                                    $wm_picture_offset += 2;
981
                                    $info_asf_extended_content_description_object_content_descriptor_current['image_description'] .= $next_byte_pair;
982
                                } while ($next_byte_pair !== "\x00\x00");
983
984
                                $info_asf_extended_content_description_object_content_descriptor_current['dataoffset'] = $wm_picture_offset;
985
                                $info_asf_extended_content_description_object_content_descriptor_current['data']       = substr($info_asf_extended_content_description_object_content_descriptor_current['value'], $wm_picture_offset);
986
                                unset($info_asf_extended_content_description_object_content_descriptor_current['value']);
987
                                break;
988
989
                            default:
990
                                switch ($info_asf_extended_content_description_object_content_descriptor_current['value_type']) {
991
                                    case 0: // Unicode string
992
                                        if (substr($this->TrimConvert($info_asf_extended_content_description_object_content_descriptor_current['name']), 0, 3) == 'WM/') {
993
                                            $info_asf_comments[str_replace('wm/', '', strtolower($this->TrimConvert($info_asf_extended_content_description_object_content_descriptor_current['name'])))] = array (getid3_asf::TrimTerm($info_asf_extended_content_description_object_content_descriptor_current['value']));
994
                                        }
995
                                        break;
996
997
                                    case 1:
998
                                        break;
999
                                }
1000
                                break;
1001
                        }
1002
1003
                    }
1004
                    break;
1005
1006
1007
                case getid3_asf::Stream_Bitrate_Properties_Object:
1008
1009
                    // Stream Bitrate Properties Object: (optional, one only)
1010
                    // Field Name                   Field Type   Size (bits)
1011
                    // Object ID                    GUID         128             // GUID for Stream Bitrate Properties object - getid3_asf::Stream_Bitrate_Properties_Object
1012
                    // Object Size                  QWORD        64              // size of Extended Content Description object, including 26 bytes of Stream Bitrate Properties Object header
1013
                    // Bitrate Records Count        WORD         16              // number of records in Bitrate Records
1014
                    // Bitrate Records              array of:    variable        //
1015
                    // * Flags                      WORD         16              //
1016
                    // * * Stream Number            bits         7  (0x007F)     // number of this stream
1017
                    // * * Reserved                 bits         9  (0xFF80)     // hardcoded: 0
1018
                    // * Average Bitrate            DWORD        32              // in bits per second
1019
1020
                    // shortcut
1021
                    $info_asf['stream_bitrate_properties_object'] = array ();
1022
                    $info_asf_stream_bitrate_properties_object = &$info_asf['stream_bitrate_properties_object'];
1023
1024
                    $info_asf_stream_bitrate_properties_object['objectid_guid']         = $next_object_guidtext;
1025
                    $info_asf_stream_bitrate_properties_object['objectsize']            = $next_object_size;
1026
                    $info_asf_stream_bitrate_properties_object['bitrate_records_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
1027
                    $offset += 2;
1028
                    
1029
                    for ($bitrate_records_counter = 0; $bitrate_records_counter < $info_asf_stream_bitrate_properties_object['bitrate_records_count']; $bitrate_records_counter++) {
1030
                    
1031
                        $info_asf_stream_bitrate_properties_object['bitrate_records'][$bitrate_records_counter]['flags_raw'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
1032
                        $offset += 2;
1033
                        
1034
                        $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;
1035
                        
1036
                        $info_asf_stream_bitrate_properties_object['bitrate_records'][$bitrate_records_counter]['bitrate'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
1037
                        $offset += 4;
1038
                    }
1039
                    break;
1040
1041
1042
                case getid3_asf::Padding_Object:
1043
1044
                    // Padding Object: (optional)
1045
                    // Field Name                   Field Type   Size (bits)
1046
                    // Object ID                    GUID         128             // GUID for Padding object - getid3_asf::Padding_Object
1047
                    // Object Size                  QWORD        64              // size of Padding object, including 24 bytes of ASF Padding Object header
1048
                    // Padding Data                 BYTESTREAM   variable        // ignore
1049
1050
                    // shortcut
1051
                    $info_asf['padding_object'] = array ();
1052
                    $info_asf_paddingobject     = &$info_asf['padding_object'];
1053
1054
                    $info_asf_paddingobject['objectid_guid']  = $next_object_guidtext;
1055
                    $info_asf_paddingobject['objectsize']     = $next_object_size;
1056
                    $info_asf_paddingobject['padding_length'] = $info_asf_paddingobject['objectsize'] - 16 - 8;
1057
                    $info_asf_paddingobject['padding']        = substr($asf_header_data, $offset, $info_asf_paddingobject['padding_length']);
1058
                    $offset += ($next_object_size - 16 - 8);
1059
                    break;
1060
1061
1062
                case getid3_asf::Extended_Content_Encryption_Object:
1063
                case getid3_asf::Content_Encryption_Object:
1064
1065
                    // WMA DRM - just ignore
1066
                    $offset += ($next_object_size - 16 - 8);
1067
                    break;
1068
1069
1070
                default:
1071
1072
                    // Implementations shall ignore any standard or non-standard object that they do not know how to handle.
1073
                    if (getid3_asf::GUIDname($next_object_guidtext)) {
1074
                        $getid3->warning('unhandled GUID "'.getid3_asf::GUIDname($next_object_guidtext).'" {'.$next_object_guidtext.'} in ASF header at offset '.($offset - 16 - 8));
1075
                    } else {
1076
                        $getid3->warning('unknown GUID {'.$next_object_guidtext.'} in ASF header at offset '.($offset - 16 - 8));
1077
                    }
1078
                    $offset += ($next_object_size - 16 - 8);
1079
                    break;
1080
            }
1081
        }
1082
        
1083
        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...
1084
            $asf_bitrate_audio = 0;
1085
            $asf_bitrate_video = 0;
1086
1087
            for ($bitrate_records_counter = 0; $bitrate_records_counter < $info_asf_stream_bitrate_properties['bitrate_records_count']; $bitrate_records_counter++) {
1088
                if (isset($info_asf_codec_list_object['codec_entries'][$bitrate_records_counter])) {
1089
                    switch ($info_asf_codec_list_object['codec_entries'][$bitrate_records_counter]['type_raw']) {
1090
                        
1091
                        case 1:
1092
                            $asf_bitrate_video += $info_asf_stream_bitrate_properties['bitrate_records'][$bitrate_records_counter]['bitrate'];
1093
                            break;
1094
                            
1095
                        case 2:
1096
                            $asf_bitrate_audio += $info_asf_stream_bitrate_properties['bitrate_records'][$bitrate_records_counter]['bitrate'];
1097
                            break;
1098
                    }
1099
                }
1100
            }
1101
            if ($asf_bitrate_audio > 0) {
1102
                $info_audio['bitrate'] = $asf_bitrate_audio;
1103
            }
1104
            if ($asf_bitrate_video > 0) {
1105
                $info_video['bitrate'] = $asf_bitrate_video;
1106
            }
1107
        }
1108
        
1109
        if (isset($info_asf['stream_properties_object']) && is_array($info_asf['stream_properties_object'])) {
1110
            
1111
            $info_audio['bitrate'] = 0;
1112
            $info_video['bitrate'] = 0;
1113
1114
            foreach ($info_asf['stream_properties_object'] as $stream_number => $stream_data) {
1115
                
1116
                switch ($stream_data['stream_type_guid']) {
1117
                    
1118
                    case getid3_asf::Audio_Media:
1119
                    
1120
                        // Field Name                   Field Type   Size (bits)
1121
                        // Codec ID / Format Tag        WORD         16              // unique ID of audio codec - defined as wFormatTag field of WAVEFORMATEX structure
1122
                        // Number of Channels           WORD         16              // number of channels of audio - defined as nChannels field of WAVEFORMATEX structure
1123
                        // Samples Per Second           DWORD        32              // in Hertz - defined as nSamplesPerSec field of WAVEFORMATEX structure
1124
                        // Average number of Bytes/sec  DWORD        32              // bytes/sec of audio stream  - defined as nAvgBytesPerSec field of WAVEFORMATEX structure
1125
                        // Block Alignment              WORD         16              // block size in bytes of audio codec - defined as nBlockAlign field of WAVEFORMATEX structure
1126
                        // 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
1127
                        // Codec Specific Data Size     WORD         16              // size in bytes of Codec Specific Data buffer - defined as cbSize field of WAVEFORMATEX structure
1128
                        // Codec Specific Data          BYTESTREAM   variable        // array of codec-specific data bytes
1129
1130
                        // shortcut
1131
                        $info_asf['audio_media'][$stream_number] = array ();
1132
                        $info_asf_audio_media_current_stream     = &$info_asf['audio_media'][$stream_number];
1133
1134
                        $audio_media_offset = 0;
1135
1136
                        $info_asf_audio_media_current_stream = getid3_riff::RIFFparseWAVEFORMATex(substr($stream_data['type_specific_data'], $audio_media_offset, 16));
1137
1138
                        $audio_media_offset += 16;
1139
1140
                        $info_audio['lossless'] = false;
1141
                        switch ($info_asf_audio_media_current_stream['raw']['wFormatTag']) {
1142
                            case 0x0001: // PCM
1143
                            case 0x0163: // WMA9 Lossless
1144
                                $info_audio['lossless'] = true;
1145
                                break;
1146
                        }
1147
1148
                        if (!empty($info_asf['stream_bitrate_properties_object']['bitrate_records'])) {
1149
							foreach ($info_asf['stream_bitrate_properties_object']['bitrate_records'] as $data_array) {
1150
								if (@$data_array['flags']['stream_number'] == $stream_number) {
1151
									$info_asf_audio_media_current_stream['bitrate'] = $data_array['bitrate'];
1152
									$info_audio['bitrate'] += $data_array['bitrate'];
1153
									break;
1154
								}
1155
							}
1156
						} else {
1157
							if (@$info_asf_audio_media_current_stream['bytes_sec']) {
1158
								$info_audio['bitrate'] += $info_asf_audio_media_current_stream['bytes_sec'] * 8;
1159
							} elseif (@$info_asf_audio_media_current_stream['bitrate']) {
1160
								$info_audio['bitrate'] += $info_asf_audio_media_current_stream['bitrate'];
1161
							}
1162
						}
1163
                        
1164
                        $info_audio['streams'][$stream_number]                  = $info_asf_audio_media_current_stream;
1165
                        $info_audio['streams'][$stream_number]['wformattag']    = $info_asf_audio_media_current_stream['raw']['wFormatTag'];
1166
                        $info_audio['streams'][$stream_number]['lossless']      = $info_audio['lossless'];
1167
                        $info_audio['streams'][$stream_number]['bitrate']       = $info_audio['bitrate'];
1168
                        unset($info_audio['streams'][$stream_number]['raw']);
1169
1170
                        $info_asf_audio_media_current_stream['codec_data_size'] = getid3_lib::LittleEndian2Int(substr($stream_data['type_specific_data'], $audio_media_offset, 2));
1171
                        $audio_media_offset += 2;
1172
                        
1173
                        $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']);
1174
                        $audio_media_offset += $info_asf_audio_media_current_stream['codec_data_size'];
1175
                        break;
1176
1177
1178
                    case getid3_asf::Video_Media:
1179
1180
                        // Field Name                   Field Type   Size (bits)
1181
                        // Encoded Image Width          DWORD        32              // width of image in pixels
1182
                        // Encoded Image Height         DWORD        32              // height of image in pixels
1183
                        // Reserved Flags               BYTE         8               // hardcoded: 0x02
1184
                        // Format Data Size             WORD         16              // size of Format Data field in bytes
1185
                        // Format Data                  array of:    variable        //
1186
                        // * Format Data Size           DWORD        32              // number of bytes in Format Data field, in bytes - defined as biSize field of BITMAPINFOHEADER structure
1187
                        // * Image Width                LONG         32              // width of encoded image in pixels - defined as biWidth field of BITMAPINFOHEADER structure
1188
                        // * Image Height               LONG         32              // height of encoded image in pixels - defined as biHeight field of BITMAPINFOHEADER structure
1189
                        // * Reserved                   WORD         16              // hardcoded: 0x0001 - defined as biPlanes field of BITMAPINFOHEADER structure
1190
                        // * Bits Per Pixel Count       WORD         16              // bits per pixel - defined as biBitCount field of BITMAPINFOHEADER structure
1191
                        // * Compression ID             FOURCC       32              // fourcc of video codec - defined as biCompression field of BITMAPINFOHEADER structure
1192
                        // * Image Size                 DWORD        32              // image size in bytes - defined as biSizeImage field of BITMAPINFOHEADER structure
1193
                        // * Horizontal Pixels / Meter  DWORD        32              // horizontal resolution of target device in pixels per meter - defined as biXPelsPerMeter field of BITMAPINFOHEADER structure
1194
                        // * Vertical Pixels / Meter    DWORD        32              // vertical resolution of target device in pixels per meter - defined as biYPelsPerMeter field of BITMAPINFOHEADER structure
1195
                        // * Colors Used Count          DWORD        32              // number of color indexes in the color table that are actually used - defined as biClrUsed field of BITMAPINFOHEADER structure
1196
                        // * 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
1197
                        // * Codec Specific Data        BYTESTREAM   variable        // array of codec-specific data bytes
1198
1199
                        $info_asf['video_media'][$stream_number] = array ();
1200
                        $info_asf_video_media_current_stream     = &$info_asf['video_media'][$stream_number];
1201
1202
                        getid3_lib::ReadSequence('LittleEndian2Int', $info_asf_video_media_current_stream, $stream_data['type_specific_data'], 0, 
1203
                            array (
1204
                                'image_width'     => 4,
1205
                                'image_height'    => 4,
1206
                                'flags'           => 1,
1207
                                'format_data_size'=> 2
1208
                            )
1209
                        );
1210
                        
1211
                        getid3_lib::ReadSequence('LittleEndian2Int', $info_asf_video_media_current_stream['format_data'], $stream_data['type_specific_data'], 11, 
1212
                            array (
1213
                                'format_data_size' => 4,
1214
                                'image_width'      => 4,
1215
                                'image_height'     => 4,
1216
                                'reserved'         => 2,
1217
                                'bits_per_pixel'   => 2,
1218
                                'codec_fourcc'     => -4,
1219
                                'image_size'       => 4,
1220
                                'horizontal_pels'  => 4,
1221
                                'vertical_pels'    => 4,
1222
                                'colors_used'      => 4,
1223
                                'colors_important' => 4
1224
                            )
1225
                        );
1226
                            
1227
                        $info_asf_video_media_current_stream['format_data']['codec_data'] = substr($stream_data['type_specific_data'], 51);
1228
                        
1229
                        if (!empty($info_asf['stream_bitrate_properties_object']['bitrate_records'])) {
1230
                            foreach ($info_asf['stream_bitrate_properties_object']['bitrate_records'] as $data_array) {
1231
                                if (@$data_array['flags']['stream_number'] == $stream_number) {
1232
                                    $info_asf_video_media_current_stream['bitrate']   = $data_array['bitrate'];
1233
                                    $info_video['streams'][$stream_number]['bitrate'] = $data_array['bitrate'];
1234
                                    $info_video['bitrate'] += $data_array['bitrate'];
1235
                                    
1236
                                    break;
1237
                                }
1238
                            }
1239
                        }
1240
                        
1241
                        $info_asf_video_media_current_stream['format_data']['codec'] = getid3_riff::RIFFfourccLookup($info_asf_video_media_current_stream['format_data']['codec_fourcc']);
1242
1243
                        $info_video['streams'][$stream_number]['fourcc']          = $info_asf_video_media_current_stream['format_data']['codec_fourcc'];
1244
                        $info_video['streams'][$stream_number]['codec']           = $info_asf_video_media_current_stream['format_data']['codec'];
1245
                        $info_video['streams'][$stream_number]['resolution_x']    = $info_asf_video_media_current_stream['image_width'];
1246
                        $info_video['streams'][$stream_number]['resolution_y']    = $info_asf_video_media_current_stream['image_height'];
1247
                        $info_video['streams'][$stream_number]['bits_per_sample'] = $info_asf_video_media_current_stream['format_data']['bits_per_pixel'];
1248
                        break;
1249
1250
                    default:
1251
                        break;
1252
                }
1253
            }
1254
        }
1255
1256
        while (ftell($getid3->fp) < $getid3->info['avdataend']) {
1257
            
1258
            $next_object_data_header = fread($getid3->fp, 24);
1259
            $offset = 0;
1260
            
1261
            $next_object_guid = substr($next_object_data_header, 0, 16);
1262
            $offset += 16;
1263
            
1264
            $next_object_guidtext = getid3_asf::BytestringToGUID($next_object_guid);
1265
            $next_object_size     = getid3_lib::LittleEndian2Int(substr($next_object_data_header, $offset, 8));
1266
            $offset += 8;
1267
1268
            switch ($next_object_guidtext) {
1269
                
1270
                case getid3_asf::Data_Object:
1271
                
1272
                    // Data Object: (mandatory, one only)
1273
                    // Field Name                       Field Type   Size (bits)
1274
                    // Object ID                        GUID         128             // GUID for Data object - getid3_asf::Data_Object
1275
                    // Object Size                      QWORD        64              // size of Data object, including 50 bytes of Data Object header. may be 0 if FilePropertiesObject.BroadcastFlag == 1
1276
                    // File ID                          GUID         128             // unique identifier. identical to File ID field in Header Object
1277
                    // Total Data Packets               QWORD        64              // number of Data Packet entries in Data Object. invalid if FilePropertiesObject.BroadcastFlag == 1
1278
                    // Reserved                         WORD         16              // hardcoded: 0x0101
1279
1280
                    // shortcut
1281
                    $info_asf['data_object'] = array ();
1282
                    $info_asf_data_object    = &$info_asf['data_object'];
1283
1284
                    $data_object_data = $next_object_data_header.fread($getid3->fp, 50 - 24);
1285
                    $offset = 24;
1286
1287
                    $info_asf_data_object['objectid_guid']      = $next_object_guidtext;
1288
                    $info_asf_data_object['objectsize']         = $next_object_size;
1289
1290
                    $info_asf_data_object['fileid_guid']        = getid3_asf::BytestringToGUID(substr($data_object_data, $offset, 16));
1291
                    $offset += 16;
1292
                    
1293
                    $info_asf_data_object['total_data_packets'] = getid3_lib::LittleEndian2Int(substr($data_object_data, $offset, 8));
1294
                    $offset += 8;
1295
                    
1296
                    $info_asf_data_object['reserved']           = getid3_lib::LittleEndian2Int(substr($data_object_data, $offset, 2));
1297
                    $offset += 2;
1298
                    
1299
                    if ($info_asf_data_object['reserved'] != 0x0101) {
1300
                        $getid3->warning('data_object.reserved ('.getid3_lib::PrintHexBytes($info_asf_data_object['reserved']).') does not match expected value of "0x0101"');
1301
                        break;
1302
                    }
1303
1304
                    // Data Packets                     array of:    variable        //
1305
                    // * Error Correction Flags         BYTE         8               //
1306
                    // * * Error Correction Data Length bits         4               // if Error Correction Length Type == 00, size of Error Correction Data in bytes, else hardcoded: 0000
1307
                    // * * Opaque Data Present          bits         1               //
1308
                    // * * Error Correction Length Type bits         2               // number of bits for size of the error correction data. hardcoded: 00
1309
                    // * * Error Correction Present     bits         1               // If set, use Opaque Data Packet structure, else use Payload structure
1310
                    // * Error Correction Data
1311
1312
                    $getid3->info['avdataoffset'] = ftell($getid3->fp);
1313
                    fseek($getid3->fp, ($info_asf_data_object['objectsize'] - 50), SEEK_CUR); // skip actual audio/video data
1314
                    $getid3->info['avdataend'] = ftell($getid3->fp);
1315
                    break;
1316
1317
1318
                case getid3_asf::Simple_Index_Object:
1319
1320
                    // Simple Index Object: (optional, recommended, one per video stream)
1321
                    // Field Name                       Field Type   Size (bits)
1322
                    // Object ID                        GUID         128             // GUID for Simple Index object - getid3_asf::Data_Object
1323
                    // Object Size                      QWORD        64              // size of Simple Index object, including 56 bytes of Simple Index Object header
1324
                    // File ID                          GUID         128             // unique identifier. may be zero or identical to File ID field in Data Object and Header Object
1325
                    // Index Entry Time Interval        QWORD        64              // interval between index entries in 100-nanosecond units
1326
                    // Maximum Packet Count             DWORD        32              // maximum packet count for all index entries
1327
                    // Index Entries Count              DWORD        32              // number of Index Entries structures
1328
                    // Index Entries                    array of:    variable        //
1329
                    // * Packet Number                  DWORD        32              // number of the Data Packet associated with this index entry
1330
                    // * Packet Count                   WORD         16              // number of Data Packets to sent at this index entry
1331
1332
                    // shortcut
1333
                    $info_asf['simple_index_object'] = array ();
1334
                    $info_asf_simple_index_object    = &$info_asf['simple_index_object'];
1335
1336
                    $info_asf_simple_index_object['objectid_guid'] = $next_object_guidtext;
1337
                    $info_asf_simple_index_object['objectsize']    = $next_object_size;
1338
1339
                    $simple_index_object_data = $next_object_data_header.fread($getid3->fp, 56 - 24);
1340
                    
1341
                    $info_asf_simple_index_object['fileid_guid'] = getid3_asf::BytestringToGUID(substr($simple_index_object_data, 24, 16));
1342
1343
                    getid3_lib::ReadSequence('LittleEndian2Int', $info_asf_simple_index_object, $simple_index_object_data, 40,
1344
                        array (
1345
                            'index_entry_time_interval' => 8,
1346
                            'maximum_packet_count'      => 4,
1347
                            'index_entries_count'       => 4
1348
                        )
1349
                    );
1350
                    
1351
                    $offset = 56;
1352
1353
                    $index_entries_data = $simple_index_object_data.fread($getid3->fp, 6 * $info_asf_simple_index_object['index_entries_count']);
1354
                    for ($index_entries_counter = 0; $index_entries_counter < $info_asf_simple_index_object['index_entries_count']; $index_entries_counter++) {
1355
                    
1356
                        $info_asf_simple_index_object['index_entries'][$index_entries_counter]['packet_number'] = getid3_lib::LittleEndian2Int(substr($index_entries_data, $offset, 4));
1357
                        $offset += 4;
1358
                    
1359
                        $info_asf_simple_index_object['index_entries'][$index_entries_counter]['packet_count']  = getid3_lib::LittleEndian2Int(substr($index_entries_data, $offset, 4));
1360
                        $offset += 2;
1361
                    }
1362
                    break;
1363
1364
1365
                case getid3_asf::Index_Object:
1366
1367
                    // 6.2 ASF top-level Index Object (optional but recommended when appropriate, 0 or 1)
1368
                    // Field Name                       Field Type   Size (bits)
1369
                    // Object ID                        GUID         128             // GUID for the Index Object - getid3_asf::Index_Object
1370
                    // Object Size                      QWORD        64              // Specifies the size, in bytes, of the Index Object, including at least 34 bytes of Index Object header
1371
                    // Index Entry Time Interval        DWORD        32              // Specifies the time interval between each index entry in ms.
1372
                    // Index Specifiers Count           WORD         16              // Specifies the number of Index Specifiers structures in this Index Object.
1373
                    // Index Blocks Count               DWORD        32              // Specifies the number of Index Blocks structures in this Index Object.
1374
1375
                    // Index Entry Time Interval        DWORD        32              // Specifies the time interval between index entries in milliseconds.  This value cannot be 0.
1376
                    // Index Specifiers Count           WORD         16              // Specifies the number of entries in the Index Specifiers list.  Valid values are 1 and greater.
1377
                    // Index Specifiers                 array of:    varies          //
1378
                    // * Stream Number                  WORD         16              // Specifies the stream number that the Index Specifiers refer to. Valid values are between 1 and 127.
1379
                    // * Index Type                     WORD         16              // Specifies Index Type values as follows:
1380
                                                                                     //   1 = Nearest Past Data Packet - indexes point to the data packet whose presentation time is closest to the index entry time.
1381
                                                                                     //   2 = Nearest Past Media Object - indexes point to the closest data packet containing an entire object or first fragment of an object.
1382
                                                                                     //   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.
1383
                                                                                     //   Nearest Past Cleanpoint is the most common type of index.
1384
                    // Index Entry Count                DWORD        32              // Specifies the number of Index Entries in the block.
1385
                    // * 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.
1386
                    // * Index Entries                  array of:    varies          //
1387
                    // * * Offsets                      DWORD        varies          // An offset value of 0xffffffff indicates an invalid offset value
1388
1389
                    // shortcut
1390
                    $info_asf['asf_index_object'] = array ();
1391
                    $info_asf_asf_index_object      = &$info_asf['asf_index_object'];
1392
1393
                    $asf_index_object_data = $next_object_data_header.fread($getid3->fp, 34 - 24);
1394
1395
                    $info_asf_asf_index_object['objectid_guid'] = $next_object_guidtext;
1396
                    $info_asf_asf_index_object['objectsize']    = $next_object_size;
1397
1398
                    getid3_lib::ReadSequence('LittleEndian2Int', $info_asf_asf_index_object, $asf_index_object_data, 24, 
1399
                        array (
1400
                            'entry_time_interval'    =>4,
1401
                            'index_specifiers_count' =>2,
1402
                            'index_blocks_count'     =>4
1403
                        )
1404
                    );
1405
1406
                    $offset = 34;
1407
1408
                    $asf_index_object_data .= fread($getid3->fp, 4 * $info_asf_asf_index_object['index_specifiers_count']);
1409
                    
1410
                    for ($index_specifiers_counter = 0; $index_specifiers_counter < $info_asf_asf_index_object['index_specifiers_count']; $index_specifiers_counter++) {
1411
                    
1412
                        $index_specifier_stream_number = getid3_lib::LittleEndian2Int(substr($asf_index_object_data, $offset, 2));
1413
                        $offset += 2;
1414
                        
1415
                        $info_asf_asf_index_object['index_specifiers'][$index_specifiers_counter]['stream_number']   = $index_specifier_stream_number;
1416
                        
1417
                        $info_asf_asf_index_object['index_specifiers'][$index_specifiers_counter]['index_type']      = getid3_lib::LittleEndian2Int(substr($asf_index_object_data, $offset, 2));
1418
                        $offset += 2;
1419
                        
1420
                        $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']);
1421
                    }
1422
1423
                    $asf_index_object_data .= fread($getid3->fp, 4);
1424
                    $info_asf_asf_index_object['index_entry_count'] = getid3_lib::LittleEndian2Int(substr($asf_index_object_data, $offset, 4));
1425
                    $offset += 4;
1426
1427
                    $asf_index_object_data .= fread($getid3->fp, 8 * $info_asf_asf_index_object['index_specifiers_count']);
1428
                    
1429
                    for ($index_specifiers_counter = 0; $index_specifiers_counter < $info_asf_asf_index_object['index_specifiers_count']; $index_specifiers_counter++) {
1430
                        $info_asf_asf_index_object['block_positions'][$index_specifiers_counter] = getid3_lib::LittleEndian2Int(substr($asf_index_object_data, $offset, 8));
1431
                        $offset += 8;
1432
                    }
1433
1434
                    $asf_index_object_data .= fread($getid3->fp, 4 * $info_asf_asf_index_object['index_specifiers_count'] * $info_asf_asf_index_object['index_entry_count']);
1435
                    
1436
                    for ($index_entry_counter = 0; $index_entry_counter < $info_asf_asf_index_object['index_entry_count']; $index_entry_counter++) {
1437
                        for ($index_specifiers_counter = 0; $index_specifiers_counter < $info_asf_asf_index_object['index_specifiers_count']; $index_specifiers_counter++) {
1438
                            $info_asf_asf_index_object['offsets'][$index_specifiers_counter][$index_entry_counter] = getid3_lib::LittleEndian2Int(substr($asf_index_object_data, $offset, 4));
1439
                            $offset += 4;
1440
                        }
1441
                    }
1442
                    break;
1443
1444
1445
                default:
1446
                    
1447
                    // Implementations shall ignore any standard or non-standard object that they do not know how to handle.
1448
                    if (getid3_asf::GUIDname($next_object_guidtext)) {
1449
                        $getid3->warning('unhandled GUID "'.getid3_asf::GUIDname($next_object_guidtext).'" {'.$next_object_guidtext.'} in ASF body at offset '.($offset - 16 - 8));
1450
                    } else {
1451
                        $getid3->warning('unknown GUID {'.$next_object_guidtext.'} in ASF body at offset '.(ftell($getid3->fp) - 16 - 8));
1452
                    }
1453
                    fseek($getid3->fp, ($next_object_size - 16 - 8), SEEK_CUR);
1454
                    break;
1455
            }
1456
        }
1457
1458
        if (isset($info_asf_codec_list_object['codec_entries']) && is_array($info_asf_codec_list_object['codec_entries'])) {
1459
            foreach ($info_asf_codec_list_object['codec_entries'] as $stream_number => $stream_data) {
1460
                switch ($stream_data['information']) {
1461
                    case 'WMV1':
1462
                    case 'WMV2':
1463
                    case 'WMV3':
1464
                    case 'MSS1':
1465
                    case 'MSS2':
1466
                    case 'WMVA':
1467
                    case 'WVC1':
1468
                    case 'WMVP':
1469
                    case 'WVP2': 
1470
                        $info_video['dataformat'] = 'wmv';
1471
                        $getid3->info['mime_type']    = 'video/x-ms-wmv';
1472
                        break;
1473
1474
                    case 'MP42':
1475
                    case 'MP43':
1476
                    case 'MP4S':
1477
                    case 'mp4s':
1478
                        $info_video['dataformat'] = 'asf';
1479
                        $getid3->info['mime_type']    = 'video/x-ms-asf';
1480
                        break;
1481
1482
                    default:
1483
                        switch ($stream_data['type_raw']) {
1484
                            case 1:
1485
                                if (strstr($this->TrimConvert($stream_data['name']), 'Windows Media')) {
1486
                                    $info_video['dataformat'] = 'wmv';
1487
                                    if ($getid3->info['mime_type'] == 'video/x-ms-asf') {
1488
                                        $getid3->info['mime_type'] = 'video/x-ms-wmv';
1489
                                    }
1490
                                }
1491
                                break;
1492
1493
                            case 2:
1494
                                if (strstr($this->TrimConvert($stream_data['name']), 'Windows Media')) {
1495
                                    $info_audio['dataformat'] = 'wma';
1496
                                    if ($getid3->info['mime_type'] == 'video/x-ms-asf') {
1497
                                        $getid3->info['mime_type'] = 'audio/x-ms-wma';
1498
                                    }
1499
                                }
1500
                                break;
1501
1502
                        }
1503
                        break;
1504
                }
1505
            }
1506
        }
1507
1508
        switch (@$info_audio['codec']) {
1509
            case 'MPEG Layer-3':
1510
                $info_audio['dataformat'] = 'mp3';
1511
                break;
1512
1513
            default:
1514
                break;
1515
        }
1516
1517
        if (isset($info_asf_codec_list_object['codec_entries'])) {
1518
            foreach ($info_asf_codec_list_object['codec_entries'] as $stream_number => $stream_data) {
1519
                switch ($stream_data['type_raw']) {
1520
1521
                    case 1: // video
1522
                        $info_video['encoder'] = $this->TrimConvert($info_asf_codec_list_object['codec_entries'][$stream_number]['name']);
1523
                        break;
1524
1525
                    case 2: // audio
1526
                        $info_audio['encoder']         = $this->TrimConvert($info_asf_codec_list_object['codec_entries'][$stream_number]['name']);
1527
                        $info_audio['encoder_options'] = $this->TrimConvert($info_asf_codec_list_object['codec_entries'][0]['description']);
1528
                        $info_audio['codec']           = $info_audio['encoder'];
1529
                        break;
1530
1531
                    default:
1532
                        $getid3->warning('Unknown streamtype: [codec_list_object][codec_entries]['.$stream_number.'][type_raw] == '.$stream_data['type_raw']);
1533
                        break;
1534
1535
                }
1536
            }
1537
        }
1538
1539
        if (isset($getid3->info['audio'])) {
1540
            $info_audio['lossless']           = (isset($info_audio['lossless'])           ? $info_audio['lossless']           : false);
1541
            $info_audio['dataformat']         = (!empty($info_audio['dataformat'])        ? $info_audio['dataformat']         : 'asf');
1542
        }
1543
        
1544
        if (!empty($info_video['dataformat'])) {
1545
            $info_video['lossless']           = (isset($info_audio['lossless'])           ? $info_audio['lossless']           : false);
1546
            $info_video['pixel_aspect_ratio'] = (isset($info_audio['pixel_aspect_ratio']) ? $info_audio['pixel_aspect_ratio'] : (float)1);
1547
            $info_video['dataformat']         = (!empty($info_video['dataformat'])        ? $info_video['dataformat']         : 'asf');
1548
        }
1549
        
1550
        $getid3->info['bitrate'] = @$info_audio['bitrate'] + @$info_video['bitrate'];
1551
              
1552
        if (empty($info_audio)) {
1553
            unset($getid3->info['audio']);
1554
        }
1555
        
1556
        if (empty($info_video)) {
1557
            unset($getid3->info['video']);
1558
        }
1559
        
1560
        return true;
1561
    }
1562
1563
1564
  
1565
    // Remove terminator 00 00 and convert UNICODE to Latin-1
1566
    private function TrimConvert($string) {
1567
        
1568
        // remove terminator, only if present (it should be, but...)
1569
        if (substr($string, strlen($string) - 2, 2) == "\x00\x00") {
1570
            $string = substr($string, 0, strlen($string) - 2);
1571
        }
1572
1573
        // convert
1574
        return trim($this->getid3->iconv('UTF-16LE', 'ISO-8859-1', $string), ' ');
1575
    }
1576
1577
1578
1579
    private function WMpictureTypeLookup($wm_picture_type) {
1580
        
1581
        static $lookup = array (
1582
            0x03 => 'Front Cover',
1583
            0x04 => 'Back Cover',
1584
            0x00 => 'User Defined',
1585
            0x05 => 'Leaflet Page',
1586
            0x06 => 'Media Label',
1587
            0x07 => 'Lead Artist',
1588
            0x08 => 'Artist',
1589
            0x09 => 'Conductor',
1590
            0x0A => 'Band',
1591
            0x0B => 'Composer',
1592
            0x0C => 'Lyricist',
1593
            0x0D => 'Recording Location',
1594
            0x0E => 'During Recording',
1595
            0x0F => 'During Performance',
1596
            0x10 => 'Video Screen Capture',
1597
            0x12 => 'Illustration',
1598
            0x13 => 'Band Logotype',
1599
            0x14 => 'Publisher Logotype'
1600
        );
1601
        
1602
        return isset($lookup[$wm_picture_type]) ? $this->getid3->iconv('ISO-8859-1', 'UTF-16LE', $lookup[$wm_picture_type]) : '';
1603
    }
1604
1605
1606
1607
    public static function ASFCodecListObjectTypeLookup($codec_list_type) {
1608
        
1609
        static $lookup = array (
1610
            0x0001 => 'Video Codec',
1611
            0x0002 => 'Audio Codec',
1612
            0xFFFF => 'Unknown Codec'
1613
        );
1614
1615
        return (isset($lookup[$codec_list_type]) ? $lookup[$codec_list_type] : 'Invalid Codec Type');
1616
    }
1617
1618
1619
1620
    public static function GUIDname($guid_string) {
1621
        
1622
        static $lookup = array (
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
1735
1736
    public static function ASFIndexObjectIndexTypeLookup($id) {
1737
        
1738
        static $lookup = array (
1739
            1 => 'Nearest Past Data Packet',
1740
            2 => 'Nearest Past Media Object',
1741
            3 => 'Nearest Past Cleanpoint'
1742
        );
1743
1744
        return (isset($lookup[$id]) ? $lookup[$id] : 'invalid');
1745
    }
1746
1747
1748
1749
    public static function GUIDtoBytestring($guid_string) {
1750
        
1751
        // Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way:
1752
        // first 4 bytes are in little-endian order
1753
        // next 2 bytes are appended in little-endian order
1754
        // next 2 bytes are appended in little-endian order
1755
        // next 2 bytes are appended in big-endian order
1756
        // next 6 bytes are appended in big-endian order
1757
1758
        // AaBbCcDd-EeFf-GgHh-IiJj-KkLlMmNnOoPp is stored as this 16-byte string:
1759
        // $Dd $Cc $Bb $Aa $Ff $Ee $Hh $Gg $Ii $Jj $Kk $Ll $Mm $Nn $Oo $Pp
1760
1761
        $hex_byte_char_string  = chr(hexdec(substr($guid_string,  6, 2)));
1762
        $hex_byte_char_string .= chr(hexdec(substr($guid_string,  4, 2)));
1763
        $hex_byte_char_string .= chr(hexdec(substr($guid_string,  2, 2)));
1764
        $hex_byte_char_string .= chr(hexdec(substr($guid_string,  0, 2)));
1765
1766
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 11, 2)));
1767
        $hex_byte_char_string .= chr(hexdec(substr($guid_string,  9, 2)));
1768
1769
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 16, 2)));
1770
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 14, 2)));
1771
1772
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 19, 2)));
1773
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 21, 2)));
1774
1775
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 24, 2)));
1776
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 26, 2)));
1777
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 28, 2)));
1778
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 30, 2)));
1779
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 32, 2)));
1780
        $hex_byte_char_string .= chr(hexdec(substr($guid_string, 34, 2)));
1781
1782
        return $hex_byte_char_string;
1783
    }
1784
1785
1786
1787
    public static function BytestringToGUID($byte_string) {
1788
        
1789
        $guid_string  = str_pad(dechex(ord($byte_string{3})),  2, '0', STR_PAD_LEFT);
1790
        $guid_string .= str_pad(dechex(ord($byte_string{2})),  2, '0', STR_PAD_LEFT);
1791
        $guid_string .= str_pad(dechex(ord($byte_string{1})),  2, '0', STR_PAD_LEFT);
1792
        $guid_string .= str_pad(dechex(ord($byte_string{0})),  2, '0', STR_PAD_LEFT);
1793
        $guid_string .= '-';
1794
        $guid_string .= str_pad(dechex(ord($byte_string{5})),  2, '0', STR_PAD_LEFT);
1795
        $guid_string .= str_pad(dechex(ord($byte_string{4})),  2, '0', STR_PAD_LEFT);
1796
        $guid_string .= '-';
1797
        $guid_string .= str_pad(dechex(ord($byte_string{7})),  2, '0', STR_PAD_LEFT);
1798
        $guid_string .= str_pad(dechex(ord($byte_string{6})),  2, '0', STR_PAD_LEFT);
1799
        $guid_string .= '-';
1800
        $guid_string .= str_pad(dechex(ord($byte_string{8})),  2, '0', STR_PAD_LEFT);
1801
        $guid_string .= str_pad(dechex(ord($byte_string{9})),  2, '0', STR_PAD_LEFT);
1802
        $guid_string .= '-';
1803
        $guid_string .= str_pad(dechex(ord($byte_string{10})), 2, '0', STR_PAD_LEFT);
1804
        $guid_string .= str_pad(dechex(ord($byte_string{11})), 2, '0', STR_PAD_LEFT);
1805
        $guid_string .= str_pad(dechex(ord($byte_string{12})), 2, '0', STR_PAD_LEFT);
1806
        $guid_string .= str_pad(dechex(ord($byte_string{13})), 2, '0', STR_PAD_LEFT);
1807
        $guid_string .= str_pad(dechex(ord($byte_string{14})), 2, '0', STR_PAD_LEFT);
1808
        $guid_string .= str_pad(dechex(ord($byte_string{15})), 2, '0', STR_PAD_LEFT);
1809
1810
        return strtoupper($guid_string);
1811
    }
1812
1813
1814
1815
    public static function FiletimeToUNIXtime($file_time, $round=true) {
1816
        
1817
        // FILETIME is a 64-bit unsigned integer representing
1818
        // the number of 100-nanosecond intervals since January 1, 1601
1819
        // UNIX timestamp is number of seconds since January 1, 1970
1820
        // 116444736000000000 = 10000000 * 60 * 60 * 24 * 365 * 369 + 89 leap days
1821
        
1822
        $time = ($file_time - 116444736000000000) / 10000000;
1823
        
1824
        if ($round) {
1825
            return intval(round($time));
1826
        }
1827
        
1828
        return $time;
1829
    }
1830
1831
1832
1833
    public static function TrimTerm($string) {
1834
1835
        // remove terminator, only if present (it should be, but...)
1836
        if (substr($string, -2) == "\x00\x00") {
1837
            $string = substr($string, 0, -2);
1838
        }
1839
        return $string;
1840
    }
1841
1842
1843
}
1844
1845
1846
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...