33 {
34 $info = &$this->getid3->info;
35
36
37 $thisfile_audio = &
$info[
'audio'];
38 $thisfile_video = &
$info[
'video'];
39 $info[
'asf'] = array();
40 $thisfile_asf = &
$info[
'asf'];
41 $thisfile_asf['comments'] = array();
42 $thisfile_asf_comments = &$thisfile_asf['comments'];
43 $thisfile_asf['header_object'] = array();
44 $thisfile_asf_headerobject = &$thisfile_asf['header_object'];
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 $info[
'fileformat'] =
'asf';
68
70 $HeaderObjectData = $this->
fread(30);
71
72 $thisfile_asf_headerobject['objectid'] = substr($HeaderObjectData, 0, 16);
73 $thisfile_asf_headerobject[
'objectid_guid'] = $this->
BytestringToGUID($thisfile_asf_headerobject[
'objectid']);
74 if ($thisfile_asf_headerobject['objectid'] != GETID3_ASF_Header_Object) {
76 return $this->
error(
'ASF header GUID {'.$this->
BytestringToGUID($thisfile_asf_headerobject[
'objectid']).
'} does not match expected "GETID3_ASF_Header_Object" GUID {'.$this->
BytestringToGUID(GETID3_ASF_Header_Object).
'}');
77 }
82
83 $NextObjectOffset = $this->
ftell();
84 $ASFHeaderData = $this->
fread($thisfile_asf_headerobject[
'objectsize'] - 30);
85 $offset = 0;
86
87 for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) {
88 $NextObjectGUID = substr($ASFHeaderData, $offset, 16);
89 $offset += 16;
92 $offset += 8;
93 switch ($NextObjectGUID) {
94
95 case GETID3_ASF_File_Properties_Object:
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 $thisfile_asf['file_properties_object'] = array();
117 $thisfile_asf_filepropertiesobject = &$thisfile_asf['file_properties_object'];
118
119 $thisfile_asf_filepropertiesobject['offset'] = $NextObjectOffset + $offset;
120 $thisfile_asf_filepropertiesobject['objectid'] = $NextObjectGUID;
121 $thisfile_asf_filepropertiesobject['objectid_guid'] = $NextObjectGUIDtext;
122 $thisfile_asf_filepropertiesobject['objectsize'] = $NextObjectSize;
123 $thisfile_asf_filepropertiesobject['fileid'] = substr($ASFHeaderData, $offset, 16);
124 $offset += 16;
125 $thisfile_asf_filepropertiesobject[
'fileid_guid'] = $this->
BytestringToGUID($thisfile_asf_filepropertiesobject[
'fileid']);
127 $offset += 8;
129 $thisfile_asf_filepropertiesobject[
'creation_date_unix'] = $this->
FILETIMEtoUNIXtime($thisfile_asf_filepropertiesobject[
'creation_date']);
130 $offset += 8;
132 $offset += 8;
134 $offset += 8;
136 $offset += 8;
138 $offset += 8;
140 $offset += 4;
141 $thisfile_asf_filepropertiesobject['flags']['broadcast'] = (bool) ($thisfile_asf_filepropertiesobject['flags_raw'] & 0x0001);
142 $thisfile_asf_filepropertiesobject['flags']['seekable'] = (bool) ($thisfile_asf_filepropertiesobject['flags_raw'] & 0x0002);
143
145 $offset += 4;
147 $offset += 4;
149 $offset += 4;
150
151 if ($thisfile_asf_filepropertiesobject['flags']['broadcast']) {
152
153
154 unset($thisfile_asf_filepropertiesobject['filesize']);
155 unset($thisfile_asf_filepropertiesobject['data_packets']);
156 unset($thisfile_asf_filepropertiesobject['play_duration']);
157 unset($thisfile_asf_filepropertiesobject['send_duration']);
158 unset($thisfile_asf_filepropertiesobject['min_packet_size']);
159 unset($thisfile_asf_filepropertiesobject['max_packet_size']);
160
161 } else {
162
163
164 $info[
'playtime_seconds'] = ($thisfile_asf_filepropertiesobject[
'play_duration'] / 10000000) - ($thisfile_asf_filepropertiesobject[
'preroll'] / 1000);
165
166
167 $info[
'bitrate'] = ((isset($thisfile_asf_filepropertiesobject[
'filesize']) ? $thisfile_asf_filepropertiesobject[
'filesize'] :
$info[
'filesize']) * 8) /
$info[
'playtime_seconds'];
168 }
169 break;
170
171 case GETID3_ASF_Stream_Properties_Object:
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193 $StreamPropertiesObjectData['offset'] = $NextObjectOffset + $offset;
194 $StreamPropertiesObjectData['objectid'] = $NextObjectGUID;
195 $StreamPropertiesObjectData['objectid_guid'] = $NextObjectGUIDtext;
196 $StreamPropertiesObjectData['objectsize'] = $NextObjectSize;
197 $StreamPropertiesObjectData['stream_type'] = substr($ASFHeaderData, $offset, 16);
198 $offset += 16;
199 $StreamPropertiesObjectData[
'stream_type_guid'] = $this->
BytestringToGUID($StreamPropertiesObjectData[
'stream_type']);
200 $StreamPropertiesObjectData['error_correct_type'] = substr($ASFHeaderData, $offset, 16);
201 $offset += 16;
202 $StreamPropertiesObjectData[
'error_correct_guid'] = $this->
BytestringToGUID($StreamPropertiesObjectData[
'error_correct_type']);
204 $offset += 8;
206 $offset += 4;
208 $offset += 4;
210 $offset += 2;
211 $StreamPropertiesObjectStreamNumber = $StreamPropertiesObjectData['flags_raw'] & 0x007F;
212 $StreamPropertiesObjectData['flags']['encrypted'] = (bool) ($StreamPropertiesObjectData['flags_raw'] & 0x8000);
213
214 $offset += 4;
215 $StreamPropertiesObjectData['type_specific_data'] = substr($ASFHeaderData, $offset, $StreamPropertiesObjectData['type_data_length']);
216 $offset += $StreamPropertiesObjectData['type_data_length'];
217 $StreamPropertiesObjectData['error_correct_data'] = substr($ASFHeaderData, $offset, $StreamPropertiesObjectData['error_data_length']);
218 $offset += $StreamPropertiesObjectData['error_data_length'];
219
220 switch ($StreamPropertiesObjectData['stream_type']) {
221
222 case GETID3_ASF_Audio_Media:
223 $thisfile_audio['dataformat'] = (!empty($thisfile_audio['dataformat']) ? $thisfile_audio['dataformat'] : 'asf');
224 $thisfile_audio['bitrate_mode'] = (!empty($thisfile_audio['bitrate_mode']) ? $thisfile_audio['bitrate_mode'] : 'cbr');
225
227 unset($audiodata['raw']);
229 break;
230
231 case GETID3_ASF_Video_Media:
232 $thisfile_video['dataformat'] = (!empty($thisfile_video['dataformat']) ? $thisfile_video['dataformat'] : 'asf');
233 $thisfile_video['bitrate_mode'] = (!empty($thisfile_video['bitrate_mode']) ? $thisfile_video['bitrate_mode'] : 'cbr');
234 break;
235
236 case GETID3_ASF_Command_Media:
237 default:
238
239 break;
240
241 }
242
243 $thisfile_asf['stream_properties_object'][$StreamPropertiesObjectStreamNumber] = $StreamPropertiesObjectData;
244 unset($StreamPropertiesObjectData);
245 break;
246
247 case GETID3_ASF_Header_Extension_Object:
248
249
250
251
252
253
254
255
256
257
258 $thisfile_asf['header_extension_object'] = array();
259 $thisfile_asf_headerextensionobject = &$thisfile_asf['header_extension_object'];
260
261 $thisfile_asf_headerextensionobject['offset'] = $NextObjectOffset + $offset;
262 $thisfile_asf_headerextensionobject['objectid'] = $NextObjectGUID;
263 $thisfile_asf_headerextensionobject['objectid_guid'] = $NextObjectGUIDtext;
264 $thisfile_asf_headerextensionobject['objectsize'] = $NextObjectSize;
265 $thisfile_asf_headerextensionobject['reserved_1'] = substr($ASFHeaderData, $offset, 16);
266 $offset += 16;
267 $thisfile_asf_headerextensionobject[
'reserved_1_guid'] = $this->
BytestringToGUID($thisfile_asf_headerextensionobject[
'reserved_1']);
268 if ($thisfile_asf_headerextensionobject['reserved_1'] != GETID3_ASF_Reserved_1) {
269 $this->
warning(
'header_extension_object.reserved_1 GUID ('.$this->
BytestringToGUID($thisfile_asf_headerextensionobject[
'reserved_1']).
') does not match expected "GETID3_ASF_Reserved_1" GUID ('.$this->
BytestringToGUID(GETID3_ASF_Reserved_1).
')');
270
271 break;
272 }
274 $offset += 2;
275 if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) {
276 $this->
warning(
'header_extension_object.reserved_2 ('.
getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject[
'reserved_2']).
') does not match expected value of "6"');
277
278 break;
279 }
281 $offset += 4;
282 $thisfile_asf_headerextensionobject['extension_data'] = substr($ASFHeaderData, $offset, $thisfile_asf_headerextensionobject['extension_data_size']);
283 $unhandled_sections = 0;
284 $thisfile_asf_headerextensionobject[
'extension_data_parsed'] = $this->
HeaderExtensionObjectDataParse($thisfile_asf_headerextensionobject[
'extension_data'], $unhandled_sections);
285 if ($unhandled_sections === 0) {
286 unset($thisfile_asf_headerextensionobject['extension_data']);
287 }
288 $offset += $thisfile_asf_headerextensionobject['extension_data_size'];
289 break;
290
291 case GETID3_ASF_Codec_List_Object:
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308 $thisfile_asf['codec_list_object'] = array();
309 $thisfile_asf_codeclistobject = &$thisfile_asf['codec_list_object'];
310
311 $thisfile_asf_codeclistobject['offset'] = $NextObjectOffset + $offset;
312 $thisfile_asf_codeclistobject['objectid'] = $NextObjectGUID;
313 $thisfile_asf_codeclistobject['objectid_guid'] = $NextObjectGUIDtext;
314 $thisfile_asf_codeclistobject['objectsize'] = $NextObjectSize;
315 $thisfile_asf_codeclistobject['reserved'] = substr($ASFHeaderData, $offset, 16);
316 $offset += 16;
317 $thisfile_asf_codeclistobject[
'reserved_guid'] = $this->
BytestringToGUID($thisfile_asf_codeclistobject[
'reserved']);
318 if ($thisfile_asf_codeclistobject[
'reserved'] != $this->
GUIDtoBytestring(
'86D15241-311D-11D0-A3A4-00A0C90348F6')) {
319 $this->
warning(
'codec_list_object.reserved GUID {'.$this->
BytestringToGUID($thisfile_asf_codeclistobject[
'reserved']).
'} does not match expected "GETID3_ASF_Reserved_1" GUID {86D15241-311D-11D0-A3A4-00A0C90348F6}');
320
321 break;
322 }
324 $offset += 4;
325 for ($CodecEntryCounter = 0; $CodecEntryCounter < $thisfile_asf_codeclistobject['codec_entries_count']; $CodecEntryCounter++) {
326
327 $thisfile_asf_codeclistobject['codec_entries'][$CodecEntryCounter] = array();
328 $thisfile_asf_codeclistobject_codecentries_current = &$thisfile_asf_codeclistobject['codec_entries'][$CodecEntryCounter];
329
331 $offset += 2;
332 $thisfile_asf_codeclistobject_codecentries_current[
'type'] =
self::codecListObjectTypeLookup($thisfile_asf_codeclistobject_codecentries_current[
'type_raw']);
333
335 $offset += 2;
336 $thisfile_asf_codeclistobject_codecentries_current['name'] = substr($ASFHeaderData, $offset, $CodecNameLength);
337 $offset += $CodecNameLength;
338
340 $offset += 2;
341 $thisfile_asf_codeclistobject_codecentries_current['description'] = substr($ASFHeaderData, $offset, $CodecDescriptionLength);
342 $offset += $CodecDescriptionLength;
343
345 $offset += 2;
346 $thisfile_asf_codeclistobject_codecentries_current['information'] = substr($ASFHeaderData, $offset, $CodecInformationLength);
347 $offset += $CodecInformationLength;
348
349 if ($thisfile_asf_codeclistobject_codecentries_current['type_raw'] == 2) {
350
351 if (strpos($thisfile_asf_codeclistobject_codecentries_current['description'], ',') === false) {
352 $this->
warning(
'[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.
'][description] expected to contain comma-separated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current[
'description'].
'"');
353 } else {
354
355 list($AudioCodecBitrate, $AudioCodecFrequency, $AudioCodecChannels) = explode(
',', $this->
TrimConvert($thisfile_asf_codeclistobject_codecentries_current[
'description']));
356 $thisfile_audio[
'codec'] = $this->
TrimConvert($thisfile_asf_codeclistobject_codecentries_current[
'name']);
357
358 if (!isset($thisfile_audio['bitrate']) && strstr($AudioCodecBitrate, 'kbps')) {
359 $thisfile_audio['bitrate'] = (int) (trim(str_replace('kbps', '', $AudioCodecBitrate)) * 1000);
360 }
361
362 if (empty($thisfile_video[
'bitrate']) && !empty($thisfile_audio[
'bitrate']) && !empty(
$info[
'bitrate'])) {
363
364 $thisfile_video[
'bitrate'] =
$info[
'bitrate'] - $thisfile_audio[
'bitrate'];
365 }
366
367 $AudioCodecFrequency = (int) trim(str_replace('kHz', '', $AudioCodecFrequency));
368 switch ($AudioCodecFrequency) {
369 case 8:
370 case 8000:
371 $thisfile_audio['sample_rate'] = 8000;
372 break;
373
374 case 11:
375 case 11025:
376 $thisfile_audio['sample_rate'] = 11025;
377 break;
378
379 case 12:
380 case 12000:
381 $thisfile_audio['sample_rate'] = 12000;
382 break;
383
384 case 16:
385 case 16000:
386 $thisfile_audio['sample_rate'] = 16000;
387 break;
388
389 case 22:
390 case 22050:
391 $thisfile_audio['sample_rate'] = 22050;
392 break;
393
394 case 24:
395 case 24000:
396 $thisfile_audio['sample_rate'] = 24000;
397 break;
398
399 case 32:
400 case 32000:
401 $thisfile_audio['sample_rate'] = 32000;
402 break;
403
404 case 44:
405 case 441000:
406 $thisfile_audio['sample_rate'] = 44100;
407 break;
408
409 case 48:
410 case 48000:
411 $thisfile_audio['sample_rate'] = 48000;
412 break;
413
414 default:
415 $this->
warning(
'unknown frequency: "'.$AudioCodecFrequency.
'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current[
'description']).
')');
416 break;
417 }
418
419 if (!isset($thisfile_audio['channels'])) {
420 if (strstr($AudioCodecChannels, 'stereo')) {
421 $thisfile_audio['channels'] = 2;
422 } elseif (strstr($AudioCodecChannels, 'mono')) {
423 $thisfile_audio['channels'] = 1;
424 }
425 }
426
427 }
428 }
429 }
430 break;
431
432 case GETID3_ASF_Script_Command_Object:
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450 $thisfile_asf['script_command_object'] = array();
451 $thisfile_asf_scriptcommandobject = &$thisfile_asf['script_command_object'];
452
453 $thisfile_asf_scriptcommandobject['offset'] = $NextObjectOffset + $offset;
454 $thisfile_asf_scriptcommandobject['objectid'] = $NextObjectGUID;
455 $thisfile_asf_scriptcommandobject['objectid_guid'] = $NextObjectGUIDtext;
456 $thisfile_asf_scriptcommandobject['objectsize'] = $NextObjectSize;
457 $thisfile_asf_scriptcommandobject['reserved'] = substr($ASFHeaderData, $offset, 16);
458 $offset += 16;
459 $thisfile_asf_scriptcommandobject[
'reserved_guid'] = $this->
BytestringToGUID($thisfile_asf_scriptcommandobject[
'reserved']);
460 if ($thisfile_asf_scriptcommandobject[
'reserved'] != $this->
GUIDtoBytestring(
'4B1ACBE3-100B-11D0-A39B-00A0C90348F6')) {
461 $this->
warning(
'script_command_object.reserved GUID {'.$this->
BytestringToGUID($thisfile_asf_scriptcommandobject[
'reserved']).
'} does not match expected "GETID3_ASF_Reserved_1" GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}');
462
463 break;
464 }
466 $offset += 2;
468 $offset += 2;
469 for ($CommandTypesCounter = 0; $CommandTypesCounter < $thisfile_asf_scriptcommandobject['command_types_count']; $CommandTypesCounter++) {
471 $offset += 2;
472 $thisfile_asf_scriptcommandobject['command_types'][$CommandTypesCounter]['name'] = substr($ASFHeaderData, $offset, $CommandTypeNameLength);
473 $offset += $CommandTypeNameLength;
474 }
475 for ($CommandsCounter = 0; $CommandsCounter < $thisfile_asf_scriptcommandobject['commands_count']; $CommandsCounter++) {
476 $thisfile_asf_scriptcommandobject[
'commands'][$CommandsCounter][
'presentation_time'] =
getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
477 $offset += 4;
478 $thisfile_asf_scriptcommandobject[
'commands'][$CommandsCounter][
'type_index'] =
getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
479 $offset += 2;
480
482 $offset += 2;
483 $thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['name'] = substr($ASFHeaderData, $offset, $CommandTypeNameLength);
484 $offset += $CommandTypeNameLength;
485 }
486 break;
487
488 case GETID3_ASF_Marker_Object:
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509 $thisfile_asf['marker_object'] = array();
510 $thisfile_asf_markerobject = &$thisfile_asf['marker_object'];
511
512 $thisfile_asf_markerobject['offset'] = $NextObjectOffset + $offset;
513 $thisfile_asf_markerobject['objectid'] = $NextObjectGUID;
514 $thisfile_asf_markerobject['objectid_guid'] = $NextObjectGUIDtext;
515 $thisfile_asf_markerobject['objectsize'] = $NextObjectSize;
516 $thisfile_asf_markerobject['reserved'] = substr($ASFHeaderData, $offset, 16);
517 $offset += 16;
518 $thisfile_asf_markerobject[
'reserved_guid'] = $this->
BytestringToGUID($thisfile_asf_markerobject[
'reserved']);
519 if ($thisfile_asf_markerobject[
'reserved'] != $this->
GUIDtoBytestring(
'4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) {
520 $this->
warning(
'marker_object.reserved GUID {'.$this->
BytestringToGUID($thisfile_asf_markerobject[
'reserved_1']).
'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}');
521 break;
522 }
524 $offset += 4;
526 $offset += 2;
527 if ($thisfile_asf_markerobject['reserved_2'] != 0) {
529 break;
530 }
532 $offset += 2;
533 $thisfile_asf_markerobject['name'] = substr($ASFHeaderData, $offset, $thisfile_asf_markerobject['name_length']);
534 $offset += $thisfile_asf_markerobject['name_length'];
535 for ($MarkersCounter = 0; $MarkersCounter < $thisfile_asf_markerobject['markers_count']; $MarkersCounter++) {
537 $offset += 8;
538 $thisfile_asf_markerobject[
'markers'][$MarkersCounter][
'presentation_time'] =
getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
539 $offset += 8;
540 $thisfile_asf_markerobject[
'markers'][$MarkersCounter][
'entry_length'] =
getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
541 $offset += 2;
543 $offset += 4;
545 $offset += 4;
546 $thisfile_asf_markerobject[
'markers'][$MarkersCounter][
'marker_description_length'] =
getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
547 $offset += 4;
548 $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description'] = substr($ASFHeaderData, $offset, $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length']);
549 $offset += $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length'];
550 $PaddingLength = $thisfile_asf_markerobject['markers'][$MarkersCounter]['entry_length'] - 4 - 4 - 4 - $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length'];
551 if ($PaddingLength > 0) {
552 $thisfile_asf_markerobject['markers'][$MarkersCounter]['padding'] = substr($ASFHeaderData, $offset, $PaddingLength);
553 $offset += $PaddingLength;
554 }
555 }
556 break;
557
558 case GETID3_ASF_Bitrate_Mutual_Exclusion_Object:
559
560
561
562
563
564
565
566
567
568 $thisfile_asf['bitrate_mutual_exclusion_object'] = array();
569 $thisfile_asf_bitratemutualexclusionobject = &$thisfile_asf['bitrate_mutual_exclusion_object'];
570
571 $thisfile_asf_bitratemutualexclusionobject['offset'] = $NextObjectOffset + $offset;
572 $thisfile_asf_bitratemutualexclusionobject['objectid'] = $NextObjectGUID;
573 $thisfile_asf_bitratemutualexclusionobject['objectid_guid'] = $NextObjectGUIDtext;
574 $thisfile_asf_bitratemutualexclusionobject['objectsize'] = $NextObjectSize;
575 $thisfile_asf_bitratemutualexclusionobject['reserved'] = substr($ASFHeaderData, $offset, 16);
576 $thisfile_asf_bitratemutualexclusionobject[
'reserved_guid'] = $this->
BytestringToGUID($thisfile_asf_bitratemutualexclusionobject[
'reserved']);
577 $offset += 16;
578 if (($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Bitrate) && ($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Unknown)) {
579 $this->
warning(
'bitrate_mutual_exclusion_object.reserved GUID {'.$this->
BytestringToGUID($thisfile_asf_bitratemutualexclusionobject[
'reserved']).
'} does not match expected "GETID3_ASF_Mutex_Bitrate" GUID {'.$this->
BytestringToGUID(GETID3_ASF_Mutex_Bitrate).
'} or "GETID3_ASF_Mutex_Unknown" GUID {'.$this->
BytestringToGUID(GETID3_ASF_Mutex_Unknown).
'}');
580
581 break;
582 }
584 $offset += 2;
585 for ($StreamNumberCounter = 0; $StreamNumberCounter < $thisfile_asf_bitratemutualexclusionobject['stream_numbers_count']; $StreamNumberCounter++) {
586 $thisfile_asf_bitratemutualexclusionobject[
'stream_numbers'][$StreamNumberCounter] =
getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
587 $offset += 2;
588 }
589 break;
590
591 case GETID3_ASF_Error_Correction_Object:
592
593
594
595
596
597
598
599
600
601 $thisfile_asf['error_correction_object'] = array();
602 $thisfile_asf_errorcorrectionobject = &$thisfile_asf['error_correction_object'];
603
604 $thisfile_asf_errorcorrectionobject['offset'] = $NextObjectOffset + $offset;
605 $thisfile_asf_errorcorrectionobject['objectid'] = $NextObjectGUID;
606 $thisfile_asf_errorcorrectionobject['objectid_guid'] = $NextObjectGUIDtext;
607 $thisfile_asf_errorcorrectionobject['objectsize'] = $NextObjectSize;
608 $thisfile_asf_errorcorrectionobject['error_correction_type'] = substr($ASFHeaderData, $offset, 16);
609 $offset += 16;
610 $thisfile_asf_errorcorrectionobject[
'error_correction_guid'] = $this->
BytestringToGUID($thisfile_asf_errorcorrectionobject[
'error_correction_type']);
612 $offset += 4;
613 switch ($thisfile_asf_errorcorrectionobject['error_correction_type']) {
614 case GETID3_ASF_No_Error_Correction:
615
616 $offset += $thisfile_asf_errorcorrectionobject['error_correction_data_length'];
617 break;
618
619 case GETID3_ASF_Audio_Spread:
620
621
622
623
624
625
626
628 $offset += 1;
630 $offset += 2;
632 $offset += 2;
634 $offset += 2;
635 $thisfile_asf_errorcorrectionobject['silence_data'] = substr($ASFHeaderData, $offset, $thisfile_asf_errorcorrectionobject['silence_data_length']);
636 $offset += $thisfile_asf_errorcorrectionobject['silence_data_length'];
637 break;
638
639 default:
640 $this->
warning(
'error_correction_object.error_correction_type GUID {'.$this->
BytestringToGUID($thisfile_asf_errorcorrectionobject[
'reserved']).
'} does not match expected "GETID3_ASF_No_Error_Correction" GUID {'.$this->
BytestringToGUID(GETID3_ASF_No_Error_Correction).
'} or "GETID3_ASF_Audio_Spread" GUID {'.$this->
BytestringToGUID(GETID3_ASF_Audio_Spread).
'}');
641
642 break;
643 }
644
645 break;
646
647 case GETID3_ASF_Content_Description_Object:
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664 $thisfile_asf['content_description_object'] = array();
665 $thisfile_asf_contentdescriptionobject = &$thisfile_asf['content_description_object'];
666
667 $thisfile_asf_contentdescriptionobject['offset'] = $NextObjectOffset + $offset;
668 $thisfile_asf_contentdescriptionobject['objectid'] = $NextObjectGUID;
669 $thisfile_asf_contentdescriptionobject['objectid_guid'] = $NextObjectGUIDtext;
670 $thisfile_asf_contentdescriptionobject['objectsize'] = $NextObjectSize;
672 $offset += 2;
674 $offset += 2;
676 $offset += 2;
678 $offset += 2;
680 $offset += 2;
681 $thisfile_asf_contentdescriptionobject['title'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['title_length']);
682 $offset += $thisfile_asf_contentdescriptionobject['title_length'];
683 $thisfile_asf_contentdescriptionobject['author'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['author_length']);
684 $offset += $thisfile_asf_contentdescriptionobject['author_length'];
685 $thisfile_asf_contentdescriptionobject['copyright'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['copyright_length']);
686 $offset += $thisfile_asf_contentdescriptionobject['copyright_length'];
687 $thisfile_asf_contentdescriptionobject['description'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['description_length']);
688 $offset += $thisfile_asf_contentdescriptionobject['description_length'];
689 $thisfile_asf_contentdescriptionobject['rating'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['rating_length']);
690 $offset += $thisfile_asf_contentdescriptionobject['rating_length'];
691
692 $ASFcommentKeysToCopy = array('title'=>'title', 'author'=>'artist', 'copyright'=>'copyright', 'description'=>'comment', 'rating'=>'rating');
693 foreach ($ASFcommentKeysToCopy as $keytocopyfrom => $keytocopyto) {
694 if (!empty($thisfile_asf_contentdescriptionobject[$keytocopyfrom])) {
695 $thisfile_asf_comments[$keytocopyto][] = $this->
TrimTerm($thisfile_asf_contentdescriptionobject[$keytocopyfrom]);
696 }
697 }
698 break;
699
700 case GETID3_ASF_Extended_Content_Description_Object:
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720 $thisfile_asf['extended_content_description_object'] = array();
721 $thisfile_asf_extendedcontentdescriptionobject = &$thisfile_asf['extended_content_description_object'];
722
723 $thisfile_asf_extendedcontentdescriptionobject['offset'] = $NextObjectOffset + $offset;
724 $thisfile_asf_extendedcontentdescriptionobject['objectid'] = $NextObjectGUID;
725 $thisfile_asf_extendedcontentdescriptionobject['objectid_guid'] = $NextObjectGUIDtext;
726 $thisfile_asf_extendedcontentdescriptionobject['objectsize'] = $NextObjectSize;
727 $thisfile_asf_extendedcontentdescriptionobject[
'content_descriptors_count'] =
getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
728 $offset += 2;
729 for ($ExtendedContentDescriptorsCounter = 0; $ExtendedContentDescriptorsCounter < $thisfile_asf_extendedcontentdescriptionobject['content_descriptors_count']; $ExtendedContentDescriptorsCounter++) {
730
731 $thisfile_asf_extendedcontentdescriptionobject['content_descriptors'][$ExtendedContentDescriptorsCounter] = array();
732 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current = &$thisfile_asf_extendedcontentdescriptionobject['content_descriptors'][$ExtendedContentDescriptorsCounter];
733
734 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['base_offset'] = $offset + 30;
735 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'name_length'] =
getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
736 $offset += 2;
737 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name'] = substr($ASFHeaderData, $offset, $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name_length']);
738 $offset += $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name_length'];
739 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value_type'] =
getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
740 $offset += 2;
741 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value_length'] =
getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
742 $offset += 2;
743 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = substr($ASFHeaderData, $offset, $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length']);
744 $offset += $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length'];
745 switch ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type']) {
746 case 0x0000:
747 break;
748
749 case 0x0001:
750
751 break;
752
753 case 0x0002:
754 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value'] = (bool)
getid3_lib::LittleEndian2Int($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']);
755 break;
756
757 case 0x0003:
758 case 0x0004:
759 case 0x0005:
760 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value'] =
getid3_lib::LittleEndian2Int($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']);
761 break;
762
763 default:
764 $this->
warning(
'extended_content_description.content_descriptors.'.$ExtendedContentDescriptorsCounter.
'.value_type is invalid ('.$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value_type'].
')');
765
766 break;
767 }
768 switch ($this->
TrimConvert(strtolower($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'name']))) {
769
770 case 'wm/albumartist':
771 case 'artist':
772
773 $thisfile_asf_comments[
'albumartist'] = array($this->
TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']));
774 break;
775
776 case 'wm/albumtitle':
777 case 'album':
778 $thisfile_asf_comments[
'album'] = array($this->
TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']));
779 break;
780
781 case 'wm/genre':
782 case 'genre':
783 $thisfile_asf_comments[
'genre'] = array($this->
TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']));
784 break;
785
786 case 'wm/partofset':
787 $thisfile_asf_comments[
'partofset'] = array($this->
TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']));
788 break;
789
790 case 'wm/tracknumber':
791 case 'tracknumber':
792
793 $thisfile_asf_comments[
'track'] = array($this->
TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']));
794 foreach ($thisfile_asf_comments[
'track'] as
$key => $value) {
795 if (preg_match('/^[0-9\x00]+$/', $value)) {
796 $thisfile_asf_comments[
'track'][
$key] = intval(str_replace(
"\x00",
'', $value));
797 }
798 }
799 break;
800
801 case 'wm/track':
802 if (empty($thisfile_asf_comments['track'])) {
803 $thisfile_asf_comments[
'track'] = array(1 + $this->
TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']));
804 }
805 break;
806
807 case 'wm/year':
808 case 'year':
809 case 'date':
810 $thisfile_asf_comments[
'year'] = array( $this->
TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']));
811 break;
812
813 case 'wm/lyrics':
814 case 'lyrics':
815 $thisfile_asf_comments[
'lyrics'] = array($this->
TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']));
816 break;
817
818 case 'isvbr':
819 if ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']) {
820 $thisfile_audio['bitrate_mode'] = 'vbr';
821 $thisfile_video['bitrate_mode'] = 'vbr';
822 }
823 break;
824
825 case 'id3':
826 $this->getid3->include_module('tag.id3v2');
827
829 $getid3_id3v2->AnalyzeString($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']);
830 unset($getid3_id3v2);
831
832 if ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length'] > 1024) {
833 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = '<value too large to display>';
834 }
835 break;
836
837 case 'wm/encodingtime':
838 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'encoding_time_unix'] = $this->
FILETIMEtoUNIXtime($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']);
839 $thisfile_asf_comments['encoding_time_unix'] = array($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['encoding_time_unix']);
840 break;
841
842 case 'wm/picture':
843 $WMpicture = $this->
ASF_WMpicture($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']);
844 foreach ($WMpicture as
$key => $value) {
845 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
$key] = $value;
846 }
847 unset($WMpicture);
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886 break;
887
888 default:
889 switch ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type']) {
890 case 0:
891 if (substr($this->
TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'name']), 0, 3) ==
'WM/') {
892 $thisfile_asf_comments[str_replace(
'wm/',
'', strtolower($this->
TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'name'])))] = array($this->
TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']));
893 }
894 break;
895
896 case 1:
897 break;
898 }
899 break;
900 }
901
902 }
903 break;
904
905 case GETID3_ASF_Stream_Bitrate_Properties_Object:
906
907
908
909
910
911
912
913
914
915
916
917
918 $thisfile_asf['stream_bitrate_properties_object'] = array();
919 $thisfile_asf_streambitratepropertiesobject = &$thisfile_asf['stream_bitrate_properties_object'];
920
921 $thisfile_asf_streambitratepropertiesobject['offset'] = $NextObjectOffset + $offset;
922 $thisfile_asf_streambitratepropertiesobject['objectid'] = $NextObjectGUID;
923 $thisfile_asf_streambitratepropertiesobject['objectid_guid'] = $NextObjectGUIDtext;
924 $thisfile_asf_streambitratepropertiesobject['objectsize'] = $NextObjectSize;
925 $thisfile_asf_streambitratepropertiesobject[
'bitrate_records_count'] =
getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
926 $offset += 2;
927 for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitratepropertiesobject['bitrate_records_count']; $BitrateRecordsCounter++) {
928 $thisfile_asf_streambitratepropertiesobject[
'bitrate_records'][$BitrateRecordsCounter][
'flags_raw'] =
getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
929 $offset += 2;
930 $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['flags']['stream_number'] = $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['flags_raw'] & 0x007F;
931 $thisfile_asf_streambitratepropertiesobject[
'bitrate_records'][$BitrateRecordsCounter][
'bitrate'] =
getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
932 $offset += 4;
933 }
934 break;
935
936 case GETID3_ASF_Padding_Object:
937
938
939
940
941
942
943
944 $thisfile_asf['padding_object'] = array();
945 $thisfile_asf_paddingobject = &$thisfile_asf['padding_object'];
946
947 $thisfile_asf_paddingobject['offset'] = $NextObjectOffset + $offset;
948 $thisfile_asf_paddingobject['objectid'] = $NextObjectGUID;
949 $thisfile_asf_paddingobject['objectid_guid'] = $NextObjectGUIDtext;
950 $thisfile_asf_paddingobject['objectsize'] = $NextObjectSize;
951 $thisfile_asf_paddingobject['padding_length'] = $thisfile_asf_paddingobject['objectsize'] - 16 - 8;
952 $thisfile_asf_paddingobject['padding'] = substr($ASFHeaderData, $offset, $thisfile_asf_paddingobject['padding_length']);
953 $offset += ($NextObjectSize - 16 - 8);
954 break;
955
956 case GETID3_ASF_Extended_Content_Encryption_Object:
957 case GETID3_ASF_Content_Encryption_Object:
958
959 $offset += ($NextObjectSize - 16 - 8);
960 break;
961
962 default:
963
964 if ($this->
GUIDname($NextObjectGUIDtext)) {
965 $this->
warning(
'unhandled GUID "'.$this->
GUIDname($NextObjectGUIDtext).
'" {'.$NextObjectGUIDtext.
'} in ASF header at offset '.($offset - 16 - 8));
966 } else {
967 $this->
warning(
'unknown GUID {'.$NextObjectGUIDtext.
'} in ASF header at offset '.($offset - 16 - 8));
968 }
969 $offset += ($NextObjectSize - 16 - 8);
970 break;
971 }
972 }
973 if (isset($thisfile_asf_streambitrateproperties['bitrate_records_count'])) {
974 $ASFbitrateAudio = 0;
975 $ASFbitrateVideo = 0;
976 for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitrateproperties['bitrate_records_count']; $BitrateRecordsCounter++) {
977 if (isset($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter])) {
978 switch ($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter]['type_raw']) {
979 case 1:
980 $ASFbitrateVideo += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
981 break;
982
983 case 2:
984 $ASFbitrateAudio += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
985 break;
986
987 default:
988
989 break;
990 }
991 }
992 }
993 if ($ASFbitrateAudio > 0) {
994 $thisfile_audio['bitrate'] = $ASFbitrateAudio;
995 }
996 if ($ASFbitrateVideo > 0) {
997 $thisfile_video['bitrate'] = $ASFbitrateVideo;
998 }
999 }
1000 if (isset($thisfile_asf['stream_properties_object']) && is_array($thisfile_asf['stream_properties_object'])) {
1001
1002 $thisfile_audio['bitrate'] = 0;
1003 $thisfile_video['bitrate'] = 0;
1004
1005 foreach ($thisfile_asf['stream_properties_object'] as $streamnumber => $streamdata) {
1006
1007 switch ($streamdata['stream_type']) {
1008 case GETID3_ASF_Audio_Media:
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 $thisfile_asf['audio_media'][$streamnumber] = array();
1021 $thisfile_asf_audiomedia_currentstream = &$thisfile_asf['audio_media'][$streamnumber];
1022
1023 $audiomediaoffset = 0;
1024
1026 $audiomediaoffset += 16;
1027
1028 $thisfile_audio['lossless'] = false;
1029 switch ($thisfile_asf_audiomedia_currentstream['raw']['wFormatTag']) {
1030 case 0x0001:
1031 case 0x0163:
1032 $thisfile_audio['lossless'] = true;
1033 break;
1034 }
1035
1036 if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) {
1037 foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) {
1038 if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) {
1039 $thisfile_asf_audiomedia_currentstream['bitrate'] = $dataarray['bitrate'];
1040 $thisfile_audio['bitrate'] += $dataarray['bitrate'];
1041 break;
1042 }
1043 }
1044 } else {
1045 if (!empty($thisfile_asf_audiomedia_currentstream['bytes_sec'])) {
1046 $thisfile_audio['bitrate'] += $thisfile_asf_audiomedia_currentstream['bytes_sec'] * 8;
1047 } elseif (!empty($thisfile_asf_audiomedia_currentstream['bitrate'])) {
1048 $thisfile_audio['bitrate'] += $thisfile_asf_audiomedia_currentstream['bitrate'];
1049 }
1050 }
1051 $thisfile_audio['streams'][$streamnumber] = $thisfile_asf_audiomedia_currentstream;
1052 $thisfile_audio['streams'][$streamnumber]['wformattag'] = $thisfile_asf_audiomedia_currentstream['raw']['wFormatTag'];
1053 $thisfile_audio['streams'][$streamnumber]['lossless'] = $thisfile_audio['lossless'];
1054 $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate'];
1055 $thisfile_audio['streams'][$streamnumber]['dataformat'] = 'wma';
1056 unset($thisfile_audio['streams'][$streamnumber]['raw']);
1057
1058 $thisfile_asf_audiomedia_currentstream[
'codec_data_size'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $audiomediaoffset, 2));
1059 $audiomediaoffset += 2;
1060 $thisfile_asf_audiomedia_currentstream['codec_data'] = substr($streamdata['type_specific_data'], $audiomediaoffset, $thisfile_asf_audiomedia_currentstream['codec_data_size']);
1061 $audiomediaoffset += $thisfile_asf_audiomedia_currentstream['codec_data_size'];
1062
1063 break;
1064
1065 case GETID3_ASF_Video_Media:
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086 $thisfile_asf['video_media'][$streamnumber] = array();
1087 $thisfile_asf_videomedia_currentstream = &$thisfile_asf['video_media'][$streamnumber];
1088
1089 $videomediaoffset = 0;
1090 $thisfile_asf_videomedia_currentstream[
'image_width'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 4));
1091 $videomediaoffset += 4;
1092 $thisfile_asf_videomedia_currentstream[
'image_height'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 4));
1093 $videomediaoffset += 4;
1094 $thisfile_asf_videomedia_currentstream[
'flags'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 1));
1095 $videomediaoffset += 1;
1096 $thisfile_asf_videomedia_currentstream[
'format_data_size'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 2));
1097 $videomediaoffset += 2;
1098 $thisfile_asf_videomedia_currentstream[
'format_data'][
'format_data_size'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 4));
1099 $videomediaoffset += 4;
1100 $thisfile_asf_videomedia_currentstream[
'format_data'][
'image_width'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 4));
1101 $videomediaoffset += 4;
1102 $thisfile_asf_videomedia_currentstream[
'format_data'][
'image_height'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 4));
1103 $videomediaoffset += 4;
1104 $thisfile_asf_videomedia_currentstream[
'format_data'][
'reserved'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 2));
1105 $videomediaoffset += 2;
1106 $thisfile_asf_videomedia_currentstream[
'format_data'][
'bits_per_pixel'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 2));
1107 $videomediaoffset += 2;
1108 $thisfile_asf_videomedia_currentstream['format_data']['codec_fourcc'] = substr($streamdata['type_specific_data'], $videomediaoffset, 4);
1109 $videomediaoffset += 4;
1110 $thisfile_asf_videomedia_currentstream[
'format_data'][
'image_size'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 4));
1111 $videomediaoffset += 4;
1112 $thisfile_asf_videomedia_currentstream[
'format_data'][
'horizontal_pels'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 4));
1113 $videomediaoffset += 4;
1114 $thisfile_asf_videomedia_currentstream[
'format_data'][
'vertical_pels'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 4));
1115 $videomediaoffset += 4;
1116 $thisfile_asf_videomedia_currentstream[
'format_data'][
'colors_used'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 4));
1117 $videomediaoffset += 4;
1118 $thisfile_asf_videomedia_currentstream[
'format_data'][
'colors_important'] =
getid3_lib::LittleEndian2Int(substr($streamdata[
'type_specific_data'], $videomediaoffset, 4));
1119 $videomediaoffset += 4;
1120 $thisfile_asf_videomedia_currentstream['format_data']['codec_data'] = substr($streamdata['type_specific_data'], $videomediaoffset);
1121
1122 if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) {
1123 foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) {
1124 if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) {
1125 $thisfile_asf_videomedia_currentstream['bitrate'] = $dataarray['bitrate'];
1126 $thisfile_video['streams'][$streamnumber]['bitrate'] = $dataarray['bitrate'];
1127 $thisfile_video['bitrate'] += $dataarray['bitrate'];
1128 break;
1129 }
1130 }
1131 }
1132
1133 $thisfile_asf_videomedia_currentstream[
'format_data'][
'codec'] =
getid3_riff::fourccLookup($thisfile_asf_videomedia_currentstream[
'format_data'][
'codec_fourcc']);
1134
1135 $thisfile_video['streams'][$streamnumber]['fourcc'] = $thisfile_asf_videomedia_currentstream['format_data']['codec_fourcc'];
1136 $thisfile_video['streams'][$streamnumber]['codec'] = $thisfile_asf_videomedia_currentstream['format_data']['codec'];
1137 $thisfile_video['streams'][$streamnumber]['resolution_x'] = $thisfile_asf_videomedia_currentstream['image_width'];
1138 $thisfile_video['streams'][$streamnumber]['resolution_y'] = $thisfile_asf_videomedia_currentstream['image_height'];
1139 $thisfile_video['streams'][$streamnumber]['bits_per_sample'] = $thisfile_asf_videomedia_currentstream['format_data']['bits_per_pixel'];
1140 break;
1141
1142 default:
1143 break;
1144 }
1145 }
1146 }
1147
1148 while ($this->
ftell() <
$info[
'avdataend']) {
1149 $NextObjectDataHeader = $this->
fread(24);
1150 $offset = 0;
1151 $NextObjectGUID = substr($NextObjectDataHeader, 0, 16);
1152 $offset += 16;
1155 $offset += 8;
1156
1157 switch ($NextObjectGUID) {
1158 case GETID3_ASF_Data_Object:
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168 $thisfile_asf['data_object'] = array();
1169 $thisfile_asf_dataobject = &$thisfile_asf['data_object'];
1170
1171 $DataObjectData = $NextObjectDataHeader.$this->fread(50 - 24);
1172 $offset = 24;
1173
1174 $thisfile_asf_dataobject['objectid'] = $NextObjectGUID;
1175 $thisfile_asf_dataobject['objectid_guid'] = $NextObjectGUIDtext;
1176 $thisfile_asf_dataobject['objectsize'] = $NextObjectSize;
1177
1178 $thisfile_asf_dataobject['fileid'] = substr($DataObjectData, $offset, 16);
1179 $offset += 16;
1180 $thisfile_asf_dataobject[
'fileid_guid'] = $this->
BytestringToGUID($thisfile_asf_dataobject[
'fileid']);
1182 $offset += 8;
1184 $offset += 2;
1185 if ($thisfile_asf_dataobject['reserved'] != 0x0101) {
1187
1188 break;
1189 }
1190
1191
1192
1193
1194
1195
1196
1197
1198
1200 $this->
fseek(($thisfile_asf_dataobject[
'objectsize'] - 50), SEEK_CUR);
1202 break;
1203
1204 case GETID3_ASF_Simple_Index_Object:
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218 $thisfile_asf['simple_index_object'] = array();
1219 $thisfile_asf_simpleindexobject = &$thisfile_asf['simple_index_object'];
1220
1221 $SimpleIndexObjectData = $NextObjectDataHeader.$this->fread(56 - 24);
1222 $offset = 24;
1223
1224 $thisfile_asf_simpleindexobject['objectid'] = $NextObjectGUID;
1225 $thisfile_asf_simpleindexobject['objectid_guid'] = $NextObjectGUIDtext;
1226 $thisfile_asf_simpleindexobject['objectsize'] = $NextObjectSize;
1227
1228 $thisfile_asf_simpleindexobject['fileid'] = substr($SimpleIndexObjectData, $offset, 16);
1229 $offset += 16;
1230 $thisfile_asf_simpleindexobject[
'fileid_guid'] = $this->
BytestringToGUID($thisfile_asf_simpleindexobject[
'fileid']);
1231 $thisfile_asf_simpleindexobject[
'index_entry_time_interval'] =
getid3_lib::LittleEndian2Int(substr($SimpleIndexObjectData, $offset, 8));
1232 $offset += 8;
1234 $offset += 4;
1236 $offset += 4;
1237
1238 $IndexEntriesData = $SimpleIndexObjectData.$this->fread(6 * $thisfile_asf_simpleindexobject['index_entries_count']);
1239 for ($IndexEntriesCounter = 0; $IndexEntriesCounter < $thisfile_asf_simpleindexobject['index_entries_count']; $IndexEntriesCounter++) {
1240 $thisfile_asf_simpleindexobject[
'index_entries'][$IndexEntriesCounter][
'packet_number'] =
getid3_lib::LittleEndian2Int(substr($IndexEntriesData, $offset, 4));
1241 $offset += 4;
1242 $thisfile_asf_simpleindexobject[
'index_entries'][$IndexEntriesCounter][
'packet_count'] =
getid3_lib::LittleEndian2Int(substr($IndexEntriesData, $offset, 4));
1243 $offset += 2;
1244 }
1245
1246 break;
1247
1248 case GETID3_ASF_Index_Object:
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272 $thisfile_asf['asf_index_object'] = array();
1273 $thisfile_asf_asfindexobject = &$thisfile_asf['asf_index_object'];
1274
1275 $ASFIndexObjectData = $NextObjectDataHeader.$this->fread(34 - 24);
1276 $offset = 24;
1277
1278 $thisfile_asf_asfindexobject['objectid'] = $NextObjectGUID;
1279 $thisfile_asf_asfindexobject['objectid_guid'] = $NextObjectGUIDtext;
1280 $thisfile_asf_asfindexobject['objectsize'] = $NextObjectSize;
1281
1283 $offset += 4;
1285 $offset += 2;
1287 $offset += 4;
1288
1289 $ASFIndexObjectData .= $this->
fread(4 * $thisfile_asf_asfindexobject[
'index_specifiers_count']);
1290 for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) {
1292 $offset += 2;
1293 $thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['stream_number'] = $IndexSpecifierStreamNumber;
1294 $thisfile_asf_asfindexobject[
'index_specifiers'][$IndexSpecifiersCounter][
'index_type'] =
getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 2));
1295 $offset += 2;
1296 $thisfile_asf_asfindexobject[
'index_specifiers'][$IndexSpecifiersCounter][
'index_type_text'] = $this->
ASFIndexObjectIndexTypeLookup($thisfile_asf_asfindexobject[
'index_specifiers'][$IndexSpecifiersCounter][
'index_type']);
1297 }
1298
1299 $ASFIndexObjectData .= $this->
fread(4);
1301 $offset += 4;
1302
1303 $ASFIndexObjectData .= $this->
fread(8 * $thisfile_asf_asfindexobject[
'index_specifiers_count']);
1304 for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) {
1305 $thisfile_asf_asfindexobject[
'block_positions'][$IndexSpecifiersCounter] =
getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 8));
1306 $offset += 8;
1307 }
1308
1309 $ASFIndexObjectData .= $this->
fread(4 * $thisfile_asf_asfindexobject[
'index_specifiers_count'] * $thisfile_asf_asfindexobject[
'index_entry_count']);
1310 for ($IndexEntryCounter = 0; $IndexEntryCounter < $thisfile_asf_asfindexobject['index_entry_count']; $IndexEntryCounter++) {
1311 for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) {
1312 $thisfile_asf_asfindexobject[
'offsets'][$IndexSpecifiersCounter][$IndexEntryCounter] =
getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4));
1313 $offset += 4;
1314 }
1315 }
1316 break;
1317
1318
1319 default:
1320
1321 if ($this->
GUIDname($NextObjectGUIDtext)) {
1322 $this->
warning(
'unhandled GUID "'.$this->
GUIDname($NextObjectGUIDtext).
'" {'.$NextObjectGUIDtext.
'} in ASF body at offset '.($offset - 16 - 8));
1323 } else {
1324 $this->
warning(
'unknown GUID {'.$NextObjectGUIDtext.
'} in ASF body at offset '.($this->ftell() - 16 - 8));
1325 }
1326 $this->
fseek(($NextObjectSize - 16 - 8), SEEK_CUR);
1327 break;
1328 }
1329 }
1330
1331 if (isset($thisfile_asf_codeclistobject['codec_entries']) && is_array($thisfile_asf_codeclistobject['codec_entries'])) {
1332 foreach ($thisfile_asf_codeclistobject['codec_entries'] as $streamnumber => $streamdata) {
1333 switch ($streamdata['information']) {
1334 case 'WMV1':
1335 case 'WMV2':
1336 case 'WMV3':
1337 case 'MSS1':
1338 case 'MSS2':
1339 case 'WMVA':
1340 case 'WVC1':
1341 case 'WMVP':
1342 case 'WVP2':
1343 $thisfile_video['dataformat'] = 'wmv';
1344 $info[
'mime_type'] =
'video/x-ms-wmv';
1345 break;
1346
1347 case 'MP42':
1348 case 'MP43':
1349 case 'MP4S':
1350 case 'mp4s':
1351 $thisfile_video['dataformat'] = 'asf';
1352 $info[
'mime_type'] =
'video/x-ms-asf';
1353 break;
1354
1355 default:
1356 switch ($streamdata['type_raw']) {
1357 case 1:
1358 if (strstr($this->
TrimConvert($streamdata[
'name']),
'Windows Media')) {
1359 $thisfile_video['dataformat'] = 'wmv';
1360 if (
$info[
'mime_type'] ==
'video/x-ms-asf') {
1361 $info[
'mime_type'] =
'video/x-ms-wmv';
1362 }
1363 }
1364 break;
1365
1366 case 2:
1367 if (strstr($this->
TrimConvert($streamdata[
'name']),
'Windows Media')) {
1368 $thisfile_audio['dataformat'] = 'wma';
1369 if (
$info[
'mime_type'] ==
'video/x-ms-asf') {
1370 $info[
'mime_type'] =
'audio/x-ms-wma';
1371 }
1372 }
1373 break;
1374
1375 }
1376 break;
1377 }
1378 }
1379 }
1380
1381 switch (isset($thisfile_audio['codec']) ? $thisfile_audio['codec'] : '') {
1382 case 'MPEG Layer-3':
1383 $thisfile_audio['dataformat'] = 'mp3';
1384 break;
1385
1386 default:
1387 break;
1388 }
1389
1390 if (isset($thisfile_asf_codeclistobject['codec_entries'])) {
1391 foreach ($thisfile_asf_codeclistobject['codec_entries'] as $streamnumber => $streamdata) {
1392 switch ($streamdata['type_raw']) {
1393
1394 case 1:
1395 $thisfile_video[
'encoder'] = $this->
TrimConvert($thisfile_asf_codeclistobject[
'codec_entries'][$streamnumber][
'name']);
1396 break;
1397
1398 case 2:
1399 $thisfile_audio[
'encoder'] = $this->
TrimConvert($thisfile_asf_codeclistobject[
'codec_entries'][$streamnumber][
'name']);
1400
1401
1402 $thisfile_audio[
'encoder_options'] = $this->
TrimConvert($thisfile_asf_codeclistobject[
'codec_entries'][0][
'description']);
1403
1404 $thisfile_audio['codec'] = $thisfile_audio['encoder'];
1405 break;
1406
1407 default:
1408 $this->
warning(
'Unknown streamtype: [codec_list_object][codec_entries]['.$streamnumber.
'][type_raw] == '.$streamdata[
'type_raw']);
1409 break;
1410
1411 }
1412 }
1413 }
1414
1415 if (isset(
$info[
'audio'])) {
1416 $thisfile_audio['lossless'] = (isset($thisfile_audio['lossless']) ? $thisfile_audio['lossless'] : false);
1417 $thisfile_audio['dataformat'] = (!empty($thisfile_audio['dataformat']) ? $thisfile_audio['dataformat'] : 'asf');
1418 }
1419 if (!empty($thisfile_video['dataformat'])) {
1420 $thisfile_video['lossless'] = (isset($thisfile_audio['lossless']) ? $thisfile_audio['lossless'] : false);
1421 $thisfile_video['pixel_aspect_ratio'] = (isset($thisfile_audio['pixel_aspect_ratio']) ? $thisfile_audio['pixel_aspect_ratio'] : (float) 1);
1422 $thisfile_video['dataformat'] = (!empty($thisfile_video['dataformat']) ? $thisfile_video['dataformat'] : 'asf');
1423 }
1424 if (!empty($thisfile_video['streams'])) {
1425 $thisfile_video['resolution_x'] = 0;
1426 $thisfile_video['resolution_y'] = 0;
1427 foreach ($thisfile_video[
'streams'] as
$key => $valuearray) {
1428 if (($valuearray['resolution_x'] > $thisfile_video['resolution_x']) || ($valuearray['resolution_y'] > $thisfile_video['resolution_y'])) {
1429 $thisfile_video['resolution_x'] = $valuearray['resolution_x'];
1430 $thisfile_video['resolution_y'] = $valuearray['resolution_y'];
1431 }
1432 }
1433 }
1434 $info[
'bitrate'] = (isset($thisfile_audio[
'bitrate']) ? $thisfile_audio[
'bitrate'] : 0) + (isset($thisfile_video[
'bitrate']) ? $thisfile_video[
'bitrate'] : 0);
1435
1436 if ((!isset(
$info[
'playtime_seconds']) || (
$info[
'playtime_seconds'] <= 0)) && (
$info[
'bitrate'] > 0)) {
1437 $info[
'playtime_seconds'] = (
$info[
'filesize'] -
$info[
'avdataoffset']) / (
$info[
'bitrate'] / 8);
1438 }
1439
1440 return true;
1441 }
HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections)
static FILETIMEtoUNIXtime($FILETIME, $round=true)
static ASFIndexObjectIndexTypeLookup($id)
static TrimConvert($string)
static GUIDname($GUIDstring)
static BytestringToGUID($Bytestring)
static codecListObjectTypeLookup($CodecListType)
fseek($bytes, $whence=SEEK_SET)
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
static LittleEndian2Int($byteword, $signed=false)
static array_merge_noclobber($array1, $array2)
static parseWAVEFORMATex($WaveFormatExData)
static fourccLookup($fourcc)