171 {
172 $info = &$this->getid3->info;
173
174
175 $thisfile_audio = &
$info[
'audio'];
176 $thisfile_video = &
$info[
'video'];
177 $info[
'asf'] = array();
178 $thisfile_asf = &
$info[
'asf'];
179 $thisfile_asf['comments'] = array();
180 $thisfile_asf_comments = &$thisfile_asf['comments'];
181 $thisfile_asf['header_object'] = array();
182 $thisfile_asf_headerobject = &$thisfile_asf['header_object'];
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 $info[
'fileformat'] =
'asf';
204
205 fseek($this->getid3->fp,
$info[
'avdataoffset'], SEEK_SET);
206 $HeaderObjectData =
fread($this->getid3->fp, 30);
207
208 $thisfile_asf_headerobject['objectid'] = substr($HeaderObjectData, 0, 16);
209 $thisfile_asf_headerobject[
'objectid_guid'] =
self::BytestringToGUID($thisfile_asf_headerobject[
'objectid']);
210 if ($thisfile_asf_headerobject['objectid'] != self::$GETID3_ASF_Header_Object) {
212 unset(
$info[
'fileformat']);
214
215 return false;
216 }
218 16,
219 8));
221 24,
222 4));
224 28,
225 1));
227 29,
228 1));
229
230 $NextObjectOffset =
ftell($this->getid3->fp);
231 $ASFHeaderData =
fread($this->getid3->fp,
232 $thisfile_asf_headerobject['objectsize'] - 30);
233 $offset = 0;
234
235 for ($HeaderObjectsCounter = 0;
236 $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects'];
237 $HeaderObjectsCounter++) {
238 $NextObjectGUID = substr($ASFHeaderData, $offset, 16);
239 $offset += 16;
242 $offset,
243 8));
244 $offset += 8;
245 switch ($NextObjectGUID) {
246
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267 $thisfile_asf['file_properties_object'] = array();
268 $thisfile_asf_filepropertiesobject = &$thisfile_asf['file_properties_object'];
269
270 $thisfile_asf_filepropertiesobject['offset'] = $NextObjectOffset + $offset;
271 $thisfile_asf_filepropertiesobject['objectid'] = $NextObjectGUID;
272 $thisfile_asf_filepropertiesobject['objectid_guid'] = $NextObjectGUIDtext;
273 $thisfile_asf_filepropertiesobject['objectsize'] = $NextObjectSize;
274 $thisfile_asf_filepropertiesobject['fileid'] = substr($ASFHeaderData,
275 $offset,
276 16);
277 $offset += 16;
278 $thisfile_asf_filepropertiesobject[
'fileid_guid'] =
self::BytestringToGUID($thisfile_asf_filepropertiesobject[
'fileid']);
280 $offset,
281 8));
282 $offset += 8;
284 $offset,
285 8));
286 $thisfile_asf_filepropertiesobject[
'creation_date_unix'] =
self::FILETIMEtoUNIXtime($thisfile_asf_filepropertiesobject[
'creation_date']);
287 $offset += 8;
289 $offset,
290 8));
291 $offset += 8;
293 $offset,
294 8));
295 $offset += 8;
297 $offset,
298 8));
299 $offset += 8;
301 $offset,
302 8));
303 $offset += 8;
305 $offset,
306 4));
307 $offset += 4;
308 $thisfile_asf_filepropertiesobject['flags']['broadcast'] = (bool) ($thisfile_asf_filepropertiesobject['flags_raw'] & 0x0001);
309 $thisfile_asf_filepropertiesobject['flags']['seekable'] = (bool) ($thisfile_asf_filepropertiesobject['flags_raw'] & 0x0002);
310
312 $offset,
313 4));
314 $offset += 4;
316 $offset,
317 4));
318 $offset += 4;
320 $offset,
321 4));
322 $offset += 4;
323
324 if ($thisfile_asf_filepropertiesobject['flags']['broadcast']) {
325
326
327 unset($thisfile_asf_filepropertiesobject['filesize']);
328 unset($thisfile_asf_filepropertiesobject['data_packets']);
329 unset($thisfile_asf_filepropertiesobject['play_duration']);
330 unset($thisfile_asf_filepropertiesobject['send_duration']);
331 unset($thisfile_asf_filepropertiesobject['min_packet_size']);
332 unset($thisfile_asf_filepropertiesobject['max_packet_size']);
333 } else {
334
335
336 $info[
'playtime_seconds'] = ($thisfile_asf_filepropertiesobject[
'play_duration'] / 10000000) - ($thisfile_asf_filepropertiesobject[
'preroll'] / 1000);
337
338
339 $info[
'bitrate'] = ((isset($thisfile_asf_filepropertiesobject[
'filesize']) ? $thisfile_asf_filepropertiesobject[
'filesize'] :
$info[
'filesize']) * 8) /
$info[
'playtime_seconds'];
340 }
341 break;
342
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363 $StreamPropertiesObjectData = array();
364 $StreamPropertiesObjectData['offset'] = $NextObjectOffset + $offset;
365 $StreamPropertiesObjectData['objectid'] = $NextObjectGUID;
366 $StreamPropertiesObjectData['objectid_guid'] = $NextObjectGUIDtext;
367 $StreamPropertiesObjectData['objectsize'] = $NextObjectSize;
368 $StreamPropertiesObjectData['stream_type'] = substr($ASFHeaderData,
369 $offset,
370 16);
371 $offset += 16;
372 $StreamPropertiesObjectData[
'stream_type_guid'] =
self::BytestringToGUID($StreamPropertiesObjectData[
'stream_type']);
373 $StreamPropertiesObjectData['error_correct_type'] = substr($ASFHeaderData,
374 $offset,
375 16);
376 $offset += 16;
377 $StreamPropertiesObjectData[
'error_correct_guid'] =
self::BytestringToGUID($StreamPropertiesObjectData[
'error_correct_type']);
379 $offset,
380 8));
381 $offset += 8;
383 $offset,
384 4));
385 $offset += 4;
387 $offset,
388 4));
389 $offset += 4;
391 $offset,
392 2));
393 $offset += 2;
394 $StreamPropertiesObjectStreamNumber = $StreamPropertiesObjectData['flags_raw'] & 0x007F;
395 $StreamPropertiesObjectData['flags']['encrypted'] = (bool) ($StreamPropertiesObjectData['flags_raw'] & 0x8000);
396
397 $offset += 4;
398 $StreamPropertiesObjectData['type_specific_data'] = substr($ASFHeaderData,
399 $offset,
400 $StreamPropertiesObjectData['type_data_length']);
401 $offset += $StreamPropertiesObjectData['type_data_length'];
402 $StreamPropertiesObjectData['error_correct_data'] = substr($ASFHeaderData,
403 $offset,
404 $StreamPropertiesObjectData['error_data_length']);
405 $offset += $StreamPropertiesObjectData['error_data_length'];
406
407 switch ($StreamPropertiesObjectData['stream_type']) {
408
410 $thisfile_audio['dataformat'] = (!empty($thisfile_audio['dataformat']) ? $thisfile_audio['dataformat'] : 'asf');
411 $thisfile_audio['bitrate_mode'] = (!empty($thisfile_audio['bitrate_mode']) ? $thisfile_audio['bitrate_mode'] : 'cbr');
412
414 0,
415 16));
416 unset($audiodata['raw']);
418 $thisfile_audio);
419 break;
420
422 $thisfile_video['dataformat'] = (!empty($thisfile_video['dataformat']) ? $thisfile_video['dataformat'] : 'asf');
423 $thisfile_video['bitrate_mode'] = (!empty($thisfile_video['bitrate_mode']) ? $thisfile_video['bitrate_mode'] : 'cbr');
424 break;
425
427 default:
428
429 break;
430 }
431
432 $thisfile_asf['stream_properties_object'][$StreamPropertiesObjectStreamNumber] = $StreamPropertiesObjectData;
433 unset($StreamPropertiesObjectData);
434 break;
435
437
438
439
440
441
442
443
444
445
446 $thisfile_asf['header_extension_object'] = array();
447 $thisfile_asf_headerextensionobject = &$thisfile_asf['header_extension_object'];
448
449 $thisfile_asf_headerextensionobject['offset'] = $NextObjectOffset + $offset;
450 $thisfile_asf_headerextensionobject['objectid'] = $NextObjectGUID;
451 $thisfile_asf_headerextensionobject['objectid_guid'] = $NextObjectGUIDtext;
452 $thisfile_asf_headerextensionobject['objectsize'] = $NextObjectSize;
453 $thisfile_asf_headerextensionobject['reserved_1'] = substr($ASFHeaderData,
454 $offset,
455 16);
456 $offset += 16;
457 $thisfile_asf_headerextensionobject[
'reserved_1_guid'] =
self::BytestringToGUID($thisfile_asf_headerextensionobject[
'reserved_1']);
458 if ($thisfile_asf_headerextensionobject['reserved_1'] != self::$GETID3_ASF_Reserved_1) {
459 $info[
'warning'][] =
'header_extension_object.reserved_1 GUID (' .
self::BytestringToGUID($thisfile_asf_headerextensionobject[
'reserved_1']) .
') does not match expected "GETID3_ASF_Reserved_1" GUID (' .
self::BytestringToGUID(self::$GETID3_ASF_Reserved_1) .
')';
460
461 break;
462 }
464 $offset,
465 2));
466 $offset += 2;
467 if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) {
468 $info[
'warning'][] =
'header_extension_object.reserved_2 (' .
Helper::PrintHexBytes($thisfile_asf_headerextensionobject[
'reserved_2']) .
') does not match expected value of "6"';
469
470 break;
471 }
473 $offset,
474 4));
475 $offset += 4;
476 $thisfile_asf_headerextensionobject['extension_data'] = substr($ASFHeaderData,
477 $offset,
478 $thisfile_asf_headerextensionobject['extension_data_size']);
479 $unhandled_sections = 0;
481 $unhandled_sections);
482 if ($unhandled_sections === 0) {
483 unset($thisfile_asf_headerextensionobject['extension_data']);
484 }
485 $offset += $thisfile_asf_headerextensionobject['extension_data_size'];
486 break;
487
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504 $thisfile_asf['codec_list_object'] = array();
505 $thisfile_asf_codeclistobject = &$thisfile_asf['codec_list_object'];
506
507 $thisfile_asf_codeclistobject['offset'] = $NextObjectOffset + $offset;
508 $thisfile_asf_codeclistobject['objectid'] = $NextObjectGUID;
509 $thisfile_asf_codeclistobject['objectid_guid'] = $NextObjectGUIDtext;
510 $thisfile_asf_codeclistobject['objectsize'] = $NextObjectSize;
511 $thisfile_asf_codeclistobject['reserved'] = substr($ASFHeaderData,
512 $offset,
513 16);
514 $offset += 16;
515 $thisfile_asf_codeclistobject[
'reserved_guid'] =
self::BytestringToGUID($thisfile_asf_codeclistobject[
'reserved']);
516 if ($thisfile_asf_codeclistobject['reserved'] != self::GUIDtoBytestring('86D15241-311D-11D0-A3A4-00A0C90348F6')) {
517 $info[
'warning'][] =
'codec_list_object.reserved GUID {' .
self::BytestringToGUID($thisfile_asf_codeclistobject[
'reserved']) .
'} does not match expected "GETID3_ASF_Reserved_1" GUID {86D15241-311D-11D0-A3A4-00A0C90348F6}';
518
519 break;
520 }
522 $offset,
523 4));
524 $offset += 4;
525 for ($CodecEntryCounter = 0;
526 $CodecEntryCounter < $thisfile_asf_codeclistobject['codec_entries_count'];
527 $CodecEntryCounter++) {
528
529 $thisfile_asf_codeclistobject['codec_entries'][$CodecEntryCounter] = array();
530 $thisfile_asf_codeclistobject_codecentries_current = &$thisfile_asf_codeclistobject['codec_entries'][$CodecEntryCounter];
531
533 $offset,
534 2));
535 $offset += 2;
536 $thisfile_asf_codeclistobject_codecentries_current[
'type'] = $this->
ASFCodecListObjectTypeLookup($thisfile_asf_codeclistobject_codecentries_current[
'type_raw']);
537
539 $offset,
540 2)) * 2;
541 $offset += 2;
542 $thisfile_asf_codeclistobject_codecentries_current['name'] = substr($ASFHeaderData,
543 $offset,
544 $CodecNameLength);
545 $offset += $CodecNameLength;
546
548 $offset,
549 2)) * 2;
550 $offset += 2;
551 $thisfile_asf_codeclistobject_codecentries_current['description'] = substr($ASFHeaderData,
552 $offset,
553 $CodecDescriptionLength);
554 $offset += $CodecDescriptionLength;
555
557 $offset,
558 2));
559 $offset += 2;
560 $thisfile_asf_codeclistobject_codecentries_current['information'] = substr($ASFHeaderData,
561 $offset,
562 $CodecInformationLength);
563 $offset += $CodecInformationLength;
564
565 if ($thisfile_asf_codeclistobject_codecentries_current['type_raw'] == 2) {
566 if (strpos($thisfile_asf_codeclistobject_codecentries_current['description'],
567 ',') === false) {
568 $info[
'warning'][] =
'[asf][codec_list_object][codec_entries][' . $CodecEntryCounter .
'][description] expected to contain comma-seperated list of parameters: "' . $thisfile_asf_codeclistobject_codecentries_current[
'description'] .
'"';
569 } else {
570
571 list($AudioCodecBitrate, $AudioCodecFrequency, $AudioCodecChannels) = explode(',',
572 self::TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']));
573 $thisfile_audio[
'codec'] =
self::TrimConvert($thisfile_asf_codeclistobject_codecentries_current[
'name']);
574
575 if (!isset($thisfile_audio['bitrate']) && strstr($AudioCodecBitrate,
576 'kbps')) {
577 $thisfile_audio['bitrate'] = (int) (trim(str_replace('kbps',
578 '',
579 $AudioCodecBitrate)) * 1000);
580 }
581
582 if (empty($thisfile_video[
'bitrate']) && !empty($thisfile_audio[
'bitrate']) && !empty(
$info[
'bitrate'])) {
583
584 $thisfile_video[
'bitrate'] =
$info[
'bitrate'] - $thisfile_audio[
'bitrate'];
585 }
586
587 $AudioCodecFrequency = (int) trim(str_replace('kHz',
588 '',
589 $AudioCodecFrequency));
590 switch ($AudioCodecFrequency) {
591 case 8:
592 case 8000:
593 $thisfile_audio['sample_rate'] = 8000;
594 break;
595
596 case 11:
597 case 11025:
598 $thisfile_audio['sample_rate'] = 11025;
599 break;
600
601 case 12:
602 case 12000:
603 $thisfile_audio['sample_rate'] = 12000;
604 break;
605
606 case 16:
607 case 16000:
608 $thisfile_audio['sample_rate'] = 16000;
609 break;
610
611 case 22:
612 case 22050:
613 $thisfile_audio['sample_rate'] = 22050;
614 break;
615
616 case 24:
617 case 24000:
618 $thisfile_audio['sample_rate'] = 24000;
619 break;
620
621 case 32:
622 case 32000:
623 $thisfile_audio['sample_rate'] = 32000;
624 break;
625
626 case 44:
627 case 441000:
628 $thisfile_audio['sample_rate'] = 44100;
629 break;
630
631 case 48:
632 case 48000:
633 $thisfile_audio['sample_rate'] = 48000;
634 break;
635
636 default:
637 $info[
'warning'][] =
'unknown frequency: "' . $AudioCodecFrequency .
'" (' .
self::TrimConvert($thisfile_asf_codeclistobject_codecentries_current[
'description']) .
')';
638 break;
639 }
640
641 if (!isset($thisfile_audio['channels'])) {
642 if (strstr($AudioCodecChannels, 'stereo')) {
643 $thisfile_audio['channels'] = 2;
644 } elseif (strstr($AudioCodecChannels, 'mono')) {
645 $thisfile_audio['channels'] = 1;
646 }
647 }
648 }
649 }
650 }
651 break;
652
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670 $thisfile_asf['script_command_object'] = array();
671 $thisfile_asf_scriptcommandobject = &$thisfile_asf['script_command_object'];
672
673 $thisfile_asf_scriptcommandobject['offset'] = $NextObjectOffset + $offset;
674 $thisfile_asf_scriptcommandobject['objectid'] = $NextObjectGUID;
675 $thisfile_asf_scriptcommandobject['objectid_guid'] = $NextObjectGUIDtext;
676 $thisfile_asf_scriptcommandobject['objectsize'] = $NextObjectSize;
677 $thisfile_asf_scriptcommandobject['reserved'] = substr($ASFHeaderData,
678 $offset,
679 16);
680 $offset += 16;
681 $thisfile_asf_scriptcommandobject[
'reserved_guid'] =
self::BytestringToGUID($thisfile_asf_scriptcommandobject[
'reserved']);
682 if ($thisfile_asf_scriptcommandobject['reserved'] != self::GUIDtoBytestring('4B1ACBE3-100B-11D0-A39B-00A0C90348F6')) {
683 $info[
'warning'][] =
'script_command_object.reserved GUID {' .
self::BytestringToGUID($thisfile_asf_scriptcommandobject[
'reserved']) .
'} does not match expected "GETID3_ASF_Reserved_1" GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}';
684
685 break;
686 }
688 $offset,
689 2));
690 $offset += 2;
692 $offset,
693 2));
694 $offset += 2;
695 for ($CommandTypesCounter = 0;
696 $CommandTypesCounter < $thisfile_asf_scriptcommandobject['command_types_count'];
697 $CommandTypesCounter++) {
699 $offset,
700 2)) * 2;
701 $offset += 2;
702 $thisfile_asf_scriptcommandobject['command_types'][$CommandTypesCounter]['name'] = substr($ASFHeaderData,
703 $offset,
704 $CommandTypeNameLength);
705 $offset += $CommandTypeNameLength;
706 }
707 for ($CommandsCounter = 0;
708 $CommandsCounter < $thisfile_asf_scriptcommandobject['commands_count'];
709 $CommandsCounter++) {
710 $thisfile_asf_scriptcommandobject[
'commands'][$CommandsCounter][
'presentation_time'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
711 $offset,
712 4));
713 $offset += 4;
714 $thisfile_asf_scriptcommandobject[
'commands'][$CommandsCounter][
'type_index'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
715 $offset,
716 2));
717 $offset += 2;
718
720 $offset,
721 2)) * 2;
722 $offset += 2;
723 $thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['name'] = substr($ASFHeaderData,
724 $offset,
725 $CommandTypeNameLength);
726 $offset += $CommandTypeNameLength;
727 }
728 break;
729
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750 $thisfile_asf['marker_object'] = array();
751 $thisfile_asf_markerobject = &$thisfile_asf['marker_object'];
752
753 $thisfile_asf_markerobject['offset'] = $NextObjectOffset + $offset;
754 $thisfile_asf_markerobject['objectid'] = $NextObjectGUID;
755 $thisfile_asf_markerobject['objectid_guid'] = $NextObjectGUIDtext;
756 $thisfile_asf_markerobject['objectsize'] = $NextObjectSize;
757 $thisfile_asf_markerobject['reserved'] = substr($ASFHeaderData,
758 $offset, 16);
759 $offset += 16;
760 $thisfile_asf_markerobject[
'reserved_guid'] =
self::BytestringToGUID($thisfile_asf_markerobject[
'reserved']);
761 if ($thisfile_asf_markerobject['reserved'] != self::GUIDtoBytestring('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) {
762 $info[
'warning'][] =
'marker_object.reserved GUID {' .
self::BytestringToGUID($thisfile_asf_markerobject[
'reserved_1']) .
'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}';
763 break;
764 }
766 $offset,
767 4));
768 $offset += 4;
770 $offset,
771 2));
772 $offset += 2;
773 if ($thisfile_asf_markerobject['reserved_2'] != 0) {
774 $info[
'warning'][] =
'marker_object.reserved_2 (' .
Helper::PrintHexBytes($thisfile_asf_markerobject[
'reserved_2']) .
') does not match expected value of "0"';
775 break;
776 }
778 $offset,
779 2));
780 $offset += 2;
781 $thisfile_asf_markerobject['name'] = substr($ASFHeaderData,
782 $offset,
783 $thisfile_asf_markerobject['name_length']);
784 $offset += $thisfile_asf_markerobject['name_length'];
785 for ($MarkersCounter = 0;
786 $MarkersCounter < $thisfile_asf_markerobject['markers_count'];
787 $MarkersCounter++) {
789 $offset,
790 8));
791 $offset += 8;
792 $thisfile_asf_markerobject[
'markers'][$MarkersCounter][
'presentation_time'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
793 $offset,
794 8));
795 $offset += 8;
796 $thisfile_asf_markerobject[
'markers'][$MarkersCounter][
'entry_length'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
797 $offset,
798 2));
799 $offset += 2;
800 $thisfile_asf_markerobject[
'markers'][$MarkersCounter][
'send_time'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
801 $offset,
802 4));
803 $offset += 4;
805 $offset,
806 4));
807 $offset += 4;
808 $thisfile_asf_markerobject[
'markers'][$MarkersCounter][
'marker_description_length'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
809 $offset,
810 4));
811 $offset += 4;
812 $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description'] = substr($ASFHeaderData,
813 $offset,
814 $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length']);
815 $offset += $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length'];
816 $PaddingLength = $thisfile_asf_markerobject['markers'][$MarkersCounter]['entry_length'] - 4 - 4 - 4 - $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length'];
817 if ($PaddingLength > 0) {
818 $thisfile_asf_markerobject['markers'][$MarkersCounter]['padding'] = substr($ASFHeaderData,
819 $offset,
820 $PaddingLength);
821 $offset += $PaddingLength;
822 }
823 }
824 break;
825
827
828
829
830
831
832
833
834
835 $thisfile_asf['bitrate_mutual_exclusion_object'] = array();
836 $thisfile_asf_bitratemutualexclusionobject = &$thisfile_asf['bitrate_mutual_exclusion_object'];
837
838 $thisfile_asf_bitratemutualexclusionobject['offset'] = $NextObjectOffset + $offset;
839 $thisfile_asf_bitratemutualexclusionobject['objectid'] = $NextObjectGUID;
840 $thisfile_asf_bitratemutualexclusionobject['objectid_guid'] = $NextObjectGUIDtext;
841 $thisfile_asf_bitratemutualexclusionobject['objectsize'] = $NextObjectSize;
842 $thisfile_asf_bitratemutualexclusionobject['reserved'] = substr($ASFHeaderData,
843 $offset,
844 16);
845 $thisfile_asf_bitratemutualexclusionobject[
'reserved_guid'] =
self::BytestringToGUID($thisfile_asf_bitratemutualexclusionobject[
'reserved']);
846 $offset += 16;
847 if (($thisfile_asf_bitratemutualexclusionobject['reserved'] != self::$GETID3_ASF_Mutex_Bitrate) && ($thisfile_asf_bitratemutualexclusionobject['reserved'] != self::$GETID3_ASF_Mutex_Unknown)) {
848 $info[
'warning'][] =
'bitrate_mutual_exclusion_object.reserved GUID {' .
self::BytestringToGUID($thisfile_asf_bitratemutualexclusionobject[
'reserved']) .
'} does not match expected "GETID3_ASF_Mutex_Bitrate" GUID {' .
self::BytestringToGUID(self::$GETID3_ASF_Mutex_Bitrate) .
'} or "GETID3_ASF_Mutex_Unknown" GUID {' .
self::BytestringToGUID(self::$GETID3_ASF_Mutex_Unknown) .
'}';
849
850 break;
851 }
852 $thisfile_asf_bitratemutualexclusionobject[
'stream_numbers_count'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
853 $offset,
854 2));
855 $offset += 2;
856 for ($StreamNumberCounter = 0;
857 $StreamNumberCounter < $thisfile_asf_bitratemutualexclusionobject['stream_numbers_count'];
858 $StreamNumberCounter++) {
859 $thisfile_asf_bitratemutualexclusionobject[
'stream_numbers'][$StreamNumberCounter] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
860 $offset,
861 2));
862 $offset += 2;
863 }
864 break;
865
867
868
869
870
871
872
873
874
875 $thisfile_asf['error_correction_object'] = array();
876 $thisfile_asf_errorcorrectionobject = &$thisfile_asf['error_correction_object'];
877
878 $thisfile_asf_errorcorrectionobject['offset'] = $NextObjectOffset + $offset;
879 $thisfile_asf_errorcorrectionobject['objectid'] = $NextObjectGUID;
880 $thisfile_asf_errorcorrectionobject['objectid_guid'] = $NextObjectGUIDtext;
881 $thisfile_asf_errorcorrectionobject['objectsize'] = $NextObjectSize;
882 $thisfile_asf_errorcorrectionobject['error_correction_type'] = substr($ASFHeaderData,
883 $offset,
884 16);
885 $offset += 16;
886 $thisfile_asf_errorcorrectionobject[
'error_correction_guid'] =
self::BytestringToGUID($thisfile_asf_errorcorrectionobject[
'error_correction_type']);
887 $thisfile_asf_errorcorrectionobject[
'error_correction_data_length'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
888 $offset,
889 4));
890 $offset += 4;
891 switch ($thisfile_asf_errorcorrectionobject['error_correction_type']) {
893
894 $offset += $thisfile_asf_errorcorrectionobject['error_correction_data_length'];
895 break;
896
898
899
900
901
902
903
904
906 $offset,
907 1));
908 $offset += 1;
910 $offset,
911 2));
912 $offset += 2;
914 $offset,
915 2));
916 $offset += 2;
918 $offset,
919 2));
920 $offset += 2;
921 $thisfile_asf_errorcorrectionobject['silence_data'] = substr($ASFHeaderData,
922 $offset,
923 $thisfile_asf_errorcorrectionobject['silence_data_length']);
924 $offset += $thisfile_asf_errorcorrectionobject['silence_data_length'];
925 break;
926
927 default:
928 $info[
'warning'][] =
'error_correction_object.error_correction_type GUID {' .
self::BytestringToGUID($thisfile_asf_errorcorrectionobject[
'reserved']) .
'} does not match expected "GETID3_ASF_No_Error_Correction" GUID {' .
self::BytestringToGUID(self::$GETID3_ASF_No_Error_Correction) .
'} or "GETID3_ASF_Audio_Spread" GUID {' .
self::BytestringToGUID(self::$GETID3_ASF_Audio_Spread) .
'}';
929
930 break;
931 }
932
933 break;
934
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951 $thisfile_asf['content_description_object'] = array();
952 $thisfile_asf_contentdescriptionobject = &$thisfile_asf['content_description_object'];
953
954 $thisfile_asf_contentdescriptionobject['offset'] = $NextObjectOffset + $offset;
955 $thisfile_asf_contentdescriptionobject['objectid'] = $NextObjectGUID;
956 $thisfile_asf_contentdescriptionobject['objectid_guid'] = $NextObjectGUIDtext;
957 $thisfile_asf_contentdescriptionobject['objectsize'] = $NextObjectSize;
959 $offset,
960 2));
961 $offset += 2;
963 $offset,
964 2));
965 $offset += 2;
967 $offset,
968 2));
969 $offset += 2;
971 $offset,
972 2));
973 $offset += 2;
975 $offset,
976 2));
977 $offset += 2;
978 $thisfile_asf_contentdescriptionobject['title'] = substr($ASFHeaderData,
979 $offset,
980 $thisfile_asf_contentdescriptionobject['title_length']);
981 $offset += $thisfile_asf_contentdescriptionobject['title_length'];
982 $thisfile_asf_contentdescriptionobject['author'] = substr($ASFHeaderData,
983 $offset,
984 $thisfile_asf_contentdescriptionobject['author_length']);
985 $offset += $thisfile_asf_contentdescriptionobject['author_length'];
986 $thisfile_asf_contentdescriptionobject['copyright'] = substr($ASFHeaderData,
987 $offset,
988 $thisfile_asf_contentdescriptionobject['copyright_length']);
989 $offset += $thisfile_asf_contentdescriptionobject['copyright_length'];
990 $thisfile_asf_contentdescriptionobject['description'] = substr($ASFHeaderData,
991 $offset,
992 $thisfile_asf_contentdescriptionobject['description_length']);
993 $offset += $thisfile_asf_contentdescriptionobject['description_length'];
994 $thisfile_asf_contentdescriptionobject['rating'] = substr($ASFHeaderData,
995 $offset,
996 $thisfile_asf_contentdescriptionobject['rating_length']);
997 $offset += $thisfile_asf_contentdescriptionobject['rating_length'];
998
999 $ASFcommentKeysToCopy = array('title' => 'title', 'author' => 'artist', 'copyright' => 'copyright', 'description' => 'comment', 'rating' => 'rating');
1000 foreach ($ASFcommentKeysToCopy as $keytocopyfrom => $keytocopyto) {
1001 if (!empty($thisfile_asf_contentdescriptionobject[$keytocopyfrom])) {
1002 $thisfile_asf_comments[$keytocopyto][] =
self::TrimTerm($thisfile_asf_contentdescriptionobject[$keytocopyfrom]);
1003 }
1004 }
1005 break;
1006
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026 $thisfile_asf['extended_content_description_object'] = array();
1027 $thisfile_asf_extendedcontentdescriptionobject = &$thisfile_asf['extended_content_description_object'];
1028
1029 $thisfile_asf_extendedcontentdescriptionobject['offset'] = $NextObjectOffset + $offset;
1030 $thisfile_asf_extendedcontentdescriptionobject['objectid'] = $NextObjectGUID;
1031 $thisfile_asf_extendedcontentdescriptionobject['objectid_guid'] = $NextObjectGUIDtext;
1032 $thisfile_asf_extendedcontentdescriptionobject['objectsize'] = $NextObjectSize;
1033 $thisfile_asf_extendedcontentdescriptionobject[
'content_descriptors_count'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
1034 $offset,
1035 2));
1036 $offset += 2;
1037 for ($ExtendedContentDescriptorsCounter = 0;
1038 $ExtendedContentDescriptorsCounter < $thisfile_asf_extendedcontentdescriptionobject['content_descriptors_count'];
1039 $ExtendedContentDescriptorsCounter++) {
1040
1041 $thisfile_asf_extendedcontentdescriptionobject['content_descriptors'][$ExtendedContentDescriptorsCounter] = array();
1042 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current = &$thisfile_asf_extendedcontentdescriptionobject['content_descriptors'][$ExtendedContentDescriptorsCounter];
1043
1044 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['base_offset'] = $offset + 30;
1045 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'name_length'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
1046 $offset,
1047 2));
1048 $offset += 2;
1049 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name'] = substr($ASFHeaderData,
1050 $offset,
1051 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name_length']);
1052 $offset += $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name_length'];
1053 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value_type'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
1054 $offset,
1055 2));
1056 $offset += 2;
1057 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value_length'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
1058 $offset,
1059 2));
1060 $offset += 2;
1061 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = substr($ASFHeaderData,
1062 $offset,
1063 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length']);
1064 $offset += $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length'];
1065 switch ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type']) {
1066 case 0x0000:
1067 break;
1068
1069 case 0x0001:
1070
1071 break;
1072
1073 case 0x0002:
1074 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value'] = (bool)
Helper::LittleEndian2Int($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']);
1075 break;
1076
1077 case 0x0003:
1078 case 0x0004:
1079 case 0x0005:
1080 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value'] =
Helper::LittleEndian2Int($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']);
1081 break;
1082
1083 default:
1084 $info[
'warning'][] =
'extended_content_description.content_descriptors.' . $ExtendedContentDescriptorsCounter .
'.value_type is invalid (' . $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value_type'] .
')';
1085
1086 break;
1087 }
1088 switch (self::TrimConvert(strtolower($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name']))) {
1089
1090 case 'wm/albumartist':
1091 case 'artist':
1092
1093 $thisfile_asf_comments['albumartist'] = array(self::TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
1094 break;
1095
1096 case 'wm/albumtitle':
1097 case 'album':
1098 $thisfile_asf_comments['album'] = array(self::TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
1099 break;
1100
1101 case 'wm/genre':
1102 case 'genre':
1103 $thisfile_asf_comments['genre'] = array(self::TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
1104 break;
1105
1106 case 'wm/partofset':
1107 $thisfile_asf_comments['partofset'] = array(self::TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
1108 break;
1109
1110 case 'wm/tracknumber':
1111 case 'tracknumber':
1112
1113 $thisfile_asf_comments['track'] = array(self::TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
1114 foreach ($thisfile_asf_comments['track'] as $key => $value) {
1115 if (preg_match('/^[0-9\x00]+$/', $value)) {
1116 $thisfile_asf_comments['track'][$key] = intval(str_replace("\x00",
1117 '',
1118 $value));
1119 }
1120 }
1121 break;
1122
1123 case 'wm/track':
1124 if (empty($thisfile_asf_comments['track'])) {
1125 $thisfile_asf_comments['track'] = array(1 + self::TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
1126 }
1127 break;
1128
1129 case 'wm/year':
1130 case 'year':
1131 case 'date':
1132 $thisfile_asf_comments['year'] = array(self::TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
1133 break;
1134
1135 case 'wm/lyrics':
1136 case 'lyrics':
1137 $thisfile_asf_comments['lyrics'] = array(self::TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
1138 break;
1139
1140 case 'isvbr':
1141 if ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']) {
1142 $thisfile_audio['bitrate_mode'] = 'vbr';
1143 $thisfile_video['bitrate_mode'] = 'vbr';
1144 }
1145 break;
1146
1147 case 'id3':
1148
1149 if (class_exists('getid3_id3v2')) {
1151 'getID3');
1152 $tempfilehandle = fopen($tempfile, 'wb');
1153 $tempThisfileInfo = array(
'encoding' =>
$info[
'encoding']);
1154 fwrite($tempfilehandle,
1155 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']);
1156 fclose($tempfilehandle);
1157
1158 $getid3_temp = new GetId3Core();
1159 $getid3_temp->openfile($tempfile);
1160 $getid3_id3v2 = new Id3v2($getid3_temp);
1161 $getid3_id3v2->analyze();
1162 $info[
'id3v2'] = $getid3_temp->info[
'id3v2'];
1163 unset($getid3_temp, $getid3_id3v2);
1164
1165 unlink($tempfile);
1166 }
1167 break;
1168
1169 case 'wm/encodingtime':
1170 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'encoding_time_unix'] =
self::FILETIMEtoUNIXtime($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']);
1171 $thisfile_asf_comments['encoding_time_unix'] = array($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['encoding_time_unix']);
1172 break;
1173
1174 case 'wm/picture':
1175 $WMpicture = $this->
ASF_WMpicture($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[
'value']);
1176 foreach ($WMpicture as $key => $value) {
1177 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[$key] = $value;
1178 }
1179 unset($WMpicture);
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218 break;
1219
1220 default:
1221 switch ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type']) {
1222 case 0:
1223 if (substr(self::TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name']),
1224 0, 3) == 'WM/') {
1225 $thisfile_asf_comments[str_replace('wm/',
1226 '',
1227 strtolower(self::TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name'])))] = array(self::TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
1228 }
1229 break;
1230
1231 case 1:
1232 break;
1233 }
1234 break;
1235 }
1236 }
1237 break;
1238
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251 $thisfile_asf['stream_bitrate_properties_object'] = array();
1252 $thisfile_asf_streambitratepropertiesobject = &$thisfile_asf['stream_bitrate_properties_object'];
1253
1254 $thisfile_asf_streambitratepropertiesobject['offset'] = $NextObjectOffset + $offset;
1255 $thisfile_asf_streambitratepropertiesobject['objectid'] = $NextObjectGUID;
1256 $thisfile_asf_streambitratepropertiesobject['objectid_guid'] = $NextObjectGUIDtext;
1257 $thisfile_asf_streambitratepropertiesobject['objectsize'] = $NextObjectSize;
1258 $thisfile_asf_streambitratepropertiesobject[
'bitrate_records_count'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
1259 $offset,
1260 2));
1261 $offset += 2;
1262 for ($BitrateRecordsCounter = 0;
1263 $BitrateRecordsCounter < $thisfile_asf_streambitratepropertiesobject['bitrate_records_count'];
1264 $BitrateRecordsCounter++) {
1265 $thisfile_asf_streambitratepropertiesobject[
'bitrate_records'][$BitrateRecordsCounter][
'flags_raw'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
1266 $offset,
1267 2));
1268 $offset += 2;
1269 $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['flags']['stream_number'] = $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['flags_raw'] & 0x007F;
1270 $thisfile_asf_streambitratepropertiesobject[
'bitrate_records'][$BitrateRecordsCounter][
'bitrate'] =
Helper::LittleEndian2Int(substr($ASFHeaderData,
1271 $offset,
1272 4));
1273 $offset += 4;
1274 }
1275 break;
1276
1278
1279
1280
1281
1282
1283
1284 $thisfile_asf['padding_object'] = array();
1285 $thisfile_asf_paddingobject = &$thisfile_asf['padding_object'];
1286
1287 $thisfile_asf_paddingobject['offset'] = $NextObjectOffset + $offset;
1288 $thisfile_asf_paddingobject['objectid'] = $NextObjectGUID;
1289 $thisfile_asf_paddingobject['objectid_guid'] = $NextObjectGUIDtext;
1290 $thisfile_asf_paddingobject['objectsize'] = $NextObjectSize;
1291 $thisfile_asf_paddingobject['padding_length'] = $thisfile_asf_paddingobject['objectsize'] - 16 - 8;
1292 $thisfile_asf_paddingobject['padding'] = substr($ASFHeaderData,
1293 $offset,
1294 $thisfile_asf_paddingobject['padding_length']);
1295 $offset += ($NextObjectSize - 16 - 8);
1296 break;
1297
1300
1301 $offset += ($NextObjectSize - 16 - 8);
1302 break;
1303
1304 default:
1305
1306 if (self::GUIDname($NextObjectGUIDtext)) {
1307 $info[
'warning'][] =
'unhandled GUID "' .
self::GUIDname($NextObjectGUIDtext) .
'" {' . $NextObjectGUIDtext .
'} in ASF header at offset ' . ($offset - 16 - 8);
1308 } else {
1309 $info[
'warning'][] =
'unknown GUID {' . $NextObjectGUIDtext .
'} in ASF header at offset ' . ($offset - 16 - 8);
1310 }
1311 $offset += ($NextObjectSize - 16 - 8);
1312 break;
1313 }
1314 }
1315 if (isset($thisfile_asf_streambitrateproperties['bitrate_records_count'])) {
1316 $ASFbitrateAudio = 0;
1317 $ASFbitrateVideo = 0;
1318 for ($BitrateRecordsCounter = 0;
1319 $BitrateRecordsCounter < $thisfile_asf_streambitrateproperties['bitrate_records_count'];
1320 $BitrateRecordsCounter++) {
1321 if (isset($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter])) {
1322 switch ($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter]['type_raw']) {
1323 case 1:
1324 $ASFbitrateVideo += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
1325 break;
1326
1327 case 2:
1328 $ASFbitrateAudio += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
1329 break;
1330
1331 default:
1332
1333 break;
1334 }
1335 }
1336 }
1337 if ($ASFbitrateAudio > 0) {
1338 $thisfile_audio['bitrate'] = $ASFbitrateAudio;
1339 }
1340 if ($ASFbitrateVideo > 0) {
1341 $thisfile_video['bitrate'] = $ASFbitrateVideo;
1342 }
1343 }
1344 if (isset($thisfile_asf['stream_properties_object']) && is_array($thisfile_asf['stream_properties_object'])) {
1345
1346 $thisfile_audio['bitrate'] = 0;
1347 $thisfile_video['bitrate'] = 0;
1348
1349 foreach ($thisfile_asf['stream_properties_object'] as $streamnumber => $streamdata) {
1350
1351 switch ($streamdata['stream_type']) {
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363 $thisfile_asf['audio_media'][$streamnumber] = array();
1364 $thisfile_asf_audiomedia_currentstream = &$thisfile_asf['audio_media'][$streamnumber];
1365
1366 $audiomediaoffset = 0;
1367
1369 $audiomediaoffset,
1370 16));
1371 $audiomediaoffset += 16;
1372
1373 $thisfile_audio['lossless'] = false;
1374 switch ($thisfile_asf_audiomedia_currentstream['raw']['wFormatTag']) {
1375 case 0x0001:
1376 case 0x0163:
1377 $thisfile_audio['lossless'] = true;
1378 break;
1379 }
1380
1381 if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) {
1382 foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) {
1383 if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) {
1384 $thisfile_asf_audiomedia_currentstream['bitrate'] = $dataarray['bitrate'];
1385 $thisfile_audio['bitrate'] += $dataarray['bitrate'];
1386 break;
1387 }
1388 }
1389 } else {
1390 if (!empty($thisfile_asf_audiomedia_currentstream['bytes_sec'])) {
1391 $thisfile_audio['bitrate'] += $thisfile_asf_audiomedia_currentstream['bytes_sec'] * 8;
1392 } elseif (!empty($thisfile_asf_audiomedia_currentstream['bitrate'])) {
1393 $thisfile_audio['bitrate'] += $thisfile_asf_audiomedia_currentstream['bitrate'];
1394 }
1395 }
1396 $thisfile_audio['streams'][$streamnumber] = $thisfile_asf_audiomedia_currentstream;
1397 $thisfile_audio['streams'][$streamnumber]['wformattag'] = $thisfile_asf_audiomedia_currentstream['raw']['wFormatTag'];
1398 $thisfile_audio['streams'][$streamnumber]['lossless'] = $thisfile_audio['lossless'];
1399 $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate'];
1400 $thisfile_audio['streams'][$streamnumber]['dataformat'] = 'wma';
1401 unset($thisfile_audio['streams'][$streamnumber]['raw']);
1402
1403 $thisfile_asf_audiomedia_currentstream[
'codec_data_size'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1404 $audiomediaoffset,
1405 2));
1406 $audiomediaoffset += 2;
1407 $thisfile_asf_audiomedia_currentstream['codec_data'] = substr($streamdata['type_specific_data'],
1408 $audiomediaoffset,
1409 $thisfile_asf_audiomedia_currentstream['codec_data_size']);
1410 $audiomediaoffset += $thisfile_asf_audiomedia_currentstream['codec_data_size'];
1411
1412 break;
1413
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434 $thisfile_asf['video_media'][$streamnumber] = array();
1435 $thisfile_asf_videomedia_currentstream = &$thisfile_asf['video_media'][$streamnumber];
1436
1437 $videomediaoffset = 0;
1438 $thisfile_asf_videomedia_currentstream[
'image_width'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1439 $videomediaoffset,
1440 4));
1441 $videomediaoffset += 4;
1442 $thisfile_asf_videomedia_currentstream[
'image_height'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1443 $videomediaoffset,
1444 4));
1445 $videomediaoffset += 4;
1446 $thisfile_asf_videomedia_currentstream[
'flags'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1447 $videomediaoffset,
1448 1));
1449 $videomediaoffset += 1;
1450 $thisfile_asf_videomedia_currentstream[
'format_data_size'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1451 $videomediaoffset,
1452 2));
1453 $videomediaoffset += 2;
1454 $thisfile_asf_videomedia_currentstream[
'format_data'][
'format_data_size'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1455 $videomediaoffset,
1456 4));
1457 $videomediaoffset += 4;
1458 $thisfile_asf_videomedia_currentstream[
'format_data'][
'image_width'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1459 $videomediaoffset,
1460 4));
1461 $videomediaoffset += 4;
1462 $thisfile_asf_videomedia_currentstream[
'format_data'][
'image_height'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1463 $videomediaoffset,
1464 4));
1465 $videomediaoffset += 4;
1466 $thisfile_asf_videomedia_currentstream[
'format_data'][
'reserved'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1467 $videomediaoffset,
1468 2));
1469 $videomediaoffset += 2;
1470 $thisfile_asf_videomedia_currentstream[
'format_data'][
'bits_per_pixel'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1471 $videomediaoffset,
1472 2));
1473 $videomediaoffset += 2;
1474 $thisfile_asf_videomedia_currentstream['format_data']['codec_fourcc'] = substr($streamdata['type_specific_data'],
1475 $videomediaoffset,
1476 4);
1477 $videomediaoffset += 4;
1478 $thisfile_asf_videomedia_currentstream[
'format_data'][
'image_size'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1479 $videomediaoffset,
1480 4));
1481 $videomediaoffset += 4;
1482 $thisfile_asf_videomedia_currentstream[
'format_data'][
'horizontal_pels'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1483 $videomediaoffset,
1484 4));
1485 $videomediaoffset += 4;
1486 $thisfile_asf_videomedia_currentstream[
'format_data'][
'vertical_pels'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1487 $videomediaoffset,
1488 4));
1489 $videomediaoffset += 4;
1490 $thisfile_asf_videomedia_currentstream[
'format_data'][
'colors_used'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1491 $videomediaoffset,
1492 4));
1493 $videomediaoffset += 4;
1494 $thisfile_asf_videomedia_currentstream[
'format_data'][
'colors_important'] =
Helper::LittleEndian2Int(substr($streamdata[
'type_specific_data'],
1495 $videomediaoffset,
1496 4));
1497 $videomediaoffset += 4;
1498 $thisfile_asf_videomedia_currentstream['format_data']['codec_data'] = substr($streamdata['type_specific_data'],
1499 $videomediaoffset);
1500
1501 if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) {
1502 foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) {
1503 if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) {
1504 $thisfile_asf_videomedia_currentstream['bitrate'] = $dataarray['bitrate'];
1505 $thisfile_video['streams'][$streamnumber]['bitrate'] = $dataarray['bitrate'];
1506 $thisfile_video['bitrate'] += $dataarray['bitrate'];
1507 break;
1508 }
1509 }
1510 }
1511
1512 $thisfile_asf_videomedia_currentstream[
'format_data'][
'codec'] =
Riff::RIFFfourccLookup($thisfile_asf_videomedia_currentstream[
'format_data'][
'codec_fourcc']);
1513
1514 $thisfile_video['streams'][$streamnumber]['fourcc'] = $thisfile_asf_videomedia_currentstream['format_data']['codec_fourcc'];
1515 $thisfile_video['streams'][$streamnumber]['codec'] = $thisfile_asf_videomedia_currentstream['format_data']['codec'];
1516 $thisfile_video['streams'][$streamnumber]['resolution_x'] = $thisfile_asf_videomedia_currentstream['image_width'];
1517 $thisfile_video['streams'][$streamnumber]['resolution_y'] = $thisfile_asf_videomedia_currentstream['image_height'];
1518 $thisfile_video['streams'][$streamnumber]['bits_per_sample'] = $thisfile_asf_videomedia_currentstream['format_data']['bits_per_pixel'];
1519 break;
1520
1521 default:
1522 break;
1523 }
1524 }
1525 }
while (
ftell($this->getid3->fp) <
$info[
'avdataend']) {
1526 $NextObjectDataHeader =
fread($this->getid3->fp, 24);
1527 $offset = 0;
1528 $NextObjectGUID = substr($NextObjectDataHeader, 0, 16);
1529 $offset += 16;
1532 $offset,
1533 8));
1534 $offset += 8;
1535
1536 switch ($NextObjectGUID) {
1538
1539
1540
1541
1542
1543
1544
1545
1546 $thisfile_asf['data_object'] = array();
1547 $thisfile_asf_dataobject = &$thisfile_asf['data_object'];
1548
1549 $DataObjectData = $NextObjectDataHeader .
fread($this->getid3->fp,
1550 50 - 24);
1551 $offset = 24;
1552
1553 $thisfile_asf_dataobject['objectid'] = $NextObjectGUID;
1554 $thisfile_asf_dataobject['objectid_guid'] = $NextObjectGUIDtext;
1555 $thisfile_asf_dataobject['objectsize'] = $NextObjectSize;
1556
1557 $thisfile_asf_dataobject['fileid'] = substr($DataObjectData,
1558 $offset, 16);
1559 $offset += 16;
1562 $offset,
1563 8));
1564 $offset += 8;
1566 $offset,
1567 2));
1568 $offset += 2;
1569 if ($thisfile_asf_dataobject['reserved'] != 0x0101) {
1570 $info[
'warning'][] =
'data_object.reserved (' .
Helper::PrintHexBytes($thisfile_asf_dataobject[
'reserved']) .
') does not match expected value of "0x0101"';
1571
1572 break;
1573 }
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583 $info[
'avdataoffset'] =
ftell($this->getid3->fp);
1584 fseek($this->getid3->fp,
1585 ($thisfile_asf_dataobject['objectsize'] - 50),
1586 SEEK_CUR);
1587 $info[
'avdataend'] =
ftell($this->getid3->fp);
1588 break;
1589
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603 $thisfile_asf['simple_index_object'] = array();
1604 $thisfile_asf_simpleindexobject = &$thisfile_asf['simple_index_object'];
1605
1606 $SimpleIndexObjectData = $NextObjectDataHeader .
fread($this->getid3->fp,
1607 56 - 24);
1608 $offset = 24;
1609
1610 $thisfile_asf_simpleindexobject['objectid'] = $NextObjectGUID;
1611 $thisfile_asf_simpleindexobject['objectid_guid'] = $NextObjectGUIDtext;
1612 $thisfile_asf_simpleindexobject['objectsize'] = $NextObjectSize;
1613
1614 $thisfile_asf_simpleindexobject['fileid'] = substr($SimpleIndexObjectData,
1615 $offset,
1616 16);
1617 $offset += 16;
1618 $thisfile_asf_simpleindexobject[
'fileid_guid'] =
self::BytestringToGUID($thisfile_asf_simpleindexobject[
'fileid']);
1619 $thisfile_asf_simpleindexobject[
'index_entry_time_interval'] =
Helper::LittleEndian2Int(substr($SimpleIndexObjectData,
1620 $offset,
1621 8));
1622 $offset += 8;
1624 $offset,
1625 4));
1626 $offset += 4;
1628 $offset,
1629 4));
1630 $offset += 4;
1631
1632 $IndexEntriesData = $SimpleIndexObjectData .
fread($this->getid3->fp,
1633 6 * $thisfile_asf_simpleindexobject['index_entries_count']);
1634 for ($IndexEntriesCounter = 0;
1635 $IndexEntriesCounter < $thisfile_asf_simpleindexobject['index_entries_count'];
1636 $IndexEntriesCounter++) {
1637 $thisfile_asf_simpleindexobject[
'index_entries'][$IndexEntriesCounter][
'packet_number'] =
Helper::LittleEndian2Int(substr($IndexEntriesData,
1638 $offset,
1639 4));
1640 $offset += 4;
1641 $thisfile_asf_simpleindexobject[
'index_entries'][$IndexEntriesCounter][
'packet_count'] =
Helper::LittleEndian2Int(substr($IndexEntriesData,
1642 $offset,
1643 4));
1644 $offset += 2;
1645 }
1646
1647 break;
1648
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671 $thisfile_asf['asf_index_object'] = array();
1672 $thisfile_asf_asfindexobject = &$thisfile_asf['asf_index_object'];
1673
1674 $ASFIndexObjectData = $NextObjectDataHeader .
fread($this->getid3->fp,
1675 34 - 24);
1676 $offset = 24;
1677
1678 $thisfile_asf_asfindexobject['objectid'] = $NextObjectGUID;
1679 $thisfile_asf_asfindexobject['objectid_guid'] = $NextObjectGUIDtext;
1680 $thisfile_asf_asfindexobject['objectsize'] = $NextObjectSize;
1681
1683 $offset,
1684 4));
1685 $offset += 4;
1687 $offset,
1688 2));
1689 $offset += 2;
1691 $offset,
1692 4));
1693 $offset += 4;
1694
1695 $ASFIndexObjectData .=
fread($this->getid3->fp,
1696 4 * $thisfile_asf_asfindexobject['index_specifiers_count']);
1697 for ($IndexSpecifiersCounter = 0;
1698 $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count'];
1699 $IndexSpecifiersCounter++) {
1701 $offset,
1702 2));
1703 $offset += 2;
1704 $thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['stream_number'] = $IndexSpecifierStreamNumber;
1705 $thisfile_asf_asfindexobject[
'index_specifiers'][$IndexSpecifiersCounter][
'index_type'] =
Helper::LittleEndian2Int(substr($ASFIndexObjectData,
1706 $offset,
1707 2));
1708 $offset += 2;
1709 $thisfile_asf_asfindexobject[
'index_specifiers'][$IndexSpecifiersCounter][
'index_type_text'] = $this->
ASFIndexObjectIndexTypeLookup($thisfile_asf_asfindexobject[
'index_specifiers'][$IndexSpecifiersCounter][
'index_type']);
1710 }
1711
1712 $ASFIndexObjectData .=
fread($this->getid3->fp, 4);
1714 $offset,
1715 4));
1716 $offset += 4;
1717
1718 $ASFIndexObjectData .=
fread($this->getid3->fp,
1719 8 * $thisfile_asf_asfindexobject['index_specifiers_count']);
1720 for ($IndexSpecifiersCounter = 0;
1721 $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count'];
1722 $IndexSpecifiersCounter++) {
1723 $thisfile_asf_asfindexobject[
'block_positions'][$IndexSpecifiersCounter] =
Helper::LittleEndian2Int(substr($ASFIndexObjectData,
1724 $offset,
1725 8));
1726 $offset += 8;
1727 }
1728
1729 $ASFIndexObjectData .=
fread($this->getid3->fp,
1730 4 * $thisfile_asf_asfindexobject['index_specifiers_count'] * $thisfile_asf_asfindexobject['index_entry_count']);
1731 for ($IndexEntryCounter = 0;
1732 $IndexEntryCounter < $thisfile_asf_asfindexobject['index_entry_count'];
1733 $IndexEntryCounter++) {
1734 for ($IndexSpecifiersCounter = 0;
1735 $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count'];
1736 $IndexSpecifiersCounter++) {
1737 $thisfile_asf_asfindexobject[
'offsets'][$IndexSpecifiersCounter][$IndexEntryCounter] =
Helper::LittleEndian2Int(substr($ASFIndexObjectData,
1738 $offset,
1739 4));
1740 $offset += 4;
1741 }
1742 }
1743 break;
1744
1745
1746 default:
1747
1748 if (self::GUIDname($NextObjectGUIDtext)) {
1749 $info[
'warning'][] =
'unhandled GUID "' .
self::GUIDname($NextObjectGUIDtext) .
'" {' . $NextObjectGUIDtext .
'} in ASF body at offset ' . ($offset - 16 - 8);
1750 } else {
1751 $info[
'warning'][] =
'unknown GUID {' . $NextObjectGUIDtext .
'} in ASF body at offset ' . (
ftell($this->getid3->fp) - 16 - 8);
1752 }
1753 fseek($this->getid3->fp, ($NextObjectSize - 16 - 8),
1754 SEEK_CUR);
1755 break;
1756 }
1757 }
1758
1759 if (isset($thisfile_asf_codeclistobject['codec_entries']) && is_array($thisfile_asf_codeclistobject['codec_entries'])) {
1760 foreach ($thisfile_asf_codeclistobject['codec_entries'] as $streamnumber => $streamdata) {
1761 switch ($streamdata['information']) {
1762 case 'WMV1':
1763 case 'WMV2':
1764 case 'WMV3':
1765 case 'MSS1':
1766 case 'MSS2':
1767 case 'WMVA':
1768 case 'WVC1':
1769 case 'WMVP':
1770 case 'WVP2':
1771 $thisfile_video['dataformat'] = 'wmv';
1772 $info[
'mime_type'] =
'video/x-ms-wmv';
1773 break;
1774
1775 case 'MP42':
1776 case 'MP43':
1777 case 'MP4S':
1778 case 'mp4s':
1779 $thisfile_video['dataformat'] = 'asf';
1780 $info[
'mime_type'] =
'video/x-ms-asf';
1781 break;
1782
1783 default:
1784 switch ($streamdata['type_raw']) {
1785 case 1:
1786 if (strstr(self::TrimConvert($streamdata['name']),
1787 'Windows Media')) {
1788 $thisfile_video['dataformat'] = 'wmv';
1789 if (
$info[
'mime_type'] ==
'video/x-ms-asf') {
1790 $info[
'mime_type'] =
'video/x-ms-wmv';
1791 }
1792 }
1793 break;
1794
1795 case 2:
1796 if (strstr(self::TrimConvert($streamdata['name']),
1797 'Windows Media')) {
1798 $thisfile_audio['dataformat'] = 'wma';
1799 if (
$info[
'mime_type'] ==
'video/x-ms-asf') {
1800 $info[
'mime_type'] =
'audio/x-ms-wma';
1801 }
1802 }
1803 break;
1804 }
1805 break;
1806 }
1807 }
1808 }
1809
1810 switch (isset($thisfile_audio['codec']) ? $thisfile_audio['codec'] : '') {
1811 case 'MPEG Layer-3':
1812 $thisfile_audio['dataformat'] = 'mp3';
1813 break;
1814
1815 default:
1816 break;
1817 }
1818
1819 if (isset($thisfile_asf_codeclistobject['codec_entries'])) {
1820 foreach ($thisfile_asf_codeclistobject['codec_entries'] as $streamnumber => $streamdata) {
1821 switch ($streamdata['type_raw']) {
1822
1823 case 1:
1824 $thisfile_video[
'encoder'] =
self::TrimConvert($thisfile_asf_codeclistobject[
'codec_entries'][$streamnumber][
'name']);
1825 break;
1826
1827 case 2:
1828 $thisfile_audio[
'encoder'] =
self::TrimConvert($thisfile_asf_codeclistobject[
'codec_entries'][$streamnumber][
'name']);
1829
1830
1831 $thisfile_audio[
'encoder_options'] =
self::TrimConvert($thisfile_asf_codeclistobject[
'codec_entries'][0][
'description']);
1832
1833 $thisfile_audio['codec'] = $thisfile_audio['encoder'];
1834 break;
1835
1836 default:
1837 $info[
'warning'][] =
'Unknown streamtype: [codec_list_object][codec_entries][' . $streamnumber .
'][type_raw] == ' . $streamdata[
'type_raw'];
1838 break;
1839 }
1840 }
1841 }
1842
1843 if (isset(
$info[
'audio'])) {
1844 $thisfile_audio['lossless'] = (isset($thisfile_audio['lossless']) ? $thisfile_audio['lossless'] : false);
1845 $thisfile_audio['dataformat'] = (!empty($thisfile_audio['dataformat']) ? $thisfile_audio['dataformat'] : 'asf');
1846 }
1847 if (!empty($thisfile_video['dataformat'])) {
1848 $thisfile_video['lossless'] = (isset($thisfile_audio['lossless']) ? $thisfile_audio['lossless'] : false);
1849 $thisfile_video['pixel_aspect_ratio'] = (isset($thisfile_audio['pixel_aspect_ratio']) ? $thisfile_audio['pixel_aspect_ratio'] : (float) 1);
1850 $thisfile_video['dataformat'] = (!empty($thisfile_video['dataformat']) ? $thisfile_video['dataformat'] : 'asf');
1851 }
1852 if (!empty($thisfile_video['streams'])) {
1853 $thisfile_video['streams']['resolution_x'] = 0;
1854 $thisfile_video['streams']['resolution_y'] = 0;
1855 foreach ($thisfile_video['streams'] as $key => $valuearray) {
1856 if (($valuearray['resolution_x'] > $thisfile_video['streams']['resolution_x']) || ($valuearray['resolution_y'] > $thisfile_video['streams']['resolution_y'])) {
1857 $thisfile_video['resolution_x'] = $valuearray['resolution_x'];
1858 $thisfile_video['resolution_y'] = $valuearray['resolution_y'];
1859 }
1860 }
1861 }
1862 $info[
'bitrate'] = (isset($thisfile_audio[
'bitrate']) ? $thisfile_audio[
'bitrate'] : 0) + (isset($thisfile_video[
'bitrate']) ? $thisfile_video[
'bitrate'] : 0);
1863
1864 if ((!isset(
$info[
'playtime_seconds']) || (
$info[
'playtime_seconds'] <= 0)) && (
$info[
'bitrate'] > 0)) {
1865 $info[
'playtime_seconds'] = (
$info[
'filesize'] -
$info[
'avdataoffset']) / (
$info[
'bitrate'] / 8);
1866 }
1867
1868 return true;
1869 }
fseek($bytes, $whence=SEEK_SET)
static array_merge_noclobber($array1, $array2)
static LittleEndian2Int($byteword, $signed=false)
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
static $GETID3_ASF_Content_Description_Object
static $GETID3_ASF_Codec_List_Object
static GUIDname($GUIDstring)
static $GETID3_ASF_Content_Encryption_Object
static $GETID3_ASF_Extended_Content_Encryption_Object
static ASFCodecListObjectTypeLookup($CodecListType)
static $GETID3_ASF_Simple_Index_Object
static TrimConvert($string)
static $GETID3_ASF_Video_Media
static $GETID3_ASF_Command_Media
static $GETID3_ASF_Stream_Properties_Object
static FILETIMEtoUNIXtime($FILETIME, $round=true)
static BytestringToGUID($Bytestring)
static $GETID3_ASF_No_Error_Correction
static $GETID3_ASF_Audio_Media
static $GETID3_ASF_Bitrate_Mutual_Exclusion_Object
static $GETID3_ASF_File_Properties_Object
static $GETID3_ASF_Index_Object
static $GETID3_ASF_Audio_Spread
static $GETID3_ASF_Header_Extension_Object
static $GETID3_ASF_Data_Object
static $GETID3_ASF_Stream_Bitrate_Properties_Object
static $GETID3_ASF_Script_Command_Object
static $GETID3_ASF_Padding_Object
static $GETID3_ASF_Error_Correction_Object
static $GETID3_ASF_Extended_Content_Description_Object
ASF_HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections)
static ASFIndexObjectIndexTypeLookup($id)
static $GETID3_ASF_Marker_Object
static RIFFfourccLookup($fourcc)
static RIFFparseWAVEFORMATex($WaveFormatExData)