[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ID3/ -> module.audio-video.asf.php (source)

   1  <?php
   2  /////////////////////////////////////////////////////////////////
   3  /// getID3() by James Heinrich <info@getid3.org>               //
   4  //  available at https://github.com/JamesHeinrich/getID3       //
   5  //            or https://www.getid3.org                        //
   6  //            or http://getid3.sourceforge.net                 //
   7  //  see readme.txt for more details                            //
   8  /////////////////////////////////////////////////////////////////
   9  //                                                             //
  10  // module.audio-video.asf.php                                  //
  11  // module for analyzing ASF, WMA and WMV files                 //
  12  // dependencies: module.audio-video.riff.php                   //
  13  //                                                            ///
  14  /////////////////////////////////////////////////////////////////
  15  
  16  if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
  17      exit;
  18  }
  19  getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
  20  
  21  class getid3_asf extends getid3_handler
  22  {
  23      protected static $ASFIndexParametersObjectIndexSpecifiersIndexTypes = array(
  24          1 => 'Nearest Past Data Packet',
  25          2 => 'Nearest Past Media Object',
  26          3 => 'Nearest Past Cleanpoint'
  27      );
  28  
  29      protected static $ASFMediaObjectIndexParametersObjectIndexSpecifiersIndexTypes = array(
  30          1 => 'Nearest Past Data Packet',
  31          2 => 'Nearest Past Media Object',
  32          3 => 'Nearest Past Cleanpoint',
  33          0xFF => 'Frame Number Offset'
  34      );
  35  
  36      protected static $ASFTimecodeIndexParametersObjectIndexSpecifiersIndexTypes = array(
  37          2 => 'Nearest Past Media Object',
  38          3 => 'Nearest Past Cleanpoint'
  39      );
  40  
  41      /**
  42       * @param getID3 $getid3
  43       */
  44  	public function __construct(getID3 $getid3) {
  45          parent::__construct($getid3);  // extends getid3_handler::__construct()
  46  
  47          // initialize all GUID constants
  48          $GUIDarray = $this->KnownGUIDs();
  49          foreach ($GUIDarray as $GUIDname => $hexstringvalue) {
  50              if (!defined($GUIDname)) {
  51                  define($GUIDname, $this->GUIDtoBytestring($hexstringvalue));
  52              }
  53          }
  54      }
  55  
  56      /**
  57       * @return bool
  58       */
  59  	public function Analyze() {
  60          $info = &$this->getid3->info;
  61  
  62          // Shortcuts
  63          $thisfile_audio = &$info['audio'];
  64          $thisfile_video = &$info['video'];
  65          $info['asf']  = array();
  66          $thisfile_asf = &$info['asf'];
  67          $thisfile_asf['comments'] = array();
  68          $thisfile_asf_comments    = &$thisfile_asf['comments'];
  69          $thisfile_asf['header_object'] = array();
  70          $thisfile_asf_headerobject     = &$thisfile_asf['header_object'];
  71  
  72  
  73          // ASF structure:
  74          // * Header Object [required]
  75          //   * File Properties Object [required]   (global file attributes)
  76          //   * Stream Properties Object [required] (defines media stream & characteristics)
  77          //   * Header Extension Object [required]  (additional functionality)
  78          //   * Content Description Object          (bibliographic information)
  79          //   * Script Command Object               (commands for during playback)
  80          //   * Marker Object                       (named jumped points within the file)
  81          // * Data Object [required]
  82          //   * Data Packets
  83          // * Index Object
  84  
  85          // Header Object: (mandatory, one only)
  86          // Field Name                   Field Type   Size (bits)
  87          // Object ID                    GUID         128             // GUID for header object - GETID3_ASF_Header_Object
  88          // Object Size                  QWORD        64              // size of header object, including 30 bytes of Header Object header
  89          // Number of Header Objects     DWORD        32              // number of objects in header object
  90          // Reserved1                    BYTE         8               // hardcoded: 0x01
  91          // Reserved2                    BYTE         8               // hardcoded: 0x02
  92  
  93          $info['fileformat'] = 'asf';
  94  
  95          $this->fseek($info['avdataoffset']);
  96          $HeaderObjectData = $this->fread(30);
  97  
  98          $thisfile_asf_headerobject['objectid']      = substr($HeaderObjectData, 0, 16);
  99          $thisfile_asf_headerobject['objectid_guid'] = $this->BytestringToGUID($thisfile_asf_headerobject['objectid']);
 100          if ($thisfile_asf_headerobject['objectid'] != GETID3_ASF_Header_Object) {
 101              unset($info['fileformat'], $info['asf']);
 102              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).'}');
 103          }
 104          $thisfile_asf_headerobject['objectsize']    = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 16, 8));
 105          $thisfile_asf_headerobject['headerobjects'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 24, 4));
 106          $thisfile_asf_headerobject['reserved1']     = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 28, 1));
 107          $thisfile_asf_headerobject['reserved2']     = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 29, 1));
 108  
 109          $NextObjectOffset = $this->ftell();
 110          $ASFHeaderData = $this->fread($thisfile_asf_headerobject['objectsize'] - 30);
 111          $offset = 0;
 112          $thisfile_asf_streambitratepropertiesobject = array();
 113          $thisfile_asf_codeclistobject = array();
 114          $StreamPropertiesObjectData = array();
 115  
 116          for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) {
 117              $NextObjectGUID = substr($ASFHeaderData, $offset, 16);
 118              $offset += 16;
 119              $NextObjectGUIDtext = $this->BytestringToGUID($NextObjectGUID);
 120              $NextObjectSize = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
 121              $offset += 8;
 122              switch ($NextObjectGUID) {
 123  
 124                  case GETID3_ASF_File_Properties_Object:
 125                      // File Properties Object: (mandatory, one only)
 126                      // Field Name                   Field Type   Size (bits)
 127                      // Object ID                    GUID         128             // GUID for file properties object - GETID3_ASF_File_Properties_Object
 128                      // Object Size                  QWORD        64              // size of file properties object, including 104 bytes of File Properties Object header
 129                      // File ID                      GUID         128             // unique ID - identical to File ID in Data Object
 130                      // File Size                    QWORD        64              // entire file in bytes. Invalid if Broadcast Flag == 1
 131                      // Creation Date                QWORD        64              // date & time of file creation. Maybe invalid if Broadcast Flag == 1
 132                      // Data Packets Count           QWORD        64              // number of data packets in Data Object. Invalid if Broadcast Flag == 1
 133                      // Play Duration                QWORD        64              // playtime, in 100-nanosecond units. Invalid if Broadcast Flag == 1
 134                      // Send Duration                QWORD        64              // time needed to send file, in 100-nanosecond units. Players can ignore this value. Invalid if Broadcast Flag == 1
 135                      // Preroll                      QWORD        64              // time to buffer data before starting to play file, in 1-millisecond units. If <> 0, PlayDuration and PresentationTime have been offset by this amount
 136                      // Flags                        DWORD        32              //
 137                      // * Broadcast Flag             bits         1  (0x01)       // file is currently being written, some header values are invalid
 138                      // * Seekable Flag              bits         1  (0x02)       // is file seekable
 139                      // * Reserved                   bits         30 (0xFFFFFFFC) // reserved - set to zero
 140                      // Minimum Data Packet Size     DWORD        32              // in bytes. should be same as Maximum Data Packet Size. Invalid if Broadcast Flag == 1
 141                      // Maximum Data Packet Size     DWORD        32              // in bytes. should be same as Minimum Data Packet Size. Invalid if Broadcast Flag == 1
 142                      // Maximum Bitrate              DWORD        32              // maximum instantaneous bitrate in bits per second for entire file, including all data streams and ASF overhead
 143  
 144                      // shortcut
 145                      $thisfile_asf['file_properties_object'] = array();
 146                      $thisfile_asf_filepropertiesobject      = &$thisfile_asf['file_properties_object'];
 147  
 148                      $thisfile_asf_filepropertiesobject['offset']             = $NextObjectOffset + $offset;
 149                      $thisfile_asf_filepropertiesobject['objectid']           = $NextObjectGUID;
 150                      $thisfile_asf_filepropertiesobject['objectid_guid']      = $NextObjectGUIDtext;
 151                      $thisfile_asf_filepropertiesobject['objectsize']         = $NextObjectSize;
 152                      $thisfile_asf_filepropertiesobject['fileid']             = substr($ASFHeaderData, $offset, 16);
 153                      $offset += 16;
 154                      $thisfile_asf_filepropertiesobject['fileid_guid']        = $this->BytestringToGUID($thisfile_asf_filepropertiesobject['fileid']);
 155                      $thisfile_asf_filepropertiesobject['filesize']           = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
 156                      $offset += 8;
 157                      $thisfile_asf_filepropertiesobject['creation_date']      = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
 158                      $thisfile_asf_filepropertiesobject['creation_date_unix'] = $this->FILETIMEtoUNIXtime($thisfile_asf_filepropertiesobject['creation_date']);
 159                      $offset += 8;
 160                      $thisfile_asf_filepropertiesobject['data_packets']       = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
 161                      $offset += 8;
 162                      $thisfile_asf_filepropertiesobject['play_duration']      = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
 163                      $offset += 8;
 164                      $thisfile_asf_filepropertiesobject['send_duration']      = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
 165                      $offset += 8;
 166                      $thisfile_asf_filepropertiesobject['preroll']            = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
 167                      $offset += 8;
 168                      $thisfile_asf_filepropertiesobject['flags_raw']          = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 169                      $offset += 4;
 170                      $thisfile_asf_filepropertiesobject['flags']['broadcast'] = (bool) ($thisfile_asf_filepropertiesobject['flags_raw'] & 0x0001);
 171                      $thisfile_asf_filepropertiesobject['flags']['seekable']  = (bool) ($thisfile_asf_filepropertiesobject['flags_raw'] & 0x0002);
 172  
 173                      $thisfile_asf_filepropertiesobject['min_packet_size']    = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 174                      $offset += 4;
 175                      $thisfile_asf_filepropertiesobject['max_packet_size']    = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 176                      $offset += 4;
 177                      $thisfile_asf_filepropertiesobject['max_bitrate']        = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 178                      $offset += 4;
 179  
 180                      if ($thisfile_asf_filepropertiesobject['flags']['broadcast']) {
 181  
 182                          // broadcast flag is set, some values invalid
 183                          unset($thisfile_asf_filepropertiesobject['filesize']);
 184                          unset($thisfile_asf_filepropertiesobject['data_packets']);
 185                          unset($thisfile_asf_filepropertiesobject['play_duration']);
 186                          unset($thisfile_asf_filepropertiesobject['send_duration']);
 187                          unset($thisfile_asf_filepropertiesobject['min_packet_size']);
 188                          unset($thisfile_asf_filepropertiesobject['max_packet_size']);
 189  
 190                      } else {
 191  
 192                          // broadcast flag NOT set, perform calculations
 193                          $info['playtime_seconds'] = ($thisfile_asf_filepropertiesobject['play_duration'] / 10000000) - ($thisfile_asf_filepropertiesobject['preroll'] / 1000);
 194  
 195                          //$info['bitrate'] = $thisfile_asf_filepropertiesobject['max_bitrate'];
 196                          $info['bitrate'] = getid3_lib::SafeDiv($thisfile_asf_filepropertiesobject['filesize'] * 8, $info['playtime_seconds']);
 197                      }
 198                      break;
 199  
 200                  case GETID3_ASF_Stream_Properties_Object:
 201                      // Stream Properties Object: (mandatory, one per media stream)
 202                      // Field Name                   Field Type   Size (bits)
 203                      // Object ID                    GUID         128             // GUID for stream properties object - GETID3_ASF_Stream_Properties_Object
 204                      // Object Size                  QWORD        64              // size of stream properties object, including 78 bytes of Stream Properties Object header
 205                      // Stream Type                  GUID         128             // GETID3_ASF_Audio_Media, GETID3_ASF_Video_Media or GETID3_ASF_Command_Media
 206                      // Error Correction Type        GUID         128             // GETID3_ASF_Audio_Spread for audio-only streams, GETID3_ASF_No_Error_Correction for other stream types
 207                      // Time Offset                  QWORD        64              // 100-nanosecond units. typically zero. added to all timestamps of samples in the stream
 208                      // Type-Specific Data Length    DWORD        32              // number of bytes for Type-Specific Data field
 209                      // Error Correction Data Length DWORD        32              // number of bytes for Error Correction Data field
 210                      // Flags                        WORD         16              //
 211                      // * Stream Number              bits         7 (0x007F)      // number of this stream.  1 <= valid <= 127
 212                      // * Reserved                   bits         8 (0x7F80)      // reserved - set to zero
 213                      // * Encrypted Content Flag     bits         1 (0x8000)      // stream contents encrypted if set
 214                      // Reserved                     DWORD        32              // reserved - set to zero
 215                      // Type-Specific Data           BYTESTREAM   variable        // type-specific format data, depending on value of Stream Type
 216                      // Error Correction Data        BYTESTREAM   variable        // error-correction-specific format data, depending on value of Error Correct Type
 217  
 218                      // There is one GETID3_ASF_Stream_Properties_Object for each stream (audio, video) but the
 219                      // stream number isn't known until halfway through decoding the structure, hence it
 220                      // it is decoded to a temporary variable and then stuck in the appropriate index later
 221  
 222                      $StreamPropertiesObjectData['offset']             = $NextObjectOffset + $offset;
 223                      $StreamPropertiesObjectData['objectid']           = $NextObjectGUID;
 224                      $StreamPropertiesObjectData['objectid_guid']      = $NextObjectGUIDtext;
 225                      $StreamPropertiesObjectData['objectsize']         = $NextObjectSize;
 226                      $StreamPropertiesObjectData['stream_type']        = substr($ASFHeaderData, $offset, 16);
 227                      $offset += 16;
 228                      $StreamPropertiesObjectData['stream_type_guid']   = $this->BytestringToGUID($StreamPropertiesObjectData['stream_type']);
 229                      $StreamPropertiesObjectData['error_correct_type'] = substr($ASFHeaderData, $offset, 16);
 230                      $offset += 16;
 231                      $StreamPropertiesObjectData['error_correct_guid'] = $this->BytestringToGUID($StreamPropertiesObjectData['error_correct_type']);
 232                      $StreamPropertiesObjectData['time_offset']        = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
 233                      $offset += 8;
 234                      $StreamPropertiesObjectData['type_data_length']   = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 235                      $offset += 4;
 236                      $StreamPropertiesObjectData['error_data_length']  = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 237                      $offset += 4;
 238                      $StreamPropertiesObjectData['flags_raw']          = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 239                      $offset += 2;
 240                      $StreamPropertiesObjectStreamNumber               = $StreamPropertiesObjectData['flags_raw'] & 0x007F;
 241                      $StreamPropertiesObjectData['flags']['encrypted'] = (bool) ($StreamPropertiesObjectData['flags_raw'] & 0x8000);
 242  
 243                      $offset += 4; // reserved - DWORD
 244                      $StreamPropertiesObjectData['type_specific_data'] = substr($ASFHeaderData, $offset, $StreamPropertiesObjectData['type_data_length']);
 245                      $offset += $StreamPropertiesObjectData['type_data_length'];
 246                      $StreamPropertiesObjectData['error_correct_data'] = substr($ASFHeaderData, $offset, $StreamPropertiesObjectData['error_data_length']);
 247                      $offset += $StreamPropertiesObjectData['error_data_length'];
 248  
 249                      switch ($StreamPropertiesObjectData['stream_type']) {
 250  
 251                          case GETID3_ASF_Audio_Media:
 252                              $thisfile_audio['dataformat']   = (!empty($thisfile_audio['dataformat'])   ? $thisfile_audio['dataformat']   : 'asf');
 253                              $thisfile_audio['bitrate_mode'] = (!empty($thisfile_audio['bitrate_mode']) ? $thisfile_audio['bitrate_mode'] : 'cbr');
 254  
 255                              $audiodata = getid3_riff::parseWAVEFORMATex(substr($StreamPropertiesObjectData['type_specific_data'], 0, 16));
 256                              unset($audiodata['raw']);
 257                              $thisfile_audio = getid3_lib::array_merge_noclobber($audiodata, $thisfile_audio);
 258                              break;
 259  
 260                          case GETID3_ASF_Video_Media:
 261                              $thisfile_video['dataformat']   = (!empty($thisfile_video['dataformat'])   ? $thisfile_video['dataformat']   : 'asf');
 262                              $thisfile_video['bitrate_mode'] = (!empty($thisfile_video['bitrate_mode']) ? $thisfile_video['bitrate_mode'] : 'cbr');
 263                              break;
 264  
 265                          case GETID3_ASF_Command_Media:
 266                          default:
 267                              // do nothing
 268                              break;
 269  
 270                      }
 271  
 272                      $thisfile_asf['stream_properties_object'][$StreamPropertiesObjectStreamNumber] = $StreamPropertiesObjectData;
 273                      unset($StreamPropertiesObjectData); // clear for next stream, if any
 274                      break;
 275  
 276                  case GETID3_ASF_Header_Extension_Object:
 277                      // Header Extension Object: (mandatory, one only)
 278                      // Field Name                   Field Type   Size (bits)
 279                      // Object ID                    GUID         128             // GUID for Header Extension object - GETID3_ASF_Header_Extension_Object
 280                      // Object Size                  QWORD        64              // size of Header Extension object, including 46 bytes of Header Extension Object header
 281                      // Reserved Field 1             GUID         128             // hardcoded: GETID3_ASF_Reserved_1
 282                      // Reserved Field 2             WORD         16              // hardcoded: 0x00000006
 283                      // Header Extension Data Size   DWORD        32              // in bytes. valid: 0, or > 24. equals object size minus 46
 284                      // Header Extension Data        BYTESTREAM   variable        // array of zero or more extended header objects
 285  
 286                      // shortcut
 287                      $thisfile_asf['header_extension_object'] = array();
 288                      $thisfile_asf_headerextensionobject      = &$thisfile_asf['header_extension_object'];
 289  
 290                      $thisfile_asf_headerextensionobject['offset']              = $NextObjectOffset + $offset;
 291                      $thisfile_asf_headerextensionobject['objectid']            = $NextObjectGUID;
 292                      $thisfile_asf_headerextensionobject['objectid_guid']       = $NextObjectGUIDtext;
 293                      $thisfile_asf_headerextensionobject['objectsize']          = $NextObjectSize;
 294                      $thisfile_asf_headerextensionobject['reserved_1']          = substr($ASFHeaderData, $offset, 16);
 295                      $offset += 16;
 296                      $thisfile_asf_headerextensionobject['reserved_1_guid']     = $this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']);
 297                      if ($thisfile_asf_headerextensionobject['reserved_1'] != GETID3_ASF_Reserved_1) {
 298                          $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).')');
 299                          //return false;
 300                          break;
 301                      }
 302                      $thisfile_asf_headerextensionobject['reserved_2']          = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 303                      $offset += 2;
 304                      if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) {
 305                          $this->warning('header_extension_object.reserved_2 ('.$thisfile_asf_headerextensionobject['reserved_2'].') does not match expected value of "6"');
 306                          //return false;
 307                          break;
 308                      }
 309                      $thisfile_asf_headerextensionobject['extension_data_size'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 310                      $offset += 4;
 311                      $thisfile_asf_headerextensionobject['extension_data']      =                              substr($ASFHeaderData, $offset, $thisfile_asf_headerextensionobject['extension_data_size']);
 312                      $unhandled_sections = 0;
 313                      $thisfile_asf_headerextensionobject['extension_data_parsed'] = $this->HeaderExtensionObjectDataParse($thisfile_asf_headerextensionobject['extension_data'], $unhandled_sections);
 314                      if ($unhandled_sections === 0) {
 315                          unset($thisfile_asf_headerextensionobject['extension_data']);
 316                      }
 317                      $offset += $thisfile_asf_headerextensionobject['extension_data_size'];
 318                      break;
 319  
 320                  case GETID3_ASF_Codec_List_Object:
 321                      // Codec List Object: (optional, one only)
 322                      // Field Name                   Field Type   Size (bits)
 323                      // Object ID                    GUID         128             // GUID for Codec List object - GETID3_ASF_Codec_List_Object
 324                      // Object Size                  QWORD        64              // size of Codec List object, including 44 bytes of Codec List Object header
 325                      // Reserved                     GUID         128             // hardcoded: 86D15241-311D-11D0-A3A4-00A0C90348F6
 326                      // Codec Entries Count          DWORD        32              // number of entries in Codec Entries array
 327                      // Codec Entries                array of:    variable        //
 328                      // * Type                       WORD         16              // 0x0001 = Video Codec, 0x0002 = Audio Codec, 0xFFFF = Unknown Codec
 329                      // * Codec Name Length          WORD         16              // number of Unicode characters stored in the Codec Name field
 330                      // * Codec Name                 WCHAR        variable        // array of Unicode characters - name of codec used to create the content
 331                      // * Codec Description Length   WORD         16              // number of Unicode characters stored in the Codec Description field
 332                      // * Codec Description          WCHAR        variable        // array of Unicode characters - description of format used to create the content
 333                      // * Codec Information Length   WORD         16              // number of Unicode characters stored in the Codec Information field
 334                      // * Codec Information          BYTESTREAM   variable        // opaque array of information bytes about the codec used to create the content
 335  
 336                      // shortcut
 337                      $thisfile_asf['codec_list_object'] = array();
 338                      /** @var mixed[] $thisfile_asf_codeclistobject */
 339                      $thisfile_asf_codeclistobject      = &$thisfile_asf['codec_list_object'];
 340  
 341                      $thisfile_asf_codeclistobject['offset']                    = $NextObjectOffset + $offset;
 342                      $thisfile_asf_codeclistobject['objectid']                  = $NextObjectGUID;
 343                      $thisfile_asf_codeclistobject['objectid_guid']             = $NextObjectGUIDtext;
 344                      $thisfile_asf_codeclistobject['objectsize']                = $NextObjectSize;
 345                      $thisfile_asf_codeclistobject['reserved']                  = substr($ASFHeaderData, $offset, 16);
 346                      $offset += 16;
 347                      $thisfile_asf_codeclistobject['reserved_guid']             = $this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']);
 348                      if ($thisfile_asf_codeclistobject['reserved'] != $this->GUIDtoBytestring('86D15241-311D-11D0-A3A4-00A0C90348F6')) {
 349                          $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}');
 350                          //return false;
 351                          break;
 352                      }
 353                      $thisfile_asf_codeclistobject['codec_entries_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 354                      if ($thisfile_asf_codeclistobject['codec_entries_count'] > 0) {
 355                          $thisfile_asf_codeclistobject['codec_entries'] = array();
 356                      }
 357                      $offset += 4;
 358                      for ($CodecEntryCounter = 0; $CodecEntryCounter < $thisfile_asf_codeclistobject['codec_entries_count']; $CodecEntryCounter++) {
 359                          // shortcut
 360                          $thisfile_asf_codeclistobject['codec_entries'][$CodecEntryCounter] = array();
 361                          $thisfile_asf_codeclistobject_codecentries_current = &$thisfile_asf_codeclistobject['codec_entries'][$CodecEntryCounter];
 362  
 363                          $thisfile_asf_codeclistobject_codecentries_current['type_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 364                          $offset += 2;
 365                          $thisfile_asf_codeclistobject_codecentries_current['type'] = self::codecListObjectTypeLookup($thisfile_asf_codeclistobject_codecentries_current['type_raw']);
 366  
 367                          $CodecNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character
 368                          $offset += 2;
 369                          $thisfile_asf_codeclistobject_codecentries_current['name'] = substr($ASFHeaderData, $offset, $CodecNameLength);
 370                          $offset += $CodecNameLength;
 371  
 372                          $CodecDescriptionLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character
 373                          $offset += 2;
 374                          $thisfile_asf_codeclistobject_codecentries_current['description'] = substr($ASFHeaderData, $offset, $CodecDescriptionLength);
 375                          $offset += $CodecDescriptionLength;
 376  
 377                          $CodecInformationLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 378                          $offset += 2;
 379                          $thisfile_asf_codeclistobject_codecentries_current['information'] = substr($ASFHeaderData, $offset, $CodecInformationLength);
 380                          $offset += $CodecInformationLength;
 381  
 382                          if ($thisfile_asf_codeclistobject_codecentries_current['type_raw'] == 2) { // audio codec
 383  
 384                              if (strpos($thisfile_asf_codeclistobject_codecentries_current['description'], ',') === false) {
 385                                  $this->warning('[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.'][description] expected to contain comma-separated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current['description'].'"');
 386                              } else {
 387  
 388                                  list($AudioCodecBitrate, $AudioCodecFrequency, $AudioCodecChannels) = explode(',', $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']));
 389                                  $thisfile_audio['codec'] = $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['name']);
 390  
 391                                  if (!isset($thisfile_audio['bitrate']) && strstr($AudioCodecBitrate, 'kbps')) {
 392                                      $thisfile_audio['bitrate'] = (int) trim(str_replace('kbps', '', $AudioCodecBitrate)) * 1000;
 393                                  }
 394                                  //if (!isset($thisfile_video['bitrate']) && isset($thisfile_audio['bitrate']) && isset($thisfile_asf['file_properties_object']['max_bitrate']) && ($thisfile_asf_codeclistobject['codec_entries_count'] > 1)) {
 395                                  if (empty($thisfile_video['bitrate']) && !empty($thisfile_audio['bitrate']) && !empty($info['bitrate'])) {
 396                                      //$thisfile_video['bitrate'] = $thisfile_asf['file_properties_object']['max_bitrate'] - $thisfile_audio['bitrate'];
 397                                      $thisfile_video['bitrate'] = $info['bitrate'] - $thisfile_audio['bitrate'];
 398                                  }
 399  
 400                                  $AudioCodecFrequency = (int) trim(str_replace('kHz', '', $AudioCodecFrequency));
 401                                  switch ($AudioCodecFrequency) {
 402                                      case 8:
 403                                      case 8000:
 404                                          $thisfile_audio['sample_rate'] = 8000;
 405                                          break;
 406  
 407                                      case 11:
 408                                      case 11025:
 409                                          $thisfile_audio['sample_rate'] = 11025;
 410                                          break;
 411  
 412                                      case 12:
 413                                      case 12000:
 414                                          $thisfile_audio['sample_rate'] = 12000;
 415                                          break;
 416  
 417                                      case 16:
 418                                      case 16000:
 419                                          $thisfile_audio['sample_rate'] = 16000;
 420                                          break;
 421  
 422                                      case 22:
 423                                      case 22050:
 424                                          $thisfile_audio['sample_rate'] = 22050;
 425                                          break;
 426  
 427                                      case 24:
 428                                      case 24000:
 429                                          $thisfile_audio['sample_rate'] = 24000;
 430                                          break;
 431  
 432                                      case 32:
 433                                      case 32000:
 434                                          $thisfile_audio['sample_rate'] = 32000;
 435                                          break;
 436  
 437                                      case 44:
 438                                      case 441000:
 439                                          $thisfile_audio['sample_rate'] = 44100;
 440                                          break;
 441  
 442                                      case 48:
 443                                      case 48000:
 444                                          $thisfile_audio['sample_rate'] = 48000;
 445                                          break;
 446  
 447                                      default:
 448                                          $this->warning('unknown frequency: "'.$AudioCodecFrequency.'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']).')');
 449                                          break;
 450                                  }
 451  
 452                                  if (!isset($thisfile_audio['channels'])) {
 453                                      if (strstr($AudioCodecChannels, 'stereo')) {
 454                                          $thisfile_audio['channels'] = 2;
 455                                      } elseif (strstr($AudioCodecChannels, 'mono')) {
 456                                          $thisfile_audio['channels'] = 1;
 457                                      }
 458                                  }
 459  
 460                              }
 461                          }
 462                      }
 463                      break;
 464  
 465                  case GETID3_ASF_Script_Command_Object:
 466                      // Script Command Object: (optional, one only)
 467                      // Field Name                   Field Type   Size (bits)
 468                      // Object ID                    GUID         128             // GUID for Script Command object - GETID3_ASF_Script_Command_Object
 469                      // Object Size                  QWORD        64              // size of Script Command object, including 44 bytes of Script Command Object header
 470                      // Reserved                     GUID         128             // hardcoded: 4B1ACBE3-100B-11D0-A39B-00A0C90348F6
 471                      // Commands Count               WORD         16              // number of Commands structures in the Script Commands Objects
 472                      // Command Types Count          WORD         16              // number of Command Types structures in the Script Commands Objects
 473                      // Command Types                array of:    variable        //
 474                      // * Command Type Name Length   WORD         16              // number of Unicode characters for Command Type Name
 475                      // * Command Type Name          WCHAR        variable        // array of Unicode characters - name of a type of command
 476                      // Commands                     array of:    variable        //
 477                      // * Presentation Time          DWORD        32              // presentation time of that command, in milliseconds
 478                      // * Type Index                 WORD         16              // type of this command, as a zero-based index into the array of Command Types of this object
 479                      // * Command Name Length        WORD         16              // number of Unicode characters for Command Name
 480                      // * Command Name               WCHAR        variable        // array of Unicode characters - name of this command
 481  
 482                      // shortcut
 483                      $thisfile_asf['script_command_object'] = array();
 484                      $thisfile_asf_scriptcommandobject      = &$thisfile_asf['script_command_object'];
 485  
 486                      $thisfile_asf_scriptcommandobject['offset']               = $NextObjectOffset + $offset;
 487                      $thisfile_asf_scriptcommandobject['objectid']             = $NextObjectGUID;
 488                      $thisfile_asf_scriptcommandobject['objectid_guid']        = $NextObjectGUIDtext;
 489                      $thisfile_asf_scriptcommandobject['objectsize']           = $NextObjectSize;
 490                      $thisfile_asf_scriptcommandobject['reserved']             = substr($ASFHeaderData, $offset, 16);
 491                      $offset += 16;
 492                      $thisfile_asf_scriptcommandobject['reserved_guid']        = $this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']);
 493                      if ($thisfile_asf_scriptcommandobject['reserved'] != $this->GUIDtoBytestring('4B1ACBE3-100B-11D0-A39B-00A0C90348F6')) {
 494                          $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}');
 495                          //return false;
 496                          break;
 497                      }
 498                      $thisfile_asf_scriptcommandobject['commands_count']       = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 499                      $offset += 2;
 500                      $thisfile_asf_scriptcommandobject['command_types_count']  = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 501                      $offset += 2;
 502                      for ($CommandTypesCounter = 0; $CommandTypesCounter < $thisfile_asf_scriptcommandobject['command_types_count']; $CommandTypesCounter++) {
 503                          $CommandTypeNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character
 504                          $offset += 2;
 505                          $thisfile_asf_scriptcommandobject['command_types'][$CommandTypesCounter]['name'] = substr($ASFHeaderData, $offset, $CommandTypeNameLength);
 506                          $offset += $CommandTypeNameLength;
 507                      }
 508                      for ($CommandsCounter = 0; $CommandsCounter < $thisfile_asf_scriptcommandobject['commands_count']; $CommandsCounter++) {
 509                          $thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['presentation_time']  = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 510                          $offset += 4;
 511                          $thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['type_index']         = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 512                          $offset += 2;
 513  
 514                          $CommandTypeNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character
 515                          $offset += 2;
 516                          $thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['name'] = substr($ASFHeaderData, $offset, $CommandTypeNameLength);
 517                          $offset += $CommandTypeNameLength;
 518                      }
 519                      break;
 520  
 521                  case GETID3_ASF_Marker_Object:
 522                      // Marker Object: (optional, one only)
 523                      // Field Name                   Field Type   Size (bits)
 524                      // Object ID                    GUID         128             // GUID for Marker object - GETID3_ASF_Marker_Object
 525                      // Object Size                  QWORD        64              // size of Marker object, including 48 bytes of Marker Object header
 526                      // Reserved                     GUID         128             // hardcoded: 4CFEDB20-75F6-11CF-9C0F-00A0C90349CB
 527                      // Markers Count                DWORD        32              // number of Marker structures in Marker Object
 528                      // Reserved                     WORD         16              // hardcoded: 0x0000
 529                      // Name Length                  WORD         16              // number of bytes in the Name field
 530                      // Name                         WCHAR        variable        // name of the Marker Object
 531                      // Markers                      array of:    variable        //
 532                      // * Offset                     QWORD        64              // byte offset into Data Object
 533                      // * Presentation Time          QWORD        64              // in 100-nanosecond units
 534                      // * Entry Length               WORD         16              // length in bytes of (Send Time + Flags + Marker Description Length + Marker Description + Padding)
 535                      // * Send Time                  DWORD        32              // in milliseconds
 536                      // * Flags                      DWORD        32              // hardcoded: 0x00000000
 537                      // * Marker Description Length  DWORD        32              // number of bytes in Marker Description field
 538                      // * Marker Description         WCHAR        variable        // array of Unicode characters - description of marker entry
 539                      // * Padding                    BYTESTREAM   variable        // optional padding bytes
 540  
 541                      // shortcut
 542                      $thisfile_asf['marker_object'] = array();
 543                      $thisfile_asf_markerobject     = &$thisfile_asf['marker_object'];
 544  
 545                      $thisfile_asf_markerobject['offset']               = $NextObjectOffset + $offset;
 546                      $thisfile_asf_markerobject['objectid']             = $NextObjectGUID;
 547                      $thisfile_asf_markerobject['objectid_guid']        = $NextObjectGUIDtext;
 548                      $thisfile_asf_markerobject['objectsize']           = $NextObjectSize;
 549                      $thisfile_asf_markerobject['reserved']             = substr($ASFHeaderData, $offset, 16);
 550                      $offset += 16;
 551                      $thisfile_asf_markerobject['reserved_guid']        = $this->BytestringToGUID($thisfile_asf_markerobject['reserved']);
 552                      if ($thisfile_asf_markerobject['reserved'] != $this->GUIDtoBytestring('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) {
 553                          $this->warning('marker_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_markerobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}');
 554                          break;
 555                      }
 556                      $thisfile_asf_markerobject['markers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 557                      $offset += 4;
 558                      $thisfile_asf_markerobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 559                      $offset += 2;
 560                      if ($thisfile_asf_markerobject['reserved_2'] != 0) {
 561                          $this->warning('marker_object.reserved_2 ('.$thisfile_asf_markerobject['reserved_2'].') does not match expected value of "0"');
 562                          break;
 563                      }
 564                      $thisfile_asf_markerobject['name_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 565                      $offset += 2;
 566                      $thisfile_asf_markerobject['name'] = substr($ASFHeaderData, $offset, $thisfile_asf_markerobject['name_length']);
 567                      $offset += $thisfile_asf_markerobject['name_length'];
 568                      for ($MarkersCounter = 0; $MarkersCounter < $thisfile_asf_markerobject['markers_count']; $MarkersCounter++) {
 569                          $thisfile_asf_markerobject['markers'][$MarkersCounter]['offset']  = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
 570                          $offset += 8;
 571                          $thisfile_asf_markerobject['markers'][$MarkersCounter]['presentation_time']         = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
 572                          $offset += 8;
 573                          $thisfile_asf_markerobject['markers'][$MarkersCounter]['entry_length']              = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 574                          $offset += 2;
 575                          $thisfile_asf_markerobject['markers'][$MarkersCounter]['send_time']                 = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 576                          $offset += 4;
 577                          $thisfile_asf_markerobject['markers'][$MarkersCounter]['flags']                     = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 578                          $offset += 4;
 579                          $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 580                          $offset += 4;
 581                          $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description']        = substr($ASFHeaderData, $offset, $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length']);
 582                          $offset += $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length'];
 583                          $PaddingLength = $thisfile_asf_markerobject['markers'][$MarkersCounter]['entry_length'] - 4 -  4 - 4 - $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length'];
 584                          if ($PaddingLength > 0) {
 585                              $thisfile_asf_markerobject['markers'][$MarkersCounter]['padding']               = substr($ASFHeaderData, $offset, $PaddingLength);
 586                              $offset += $PaddingLength;
 587                          }
 588                      }
 589                      break;
 590  
 591                  case GETID3_ASF_Bitrate_Mutual_Exclusion_Object:
 592                      // Bitrate Mutual Exclusion Object: (optional)
 593                      // Field Name                   Field Type   Size (bits)
 594                      // Object ID                    GUID         128             // GUID for Bitrate Mutual Exclusion object - GETID3_ASF_Bitrate_Mutual_Exclusion_Object
 595                      // Object Size                  QWORD        64              // size of Bitrate Mutual Exclusion object, including 42 bytes of Bitrate Mutual Exclusion Object header
 596                      // Exlusion Type                GUID         128             // nature of mutual exclusion relationship. one of: (GETID3_ASF_Mutex_Bitrate, GETID3_ASF_Mutex_Unknown)
 597                      // Stream Numbers Count         WORD         16              // number of video streams
 598                      // Stream Numbers               WORD         variable        // array of mutually exclusive video stream numbers. 1 <= valid <= 127
 599  
 600                      // shortcut
 601                      $thisfile_asf['bitrate_mutual_exclusion_object'] = array();
 602                      $thisfile_asf_bitratemutualexclusionobject       = &$thisfile_asf['bitrate_mutual_exclusion_object'];
 603  
 604                      $thisfile_asf_bitratemutualexclusionobject['offset']               = $NextObjectOffset + $offset;
 605                      $thisfile_asf_bitratemutualexclusionobject['objectid']             = $NextObjectGUID;
 606                      $thisfile_asf_bitratemutualexclusionobject['objectid_guid']        = $NextObjectGUIDtext;
 607                      $thisfile_asf_bitratemutualexclusionobject['objectsize']           = $NextObjectSize;
 608                      $thisfile_asf_bitratemutualexclusionobject['reserved']             = substr($ASFHeaderData, $offset, 16);
 609                      $thisfile_asf_bitratemutualexclusionobject['reserved_guid']        = $this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']);
 610                      $offset += 16;
 611                      if (($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Bitrate) && ($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Unknown)) {
 612                          $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).'}');
 613                          //return false;
 614                          break;
 615                      }
 616                      $thisfile_asf_bitratemutualexclusionobject['stream_numbers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 617                      $offset += 2;
 618                      for ($StreamNumberCounter = 0; $StreamNumberCounter < $thisfile_asf_bitratemutualexclusionobject['stream_numbers_count']; $StreamNumberCounter++) {
 619                          $thisfile_asf_bitratemutualexclusionobject['stream_numbers'][$StreamNumberCounter] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 620                          $offset += 2;
 621                      }
 622                      break;
 623  
 624                  case GETID3_ASF_Error_Correction_Object:
 625                      // Error Correction Object: (optional, one only)
 626                      // Field Name                   Field Type   Size (bits)
 627                      // Object ID                    GUID         128             // GUID for Error Correction object - GETID3_ASF_Error_Correction_Object
 628                      // Object Size                  QWORD        64              // size of Error Correction object, including 44 bytes of Error Correction Object header
 629                      // Error Correction Type        GUID         128             // type of error correction. one of: (GETID3_ASF_No_Error_Correction, GETID3_ASF_Audio_Spread)
 630                      // Error Correction Data Length DWORD        32              // number of bytes in Error Correction Data field
 631                      // Error Correction Data        BYTESTREAM   variable        // structure depends on value of Error Correction Type field
 632  
 633                      // shortcut
 634                      $thisfile_asf['error_correction_object'] = array();
 635                      $thisfile_asf_errorcorrectionobject      = &$thisfile_asf['error_correction_object'];
 636  
 637                      $thisfile_asf_errorcorrectionobject['offset']                = $NextObjectOffset + $offset;
 638                      $thisfile_asf_errorcorrectionobject['objectid']              = $NextObjectGUID;
 639                      $thisfile_asf_errorcorrectionobject['objectid_guid']         = $NextObjectGUIDtext;
 640                      $thisfile_asf_errorcorrectionobject['objectsize']            = $NextObjectSize;
 641                      $thisfile_asf_errorcorrectionobject['error_correction_type'] = substr($ASFHeaderData, $offset, 16);
 642                      $offset += 16;
 643                      $thisfile_asf_errorcorrectionobject['error_correction_guid'] = $this->BytestringToGUID($thisfile_asf_errorcorrectionobject['error_correction_type']);
 644                      $thisfile_asf_errorcorrectionobject['error_correction_data_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 645                      $offset += 4;
 646                      switch ($thisfile_asf_errorcorrectionobject['error_correction_type']) {
 647                          case GETID3_ASF_No_Error_Correction:
 648                              // should be no data, but just in case there is, skip to the end of the field
 649                              $offset += $thisfile_asf_errorcorrectionobject['error_correction_data_length'];
 650                              break;
 651  
 652                          case GETID3_ASF_Audio_Spread:
 653                              // Field Name                   Field Type   Size (bits)
 654                              // Span                         BYTE         8               // number of packets over which audio will be spread.
 655                              // Virtual Packet Length        WORD         16              // size of largest audio payload found in audio stream
 656                              // Virtual Chunk Length         WORD         16              // size of largest audio payload found in audio stream
 657                              // Silence Data Length          WORD         16              // number of bytes in Silence Data field
 658                              // Silence Data                 BYTESTREAM   variable        // hardcoded: 0x00 * (Silence Data Length) bytes
 659  
 660                              $thisfile_asf_errorcorrectionobject['span']                  = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 1));
 661                              $offset += 1;
 662                              $thisfile_asf_errorcorrectionobject['virtual_packet_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 663                              $offset += 2;
 664                              $thisfile_asf_errorcorrectionobject['virtual_chunk_length']  = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 665                              $offset += 2;
 666                              $thisfile_asf_errorcorrectionobject['silence_data_length']   = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 667                              $offset += 2;
 668                              $thisfile_asf_errorcorrectionobject['silence_data']          = substr($ASFHeaderData, $offset, $thisfile_asf_errorcorrectionobject['silence_data_length']);
 669                              $offset += $thisfile_asf_errorcorrectionobject['silence_data_length'];
 670                              break;
 671  
 672                          default:
 673                              $this->warning('error_correction_object.error_correction_type GUID {'.$this->BytestringToGUID($thisfile_asf_errorcorrectionobject['error_correction_type']).'} 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).'}');
 674                              //return false;
 675                              break;
 676                      }
 677  
 678                      break;
 679  
 680                  case GETID3_ASF_Content_Description_Object:
 681                      // Content Description Object: (optional, one only)
 682                      // Field Name                   Field Type   Size (bits)
 683                      // Object ID                    GUID         128             // GUID for Content Description object - GETID3_ASF_Content_Description_Object
 684                      // Object Size                  QWORD        64              // size of Content Description object, including 34 bytes of Content Description Object header
 685                      // Title Length                 WORD         16              // number of bytes in Title field
 686                      // Author Length                WORD         16              // number of bytes in Author field
 687                      // Copyright Length             WORD         16              // number of bytes in Copyright field
 688                      // Description Length           WORD         16              // number of bytes in Description field
 689                      // Rating Length                WORD         16              // number of bytes in Rating field
 690                      // Title                        WCHAR        16              // array of Unicode characters - Title
 691                      // Author                       WCHAR        16              // array of Unicode characters - Author
 692                      // Copyright                    WCHAR        16              // array of Unicode characters - Copyright
 693                      // Description                  WCHAR        16              // array of Unicode characters - Description
 694                      // Rating                       WCHAR        16              // array of Unicode characters - Rating
 695  
 696                      // shortcut
 697                      $thisfile_asf['content_description_object'] = array();
 698                      $thisfile_asf_contentdescriptionobject      = &$thisfile_asf['content_description_object'];
 699  
 700                      $thisfile_asf_contentdescriptionobject['offset']                = $NextObjectOffset + $offset;
 701                      $thisfile_asf_contentdescriptionobject['objectid']              = $NextObjectGUID;
 702                      $thisfile_asf_contentdescriptionobject['objectid_guid']         = $NextObjectGUIDtext;
 703                      $thisfile_asf_contentdescriptionobject['objectsize']            = $NextObjectSize;
 704                      $thisfile_asf_contentdescriptionobject['title_length']          = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 705                      $offset += 2;
 706                      $thisfile_asf_contentdescriptionobject['author_length']         = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 707                      $offset += 2;
 708                      $thisfile_asf_contentdescriptionobject['copyright_length']      = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 709                      $offset += 2;
 710                      $thisfile_asf_contentdescriptionobject['description_length']    = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 711                      $offset += 2;
 712                      $thisfile_asf_contentdescriptionobject['rating_length']         = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 713                      $offset += 2;
 714                      $thisfile_asf_contentdescriptionobject['title']                 = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['title_length']);
 715                      $offset += $thisfile_asf_contentdescriptionobject['title_length'];
 716                      $thisfile_asf_contentdescriptionobject['author']                = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['author_length']);
 717                      $offset += $thisfile_asf_contentdescriptionobject['author_length'];
 718                      $thisfile_asf_contentdescriptionobject['copyright']             = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['copyright_length']);
 719                      $offset += $thisfile_asf_contentdescriptionobject['copyright_length'];
 720                      $thisfile_asf_contentdescriptionobject['description']           = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['description_length']);
 721                      $offset += $thisfile_asf_contentdescriptionobject['description_length'];
 722                      $thisfile_asf_contentdescriptionobject['rating']                = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['rating_length']);
 723                      $offset += $thisfile_asf_contentdescriptionobject['rating_length'];
 724  
 725                      $ASFcommentKeysToCopy = array('title'=>'title', 'author'=>'artist', 'copyright'=>'copyright', 'description'=>'comment', 'rating'=>'rating');
 726                      foreach ($ASFcommentKeysToCopy as $keytocopyfrom => $keytocopyto) {
 727                          if (!empty($thisfile_asf_contentdescriptionobject[$keytocopyfrom])) {
 728                              $thisfile_asf_comments[$keytocopyto][] = $this->TrimTerm($thisfile_asf_contentdescriptionobject[$keytocopyfrom]);
 729                          }
 730                      }
 731                      break;
 732  
 733                  case GETID3_ASF_Extended_Content_Description_Object:
 734                      // Extended Content Description Object: (optional, one only)
 735                      // Field Name                   Field Type   Size (bits)
 736                      // Object ID                    GUID         128             // GUID for Extended Content Description object - GETID3_ASF_Extended_Content_Description_Object
 737                      // Object Size                  QWORD        64              // size of ExtendedContent Description object, including 26 bytes of Extended Content Description Object header
 738                      // Content Descriptors Count    WORD         16              // number of entries in Content Descriptors list
 739                      // Content Descriptors          array of:    variable        //
 740                      // * Descriptor Name Length     WORD         16              // size in bytes of Descriptor Name field
 741                      // * Descriptor Name            WCHAR        variable        // array of Unicode characters - Descriptor Name
 742                      // * Descriptor Value Data Type WORD         16              // Lookup array:
 743                                                                                      // 0x0000 = Unicode String (variable length)
 744                                                                                      // 0x0001 = BYTE array     (variable length)
 745                                                                                      // 0x0002 = BOOL           (DWORD, 32 bits)
 746                                                                                      // 0x0003 = DWORD          (DWORD, 32 bits)
 747                                                                                      // 0x0004 = QWORD          (QWORD, 64 bits)
 748                                                                                      // 0x0005 = WORD           (WORD,  16 bits)
 749                      // * Descriptor Value Length    WORD         16              // number of bytes stored in Descriptor Value field
 750                      // * Descriptor Value           variable     variable        // value for Content Descriptor
 751  
 752                      // shortcut
 753                      $thisfile_asf['extended_content_description_object'] = array();
 754                      $thisfile_asf_extendedcontentdescriptionobject       = &$thisfile_asf['extended_content_description_object'];
 755  
 756                      $thisfile_asf_extendedcontentdescriptionobject['offset']                    = $NextObjectOffset + $offset;
 757                      $thisfile_asf_extendedcontentdescriptionobject['objectid']                  = $NextObjectGUID;
 758                      $thisfile_asf_extendedcontentdescriptionobject['objectid_guid']             = $NextObjectGUIDtext;
 759                      $thisfile_asf_extendedcontentdescriptionobject['objectsize']                = $NextObjectSize;
 760                      $thisfile_asf_extendedcontentdescriptionobject['content_descriptors_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 761                      $offset += 2;
 762                      for ($ExtendedContentDescriptorsCounter = 0; $ExtendedContentDescriptorsCounter < $thisfile_asf_extendedcontentdescriptionobject['content_descriptors_count']; $ExtendedContentDescriptorsCounter++) {
 763                          // shortcut
 764                          $thisfile_asf_extendedcontentdescriptionobject['content_descriptors'][$ExtendedContentDescriptorsCounter] = array();
 765                          $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current                 = &$thisfile_asf_extendedcontentdescriptionobject['content_descriptors'][$ExtendedContentDescriptorsCounter];
 766  
 767                          $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['base_offset']  = $offset + 30;
 768                          $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name_length']  = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 769                          $offset += 2;
 770                          $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name']         = substr($ASFHeaderData, $offset, $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name_length']);
 771                          $offset += $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name_length'];
 772                          $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type']   = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 773                          $offset += 2;
 774                          $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 775                          $offset += 2;
 776                          $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']        = substr($ASFHeaderData, $offset, $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length']);
 777                          $offset += $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length'];
 778                          switch ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type']) {
 779                              case 0x0000: // Unicode string
 780                                  break;
 781  
 782                              case 0x0001: // BYTE array
 783                                  // do nothing
 784                                  break;
 785  
 786                              case 0x0002: // BOOL
 787                                  $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = (bool) getid3_lib::LittleEndian2Int($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']);
 788                                  break;
 789  
 790                              case 0x0003: // DWORD
 791                              case 0x0004: // QWORD
 792                              case 0x0005: // WORD
 793                                  $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = getid3_lib::LittleEndian2Int($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']);
 794                                  break;
 795  
 796                              default:
 797                                  $this->warning('extended_content_description.content_descriptors.'.$ExtendedContentDescriptorsCounter.'.value_type is invalid ('.$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'].')');
 798                                  //return false;
 799                                  break;
 800                          }
 801                          switch ($this->TrimConvert(strtolower($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name']))) {
 802  
 803                              case 'wm/albumartist':
 804                              case 'artist':
 805                                  // Note: not 'artist', that comes from 'author' tag
 806                                  $thisfile_asf_comments['albumartist'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
 807                                  break;
 808  
 809                              case 'wm/albumtitle':
 810                              case 'album':
 811                                  $thisfile_asf_comments['album']  = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
 812                                  break;
 813  
 814                              case 'wm/genre':
 815                              case 'genre':
 816                                  $thisfile_asf_comments['genre'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
 817                                  break;
 818  
 819                              case 'wm/partofset':
 820                                  $thisfile_asf_comments['partofset'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
 821                                  break;
 822  
 823                              case 'wm/tracknumber':
 824                              case 'tracknumber':
 825                                  // be careful casting to int: casting unicode strings to int gives unexpected results (stops parsing at first non-numeric character)
 826                                  $thisfile_asf_comments['track_number'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
 827                                  foreach ($thisfile_asf_comments['track_number'] as $key => $value) {
 828                                      if (preg_match('/^[0-9\x00]+$/', $value)) {
 829                                          $thisfile_asf_comments['track_number'][$key] = intval(str_replace("\x00", '', $value));
 830                                      }
 831                                  }
 832                                  break;
 833  
 834                              case 'wm/track':
 835                                  if (empty($thisfile_asf_comments['track_number'])) {
 836                                      $thisfile_asf_comments['track_number'] = array(1 + (int) $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
 837                                  }
 838                                  break;
 839  
 840                              case 'wm/year':
 841                              case 'year':
 842                              case 'date':
 843                                  $thisfile_asf_comments['year'] = array( $this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
 844                                  break;
 845  
 846                              case 'wm/lyrics':
 847                              case 'lyrics':
 848                                  $thisfile_asf_comments['lyrics'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
 849                                  break;
 850  
 851                              case 'isvbr':
 852                                  if ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']) {
 853                                      $thisfile_audio['bitrate_mode'] = 'vbr';
 854                                      $thisfile_video['bitrate_mode'] = 'vbr';
 855                                  }
 856                                  break;
 857  
 858                              case 'id3':
 859                                  $this->getid3->include_module('tag.id3v2');
 860  
 861                                  $getid3_id3v2 = new getid3_id3v2($this->getid3);
 862                                  $getid3_id3v2->AnalyzeString($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']);
 863                                  unset($getid3_id3v2);
 864  
 865                                  if ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length'] > 1024) {
 866                                      $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = '<value too large to display>';
 867                                  }
 868                                  break;
 869  
 870                              case 'wm/encodingtime':
 871                                  $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['encoding_time_unix'] = $this->FILETIMEtoUNIXtime($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']);
 872                                  $thisfile_asf_comments['encoding_time_unix'] = array($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['encoding_time_unix']);
 873                                  break;
 874  
 875                              case 'wm/picture':
 876                                  $WMpicture = $this->ASF_WMpicture($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']);
 877                                  foreach ($WMpicture as $key => $value) {
 878                                      $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[$key] = $value;
 879                                  }
 880                                  unset($WMpicture);
 881  /*
 882                                  $wm_picture_offset = 0;
 883                                  $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type_id'] = getid3_lib::LittleEndian2Int(substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset, 1));
 884                                  $wm_picture_offset += 1;
 885                                  $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type']    = self::WMpictureTypeLookup($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type_id']);
 886                                  $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_size']    = getid3_lib::LittleEndian2Int(substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset, 4));
 887                                  $wm_picture_offset += 4;
 888  
 889                                  $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_mime'] = '';
 890                                  do {
 891                                      $next_byte_pair = substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset, 2);
 892                                      $wm_picture_offset += 2;
 893                                      $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_mime'] .= $next_byte_pair;
 894                                  } while ($next_byte_pair !== "\x00\x00");
 895  
 896                                  $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_description'] = '';
 897                                  do {
 898                                      $next_byte_pair = substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset, 2);
 899                                      $wm_picture_offset += 2;
 900                                      $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_description'] .= $next_byte_pair;
 901                                  } while ($next_byte_pair !== "\x00\x00");
 902  
 903                                  $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['dataoffset'] = $wm_picture_offset;
 904                                  $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['data'] = substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset);
 905                                  unset($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']);
 906  
 907                                  $imageinfo = array();
 908                                  $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_mime'] = '';
 909                                  $imagechunkcheck = getid3_lib::GetDataImageSize($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['data'], $imageinfo);
 910                                  unset($imageinfo);
 911                                  if (!empty($imagechunkcheck)) {
 912                                      $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]);
 913                                  }
 914                                  if (!isset($thisfile_asf_comments['picture'])) {
 915                                      $thisfile_asf_comments['picture'] = array();
 916                                  }
 917                                  $thisfile_asf_comments['picture'][] = array('data'=>$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['data'], 'image_mime'=>$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_mime']);
 918  */
 919                                  break;
 920  
 921                              default:
 922                                  switch ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type']) {
 923                                      case 0: // Unicode string
 924                                          if (substr($this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name']), 0, 3) == 'WM/') {
 925                                              $thisfile_asf_comments[str_replace('wm/', '', strtolower($this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name'])))] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
 926                                          }
 927                                          break;
 928  
 929                                      case 1:
 930                                          break;
 931                                  }
 932                                  break;
 933                          }
 934  
 935                      }
 936                      break;
 937  
 938                  case GETID3_ASF_Stream_Bitrate_Properties_Object:
 939                      // Stream Bitrate Properties Object: (optional, one only)
 940                      // Field Name                   Field Type   Size (bits)
 941                      // Object ID                    GUID         128             // GUID for Stream Bitrate Properties object - GETID3_ASF_Stream_Bitrate_Properties_Object
 942                      // Object Size                  QWORD        64              // size of Extended Content Description object, including 26 bytes of Stream Bitrate Properties Object header
 943                      // Bitrate Records Count        WORD         16              // number of records in Bitrate Records
 944                      // Bitrate Records              array of:    variable        //
 945                      // * Flags                      WORD         16              //
 946                      // * * Stream Number            bits         7  (0x007F)     // number of this stream
 947                      // * * Reserved                 bits         9  (0xFF80)     // hardcoded: 0
 948                      // * Average Bitrate            DWORD        32              // in bits per second
 949  
 950                      // shortcut
 951                      $thisfile_asf['stream_bitrate_properties_object'] = array();
 952                      $thisfile_asf_streambitratepropertiesobject       = &$thisfile_asf['stream_bitrate_properties_object'];
 953  
 954                      $thisfile_asf_streambitratepropertiesobject['offset']                    = $NextObjectOffset + $offset;
 955                      $thisfile_asf_streambitratepropertiesobject['objectid']                  = $NextObjectGUID;
 956                      $thisfile_asf_streambitratepropertiesobject['objectid_guid']             = $NextObjectGUIDtext;
 957                      $thisfile_asf_streambitratepropertiesobject['objectsize']                = $NextObjectSize;
 958                      $thisfile_asf_streambitratepropertiesobject['bitrate_records_count']     = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 959                      $offset += 2;
 960                      for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitratepropertiesobject['bitrate_records_count']; $BitrateRecordsCounter++) {
 961                          $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['flags_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
 962                          $offset += 2;
 963                          $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['flags']['stream_number'] = $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['flags_raw'] & 0x007F;
 964                          $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
 965                          $offset += 4;
 966                      }
 967                      break;
 968  
 969                  case GETID3_ASF_Padding_Object:
 970                      // Padding Object: (optional)
 971                      // Field Name                   Field Type   Size (bits)
 972                      // Object ID                    GUID         128             // GUID for Padding object - GETID3_ASF_Padding_Object
 973                      // Object Size                  QWORD        64              // size of Padding object, including 24 bytes of ASF Padding Object header
 974                      // Padding Data                 BYTESTREAM   variable        // ignore
 975  
 976                      // shortcut
 977                      $thisfile_asf['padding_object'] = array();
 978                      $thisfile_asf_paddingobject     = &$thisfile_asf['padding_object'];
 979  
 980                      $thisfile_asf_paddingobject['offset']                    = $NextObjectOffset + $offset;
 981                      $thisfile_asf_paddingobject['objectid']                  = $NextObjectGUID;
 982                      $thisfile_asf_paddingobject['objectid_guid']             = $NextObjectGUIDtext;
 983                      $thisfile_asf_paddingobject['objectsize']                = $NextObjectSize;
 984                      $thisfile_asf_paddingobject['padding_length']            = $thisfile_asf_paddingobject['objectsize'] - 16 - 8;
 985                      $thisfile_asf_paddingobject['padding']                   = substr($ASFHeaderData, $offset, $thisfile_asf_paddingobject['padding_length']);
 986                      $offset += ($NextObjectSize - 16 - 8);
 987                      break;
 988  
 989                  case GETID3_ASF_Extended_Content_Encryption_Object:
 990                  case GETID3_ASF_Content_Encryption_Object:
 991                      // WMA DRM - just ignore
 992                      $offset += ($NextObjectSize - 16 - 8);
 993                      break;
 994  
 995                  default:
 996                      // Implementations shall ignore any standard or non-standard object that they do not know how to handle.
 997                      if ($this->GUIDname($NextObjectGUIDtext)) {
 998                          $this->warning('unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8));
 999                      } else {
1000                          $this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8));
1001                      }
1002                      $offset += ($NextObjectSize - 16 - 8);
1003                      break;
1004              }
1005          }
1006          if (isset($thisfile_asf_streambitratepropertiesobject['bitrate_records_count'])) {
1007              $ASFbitrateAudio = 0;
1008              $ASFbitrateVideo = 0;
1009              for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitratepropertiesobject['bitrate_records_count']; $BitrateRecordsCounter++) {
1010                  if (isset($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter])) {
1011                      switch ($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter]['type_raw']) {
1012                          case 1:
1013                              $ASFbitrateVideo += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
1014                              break;
1015  
1016                          case 2:
1017                              $ASFbitrateAudio += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
1018                              break;
1019  
1020                          default:
1021                              // do nothing
1022                              break;
1023                      }
1024                  }
1025              }
1026              if ($ASFbitrateAudio > 0) {
1027                  $thisfile_audio['bitrate'] = $ASFbitrateAudio;
1028              }
1029              if ($ASFbitrateVideo > 0) {
1030                  $thisfile_video['bitrate'] = $ASFbitrateVideo;
1031              }
1032          }
1033          if (isset($thisfile_asf['stream_properties_object']) && is_array($thisfile_asf['stream_properties_object'])) {
1034  
1035              $thisfile_audio['bitrate'] = 0;
1036              $thisfile_video['bitrate'] = 0;
1037  
1038              foreach ($thisfile_asf['stream_properties_object'] as $streamnumber => $streamdata) {
1039  
1040                  switch ($streamdata['stream_type']) {
1041                      case GETID3_ASF_Audio_Media:
1042                          // Field Name                   Field Type   Size (bits)
1043                          // Codec ID / Format Tag        WORD         16              // unique ID of audio codec - defined as wFormatTag field of WAVEFORMATEX structure
1044                          // Number of Channels           WORD         16              // number of channels of audio - defined as nChannels field of WAVEFORMATEX structure
1045                          // Samples Per Second           DWORD        32              // in Hertz - defined as nSamplesPerSec field of WAVEFORMATEX structure
1046                          // Average number of Bytes/sec  DWORD        32              // bytes/sec of audio stream  - defined as nAvgBytesPerSec field of WAVEFORMATEX structure
1047                          // Block Alignment              WORD         16              // block size in bytes of audio codec - defined as nBlockAlign field of WAVEFORMATEX structure
1048                          // Bits per sample              WORD         16              // bits per sample of mono data. set to zero for variable bitrate codecs. defined as wBitsPerSample field of WAVEFORMATEX structure
1049                          // Codec Specific Data Size     WORD         16              // size in bytes of Codec Specific Data buffer - defined as cbSize field of WAVEFORMATEX structure
1050                          // Codec Specific Data          BYTESTREAM   variable        // array of codec-specific data bytes
1051  
1052                          // shortcut
1053                          $thisfile_asf['audio_media'][$streamnumber] = array();
1054                          $thisfile_asf_audiomedia_currentstream      = &$thisfile_asf['audio_media'][$streamnumber];
1055  
1056                          $audiomediaoffset = 0;
1057  
1058                          $thisfile_asf_audiomedia_currentstream = getid3_riff::parseWAVEFORMATex(substr($streamdata['type_specific_data'], $audiomediaoffset, 16));
1059                          $audiomediaoffset += 16;
1060  
1061                          $thisfile_audio['lossless'] = false;
1062                          switch ($thisfile_asf_audiomedia_currentstream['raw']['wFormatTag']) {
1063                              case 0x0001: // PCM
1064                              case 0x0163: // WMA9 Lossless
1065                                  $thisfile_audio['lossless'] = true;
1066                                  break;
1067                          }
1068  
1069                          if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) { // @phpstan-ignore-line
1070                              foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) {
1071                                  if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) {
1072                                      $thisfile_asf_audiomedia_currentstream['bitrate'] = $dataarray['bitrate'];
1073                                      $thisfile_audio['bitrate'] += $dataarray['bitrate'];
1074                                      break;
1075                                  }
1076                              }
1077                          } else {
1078                              if (!empty($thisfile_asf_audiomedia_currentstream['bytes_sec'])) {
1079                                  $thisfile_audio['bitrate'] += $thisfile_asf_audiomedia_currentstream['bytes_sec'] * 8;
1080                              } elseif (!empty($thisfile_asf_audiomedia_currentstream['bitrate'])) {
1081                                  $thisfile_audio['bitrate'] += $thisfile_asf_audiomedia_currentstream['bitrate'];
1082                              }
1083                          }
1084                          $thisfile_audio['streams'][$streamnumber]                = $thisfile_asf_audiomedia_currentstream;
1085                          $thisfile_audio['streams'][$streamnumber]['wformattag']  = $thisfile_asf_audiomedia_currentstream['raw']['wFormatTag'];
1086                          $thisfile_audio['streams'][$streamnumber]['lossless']    = $thisfile_audio['lossless'];
1087                          $thisfile_audio['streams'][$streamnumber]['bitrate']     = $thisfile_audio['bitrate'];
1088                          $thisfile_audio['streams'][$streamnumber]['dataformat']  = 'wma';
1089                          unset($thisfile_audio['streams'][$streamnumber]['raw']);
1090  
1091                          $thisfile_asf_audiomedia_currentstream['codec_data_size'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $audiomediaoffset, 2));
1092                          $audiomediaoffset += 2;
1093                          $thisfile_asf_audiomedia_currentstream['codec_data']      = substr($streamdata['type_specific_data'], $audiomediaoffset, $thisfile_asf_audiomedia_currentstream['codec_data_size']);
1094                          $audiomediaoffset += $thisfile_asf_audiomedia_currentstream['codec_data_size'];
1095  
1096                          break;
1097  
1098                      case GETID3_ASF_Video_Media:
1099                          // Field Name                   Field Type   Size (bits)
1100                          // Encoded Image Width          DWORD        32              // width of image in pixels
1101                          // Encoded Image Height         DWORD        32              // height of image in pixels
1102                          // Reserved Flags               BYTE         8               // hardcoded: 0x02
1103                          // Format Data Size             WORD         16              // size of Format Data field in bytes
1104                          // Format Data                  array of:    variable        //
1105                          // * Format Data Size           DWORD        32              // number of bytes in Format Data field, in bytes - defined as biSize field of BITMAPINFOHEADER structure
1106                          // * Image Width                LONG         32              // width of encoded image in pixels - defined as biWidth field of BITMAPINFOHEADER structure
1107                          // * Image Height               LONG         32              // height of encoded image in pixels - defined as biHeight field of BITMAPINFOHEADER structure
1108                          // * Reserved                   WORD         16              // hardcoded: 0x0001 - defined as biPlanes field of BITMAPINFOHEADER structure
1109                          // * Bits Per Pixel Count       WORD         16              // bits per pixel - defined as biBitCount field of BITMAPINFOHEADER structure
1110                          // * Compression ID             FOURCC       32              // fourcc of video codec - defined as biCompression field of BITMAPINFOHEADER structure
1111                          // * Image Size                 DWORD        32              // image size in bytes - defined as biSizeImage field of BITMAPINFOHEADER structure
1112                          // * Horizontal Pixels / Meter  DWORD        32              // horizontal resolution of target device in pixels per meter - defined as biXPelsPerMeter field of BITMAPINFOHEADER structure
1113                          // * Vertical Pixels / Meter    DWORD        32              // vertical resolution of target device in pixels per meter - defined as biYPelsPerMeter field of BITMAPINFOHEADER structure
1114                          // * Colors Used Count          DWORD        32              // number of color indexes in the color table that are actually used - defined as biClrUsed field of BITMAPINFOHEADER structure
1115                          // * Important Colors Count     DWORD        32              // number of color index required for displaying bitmap. if zero, all colors are required. defined as biClrImportant field of BITMAPINFOHEADER structure
1116                          // * Codec Specific Data        BYTESTREAM   variable        // array of codec-specific data bytes
1117  
1118                          // shortcut
1119                          $thisfile_asf['video_media'][$streamnumber] = array();
1120                          $thisfile_asf_videomedia_currentstream      = &$thisfile_asf['video_media'][$streamnumber];
1121  
1122                          $videomediaoffset = 0;
1123                          $thisfile_asf_videomedia_currentstream['image_width']                     = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4));
1124                          $videomediaoffset += 4;
1125                          $thisfile_asf_videomedia_currentstream['image_height']                    = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4));
1126                          $videomediaoffset += 4;
1127                          $thisfile_asf_videomedia_currentstream['flags']                           = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 1));
1128                          $videomediaoffset += 1;
1129                          $thisfile_asf_videomedia_currentstream['format_data_size']                = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 2));
1130                          $videomediaoffset += 2;
1131                          $thisfile_asf_videomedia_currentstream['format_data']['format_data_size'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4));
1132                          $videomediaoffset += 4;
1133                          $thisfile_asf_videomedia_currentstream['format_data']['image_width']      = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4));
1134                          $videomediaoffset += 4;
1135                          $thisfile_asf_videomedia_currentstream['format_data']['image_height']     = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4));
1136                          $videomediaoffset += 4;
1137                          $thisfile_asf_videomedia_currentstream['format_data']['reserved']         = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 2));
1138                          $videomediaoffset += 2;
1139                          $thisfile_asf_videomedia_currentstream['format_data']['bits_per_pixel']   = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 2));
1140                          $videomediaoffset += 2;
1141                          $thisfile_asf_videomedia_currentstream['format_data']['codec_fourcc']     = substr($streamdata['type_specific_data'], $videomediaoffset, 4);
1142                          $videomediaoffset += 4;
1143                          $thisfile_asf_videomedia_currentstream['format_data']['image_size']       = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4));
1144                          $videomediaoffset += 4;
1145                          $thisfile_asf_videomedia_currentstream['format_data']['horizontal_pels']  = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4));
1146                          $videomediaoffset += 4;
1147                          $thisfile_asf_videomedia_currentstream['format_data']['vertical_pels']    = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4));
1148                          $videomediaoffset += 4;
1149                          $thisfile_asf_videomedia_currentstream['format_data']['colors_used']      = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4));
1150                          $videomediaoffset += 4;
1151                          $thisfile_asf_videomedia_currentstream['format_data']['colors_important'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4));
1152                          $videomediaoffset += 4;
1153                          $thisfile_asf_videomedia_currentstream['format_data']['codec_data']       = substr($streamdata['type_specific_data'], $videomediaoffset);
1154  
1155                          if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) { // @phpstan-ignore-line
1156                              foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) {
1157                                  if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) {
1158                                      $thisfile_asf_videomedia_currentstream['bitrate'] = $dataarray['bitrate'];
1159                                      $thisfile_video['streams'][$streamnumber]['bitrate'] = $dataarray['bitrate'];
1160                                      $thisfile_video['bitrate'] += $dataarray['bitrate'];
1161                                      break;
1162                                  }
1163                              }
1164                          }
1165  
1166                          $thisfile_asf_videomedia_currentstream['format_data']['codec'] = getid3_riff::fourccLookup($thisfile_asf_videomedia_currentstream['format_data']['codec_fourcc']);
1167  
1168                          $thisfile_video['streams'][$streamnumber]['fourcc']          = $thisfile_asf_videomedia_currentstream['format_data']['codec_fourcc'];
1169                          $thisfile_video['streams'][$streamnumber]['codec']           = $thisfile_asf_videomedia_currentstream['format_data']['codec'];
1170                          $thisfile_video['streams'][$streamnumber]['resolution_x']    = $thisfile_asf_videomedia_currentstream['image_width'];
1171                          $thisfile_video['streams'][$streamnumber]['resolution_y']    = $thisfile_asf_videomedia_currentstream['image_height'];
1172                          $thisfile_video['streams'][$streamnumber]['bits_per_sample'] = $thisfile_asf_videomedia_currentstream['format_data']['bits_per_pixel'];
1173                          break;
1174  
1175                      default:
1176                          break;
1177                  }
1178              }
1179          }
1180  
1181          while ($this->ftell() < $info['avdataend']) {
1182              $NextObjectDataHeader = $this->fread(24);
1183              $offset = 0;
1184              $NextObjectGUID = substr($NextObjectDataHeader, 0, 16);
1185              $offset += 16;
1186              $NextObjectGUIDtext = $this->BytestringToGUID($NextObjectGUID);
1187              $NextObjectSize = getid3_lib::LittleEndian2Int(substr($NextObjectDataHeader, $offset, 8));
1188              $offset += 8;
1189  
1190              switch ($NextObjectGUID) {
1191                  case GETID3_ASF_Data_Object:
1192                      // Data Object: (mandatory, one only)
1193                      // Field Name                       Field Type   Size (bits)
1194                      // Object ID                        GUID         128             // GUID for Data object - GETID3_ASF_Data_Object
1195                      // Object Size                      QWORD        64              // size of Data object, including 50 bytes of Data Object header. may be 0 if FilePropertiesObject.BroadcastFlag == 1
1196                      // File ID                          GUID         128             // unique identifier. identical to File ID field in Header Object
1197                      // Total Data Packets               QWORD        64              // number of Data Packet entries in Data Object. invalid if FilePropertiesObject.BroadcastFlag == 1
1198                      // Reserved                         WORD         16              // hardcoded: 0x0101
1199  
1200                      // shortcut
1201                      $thisfile_asf['data_object'] = array();
1202                      $thisfile_asf_dataobject     = &$thisfile_asf['data_object'];
1203  
1204                      $DataObjectData = $NextObjectDataHeader.$this->fread(50 - 24);
1205                      $offset = 24;
1206  
1207                      $thisfile_asf_dataobject['objectid']           = $NextObjectGUID;
1208                      $thisfile_asf_dataobject['objectid_guid']      = $NextObjectGUIDtext;
1209                      $thisfile_asf_dataobject['objectsize']         = $NextObjectSize;
1210  
1211                      $thisfile_asf_dataobject['fileid']             = substr($DataObjectData, $offset, 16);
1212                      $offset += 16;
1213                      $thisfile_asf_dataobject['fileid_guid']        = $this->BytestringToGUID($thisfile_asf_dataobject['fileid']);
1214                      $thisfile_asf_dataobject['total_data_packets'] = getid3_lib::LittleEndian2Int(substr($DataObjectData, $offset, 8));
1215                      $offset += 8;
1216                      $thisfile_asf_dataobject['reserved']           = getid3_lib::LittleEndian2Int(substr($DataObjectData, $offset, 2));
1217                      $offset += 2;
1218                      if ($thisfile_asf_dataobject['reserved'] != 0x0101) {
1219                          $this->warning('data_object.reserved (0x'.sprintf('%04X', $thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"');
1220                          //return false;
1221                          break;
1222                      }
1223  
1224                      // Data Packets                     array of:    variable        //
1225                      // * Error Correction Flags         BYTE         8               //
1226                      // * * Error Correction Data Length bits         4               // if Error Correction Length Type == 00, size of Error Correction Data in bytes, else hardcoded: 0000
1227                      // * * Opaque Data Present          bits         1               //
1228                      // * * Error Correction Length Type bits         2               // number of bits for size of the error correction data. hardcoded: 00
1229                      // * * Error Correction Present     bits         1               // If set, use Opaque Data Packet structure, else use Payload structure
1230                      // * Error Correction Data
1231  
1232                      $info['avdataoffset'] = $this->ftell();
1233                      $this->fseek(($thisfile_asf_dataobject['objectsize'] - 50), SEEK_CUR); // skip actual audio/video data
1234                      $info['avdataend'] = $this->ftell();
1235                      break;
1236  
1237                  case GETID3_ASF_Simple_Index_Object:
1238                      // Simple Index Object: (optional, recommended, one per video stream)
1239                      // Field Name                       Field Type   Size (bits)
1240                      // Object ID                        GUID         128             // GUID for Simple Index object - GETID3_ASF_Data_Object
1241                      // Object Size                      QWORD        64              // size of Simple Index object, including 56 bytes of Simple Index Object header
1242                      // File ID                          GUID         128             // unique identifier. may be zero or identical to File ID field in Data Object and Header Object
1243                      // Index Entry Time Interval        QWORD        64              // interval between index entries in 100-nanosecond units
1244                      // Maximum Packet Count             DWORD        32              // maximum packet count for all index entries
1245                      // Index Entries Count              DWORD        32              // number of Index Entries structures
1246                      // Index Entries                    array of:    variable        //
1247                      // * Packet Number                  DWORD        32              // number of the Data Packet associated with this index entry
1248                      // * Packet Count                   WORD         16              // number of Data Packets to sent at this index entry
1249  
1250                      // shortcut
1251                      $thisfile_asf['simple_index_object'] = array();
1252                      $thisfile_asf_simpleindexobject      = &$thisfile_asf['simple_index_object'];
1253  
1254                      $SimpleIndexObjectData = $NextObjectDataHeader.$this->fread(56 - 24);
1255                      $offset = 24;
1256  
1257                      $thisfile_asf_simpleindexobject['objectid']                  = $NextObjectGUID;
1258                      $thisfile_asf_simpleindexobject['objectid_guid']             = $NextObjectGUIDtext;
1259                      $thisfile_asf_simpleindexobject['objectsize']                = $NextObjectSize;
1260  
1261                      $thisfile_asf_simpleindexobject['fileid']                    =                  substr($SimpleIndexObjectData, $offset, 16);
1262                      $offset += 16;
1263                      $thisfile_asf_simpleindexobject['fileid_guid']               = $this->BytestringToGUID($thisfile_asf_simpleindexobject['fileid']);
1264                      $thisfile_asf_simpleindexobject['index_entry_time_interval'] = getid3_lib::LittleEndian2Int(substr($SimpleIndexObjectData, $offset, 8));
1265                      $offset += 8;
1266                      $thisfile_asf_simpleindexobject['maximum_packet_count']      = getid3_lib::LittleEndian2Int(substr($SimpleIndexObjectData, $offset, 4));
1267                      $offset += 4;
1268                      $thisfile_asf_simpleindexobject['index_entries_count']       = getid3_lib::LittleEndian2Int(substr($SimpleIndexObjectData, $offset, 4));
1269                      $offset += 4;
1270  
1271                      $IndexEntriesData = $SimpleIndexObjectData.$this->fread(6 * $thisfile_asf_simpleindexobject['index_entries_count']);
1272                      for ($IndexEntriesCounter = 0; $IndexEntriesCounter < $thisfile_asf_simpleindexobject['index_entries_count']; $IndexEntriesCounter++) {
1273                          $thisfile_asf_simpleindexobject['index_entries'][$IndexEntriesCounter]['packet_number'] = getid3_lib::LittleEndian2Int(substr($IndexEntriesData, $offset, 4));
1274                          $offset += 4;
1275                          $thisfile_asf_simpleindexobject['index_entries'][$IndexEntriesCounter]['packet_count']  = getid3_lib::LittleEndian2Int(substr($IndexEntriesData, $offset, 4));
1276                          $offset += 2;
1277                      }
1278  
1279                      break;
1280  
1281                  case GETID3_ASF_Index_Object:
1282                      // 6.2 ASF top-level Index Object (optional but recommended when appropriate, 0 or 1)
1283                      // Field Name                       Field Type   Size (bits)
1284                      // Object ID                        GUID         128             // GUID for the Index Object - GETID3_ASF_Index_Object
1285                      // Object Size                      QWORD        64              // Specifies the size, in bytes, of the Index Object, including at least 34 bytes of Index Object header
1286                      // Index Entry Time Interval        DWORD        32              // Specifies the time interval between each index entry in ms.
1287                      // Index Specifiers Count           WORD         16              // Specifies the number of Index Specifiers structures in this Index Object.
1288                      // Index Blocks Count               DWORD        32              // Specifies the number of Index Blocks structures in this Index Object.
1289  
1290                      // Index Entry Time Interval        DWORD        32              // Specifies the time interval between index entries in milliseconds.  This value cannot be 0.
1291                      // Index Specifiers Count           WORD         16              // Specifies the number of entries in the Index Specifiers list.  Valid values are 1 and greater.
1292                      // Index Specifiers                 array of:    varies          //
1293                      // * Stream Number                  WORD         16              // Specifies the stream number that the Index Specifiers refer to. Valid values are between 1 and 127.
1294                      // * Index Type                     WORD         16              // Specifies Index Type values as follows:
1295                                                                                      //   1 = Nearest Past Data Packet - indexes point to the data packet whose presentation time is closest to the index entry time.
1296                                                                                      //   2 = Nearest Past Media Object - indexes point to the closest data packet containing an entire object or first fragment of an object.
1297                                                                                      //   3 = Nearest Past Cleanpoint. - indexes point to the closest data packet containing an entire object (or first fragment of an object) that has the Cleanpoint Flag set.
1298                                                                                      //   Nearest Past Cleanpoint is the most common type of index.
1299                      // Index Entry Count                DWORD        32              // Specifies the number of Index Entries in the block.
1300                      // * Block Positions                QWORD        varies          // Specifies a list of byte offsets of the beginnings of the blocks relative to the beginning of the first Data Packet (i.e., the beginning of the Data Object + 50 bytes). The number of entries in this list is specified by the value of the Index Specifiers Count field. The order of those byte offsets is tied to the order in which Index Specifiers are listed.
1301                      // * Index Entries                  array of:    varies          //
1302                      // * * Offsets                      DWORD        varies          // An offset value of 0xffffffff indicates an invalid offset value
1303  
1304                      // shortcut
1305                      $thisfile_asf['asf_index_object'] = array();
1306                      $thisfile_asf_asfindexobject      = &$thisfile_asf['asf_index_object'];
1307  
1308                      $ASFIndexObjectData = $NextObjectDataHeader.$this->fread(34 - 24);
1309                      $offset = 24;
1310  
1311                      $thisfile_asf_asfindexobject['objectid']                  = $NextObjectGUID;
1312                      $thisfile_asf_asfindexobject['objectid_guid']             = $NextObjectGUIDtext;
1313                      $thisfile_asf_asfindexobject['objectsize']                = $NextObjectSize;
1314  
1315                      $thisfile_asf_asfindexobject['entry_time_interval']       = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4));
1316                      $offset += 4;
1317                      $thisfile_asf_asfindexobject['index_specifiers_count']    = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 2));
1318                      $offset += 2;
1319                      $thisfile_asf_asfindexobject['index_blocks_count']        = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4));
1320                      $offset += 4;
1321  
1322                      $ASFIndexObjectData .= $this->fread(4 * $thisfile_asf_asfindexobject['index_specifiers_count']);
1323                      for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) {
1324                          $IndexSpecifierStreamNumber = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 2));
1325                          $offset += 2;
1326                          $thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['stream_number']   = $IndexSpecifierStreamNumber;
1327                          $thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['index_type']      = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 2));
1328                          $offset += 2;
1329                          $thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['index_type_text'] = $this->ASFIndexObjectIndexTypeLookup($thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['index_type']);
1330                      }
1331  
1332                      $ASFIndexObjectData .= $this->fread(4);
1333                      $thisfile_asf_asfindexobject['index_entry_count'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4));
1334                      $offset += 4;
1335  
1336                      $ASFIndexObjectData .= $this->fread(8 * $thisfile_asf_asfindexobject['index_specifiers_count']);
1337                      for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) {
1338                          $thisfile_asf_asfindexobject['block_positions'][$IndexSpecifiersCounter] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 8));
1339                          $offset += 8;
1340                      }
1341  
1342                      $ASFIndexObjectData .= $this->fread(4 * $thisfile_asf_asfindexobject['index_specifiers_count'] * $thisfile_asf_asfindexobject['index_entry_count']);
1343                      for ($IndexEntryCounter = 0; $IndexEntryCounter < $thisfile_asf_asfindexobject['index_entry_count']; $IndexEntryCounter++) {
1344                          for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) {
1345                              $thisfile_asf_asfindexobject['offsets'][$IndexSpecifiersCounter][$IndexEntryCounter] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4));
1346                              $offset += 4;
1347                          }
1348                      }
1349                      break;
1350  
1351  
1352                  default:
1353                      // Implementations shall ignore any standard or non-standard object that they do not know how to handle.
1354                      if ($this->GUIDname($NextObjectGUIDtext)) {
1355                          $this->warning('unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF body at offset '.($offset - 16 - 8));
1356                      } else {
1357                          $this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.($this->ftell() - 16 - 8));
1358                      }
1359                      $this->fseek(($NextObjectSize - 16 - 8), SEEK_CUR);
1360                      break;
1361              }
1362          }
1363  
1364          if (isset($thisfile_asf_codeclistobject['codec_entries']) && is_array($thisfile_asf_codeclistobject['codec_entries'])) {
1365              foreach ($thisfile_asf_codeclistobject['codec_entries'] as $streamnumber => $streamdata) {
1366                  switch ($streamdata['information']) {
1367                      case 'WMV1':
1368                      case 'WMV2':
1369                      case 'WMV3':
1370                      case 'MSS1':
1371                      case 'MSS2':
1372                      case 'WMVA':
1373                      case 'WVC1':
1374                      case 'WMVP':
1375                      case 'WVP2':
1376                          $thisfile_video['dataformat'] = 'wmv';
1377                          $info['mime_type'] = 'video/x-ms-wmv';
1378                          break;
1379  
1380                      case 'MP42':
1381                      case 'MP43':
1382                      case 'MP4S':
1383                      case 'mp4s':
1384                          $thisfile_video['dataformat'] = 'asf';
1385                          $info['mime_type'] = 'video/x-ms-asf';
1386                          break;
1387  
1388                      default:
1389                          switch ($streamdata['type_raw']) {
1390                              case 1:
1391                                  if (strstr($this->TrimConvert($streamdata['name']), 'Windows Media')) {
1392                                      $thisfile_video['dataformat'] = 'wmv';
1393                                      if ($info['mime_type'] == 'video/x-ms-asf') {
1394                                          $info['mime_type'] = 'video/x-ms-wmv';
1395                                      }
1396                                  }
1397                                  break;
1398  
1399                              case 2:
1400                                  if (strstr($this->TrimConvert($streamdata['name']), 'Windows Media')) {
1401                                      $thisfile_audio['dataformat'] = 'wma';
1402                                      if ($info['mime_type'] == 'video/x-ms-asf') {
1403                                          $info['mime_type'] = 'audio/x-ms-wma';
1404                                      }
1405                                  }
1406                                  break;
1407  
1408                          }
1409                          break;
1410                  }
1411              }
1412          }
1413  
1414          switch (isset($thisfile_audio['codec']) ? $thisfile_audio['codec'] : '') {
1415              case 'MPEG Layer-3':
1416                  $thisfile_audio['dataformat'] = 'mp3';
1417                  break;
1418  
1419              default:
1420                  break;
1421          }
1422  
1423          if (isset($thisfile_asf_codeclistobject['codec_entries'])) {
1424              foreach ($thisfile_asf_codeclistobject['codec_entries'] as $streamnumber => $streamdata) {
1425                  switch ($streamdata['type_raw']) {
1426  
1427                      case 1: // video
1428                          $thisfile_video['encoder'] = $this->TrimConvert($thisfile_asf_codeclistobject['codec_entries'][$streamnumber]['name']);
1429                          break;
1430  
1431                      case 2: // audio
1432                          $thisfile_audio['encoder'] = $this->TrimConvert($thisfile_asf_codeclistobject['codec_entries'][$streamnumber]['name']);
1433  
1434                          // AH 2003-10-01
1435                          $thisfile_audio['encoder_options'] = $this->TrimConvert($thisfile_asf_codeclistobject['codec_entries'][0]['description']);
1436  
1437                          $thisfile_audio['codec']   = $thisfile_audio['encoder'];
1438                          break;
1439  
1440                      default:
1441                          $this->warning('Unknown streamtype: [codec_list_object][codec_entries]['.$streamnumber.'][type_raw] == '.$streamdata['type_raw']);
1442                          break;
1443  
1444                  }
1445              }
1446          }
1447  
1448          if (isset($info['audio'])) {
1449              $thisfile_audio['lossless']           = (isset($thisfile_audio['lossless'])           ? $thisfile_audio['lossless']           : false);
1450              $thisfile_audio['dataformat']         = (!empty($thisfile_audio['dataformat'])        ? $thisfile_audio['dataformat']         : 'asf');
1451          }
1452          if (!empty($thisfile_video['dataformat'])) {
1453              $thisfile_video['lossless']           = (isset($thisfile_audio['lossless'])           ? $thisfile_audio['lossless']           : false);
1454              $thisfile_video['pixel_aspect_ratio'] = (isset($thisfile_audio['pixel_aspect_ratio']) ? $thisfile_audio['pixel_aspect_ratio'] : (float) 1);
1455              $thisfile_video['dataformat']         = (!empty($thisfile_video['dataformat'])        ? $thisfile_video['dataformat']         : 'asf');
1456          }
1457          if (!empty($thisfile_video['streams'])) {
1458              $thisfile_video['resolution_x'] = 0;
1459              $thisfile_video['resolution_y'] = 0;
1460              foreach ($thisfile_video['streams'] as $key => $valuearray) {
1461                  if (($valuearray['resolution_x'] > $thisfile_video['resolution_x']) || ($valuearray['resolution_y'] > $thisfile_video['resolution_y'])) {
1462                      $thisfile_video['resolution_x'] = $valuearray['resolution_x'];
1463                      $thisfile_video['resolution_y'] = $valuearray['resolution_y'];
1464                  }
1465              }
1466          }
1467          $info['bitrate'] = 0 + (isset($thisfile_audio['bitrate']) ? $thisfile_audio['bitrate'] : 0) + (isset($thisfile_video['bitrate']) ? $thisfile_video['bitrate'] : 0);
1468  
1469          if ((!isset($info['playtime_seconds']) || ($info['playtime_seconds'] <= 0)) && ($info['bitrate'] > 0)) {
1470              $info['playtime_seconds'] = ($info['filesize'] - $info['avdataoffset']) / ($info['bitrate'] / 8);
1471          }
1472  
1473          return true;
1474      }
1475  
1476      /**
1477       * @param int $CodecListType
1478       *
1479       * @return string
1480       */
1481  	public static function codecListObjectTypeLookup($CodecListType) {
1482          static $lookup = array(
1483              0x0001 => 'Video Codec',
1484              0x0002 => 'Audio Codec',
1485              0xFFFF => 'Unknown Codec'
1486          );
1487  
1488          return (isset($lookup[$CodecListType]) ? $lookup[$CodecListType] : 'Invalid Codec Type');
1489      }
1490  
1491      /**
1492       * @return array
1493       */
1494  	public static function KnownGUIDs() {
1495          static $GUIDarray = array(
1496              'GETID3_ASF_Extended_Stream_Properties_Object'   => '14E6A5CB-C672-4332-8399-A96952065B5A',
1497              'GETID3_ASF_Padding_Object'                      => '1806D474-CADF-4509-A4BA-9AABCB96AAE8',
1498              'GETID3_ASF_Payload_Ext_Syst_Pixel_Aspect_Ratio' => '1B1EE554-F9EA-4BC8-821A-376B74E4C4B8',
1499              'GETID3_ASF_Script_Command_Object'               => '1EFB1A30-0B62-11D0-A39B-00A0C90348F6',
1500              'GETID3_ASF_No_Error_Correction'                 => '20FB5700-5B55-11CF-A8FD-00805F5C442B',
1501              'GETID3_ASF_Content_Branding_Object'             => '2211B3FA-BD23-11D2-B4B7-00A0C955FC6E',
1502              'GETID3_ASF_Content_Encryption_Object'           => '2211B3FB-BD23-11D2-B4B7-00A0C955FC6E',
1503              'GETID3_ASF_Digital_Signature_Object'            => '2211B3FC-BD23-11D2-B4B7-00A0C955FC6E',
1504              'GETID3_ASF_Extended_Content_Encryption_Object'  => '298AE614-2622-4C17-B935-DAE07EE9289C',
1505              'GETID3_ASF_Simple_Index_Object'                 => '33000890-E5B1-11CF-89F4-00A0C90349CB',
1506              'GETID3_ASF_Degradable_JPEG_Media'               => '35907DE0-E415-11CF-A917-00805F5C442B',
1507              'GETID3_ASF_Payload_Extension_System_Timecode'   => '399595EC-8667-4E2D-8FDB-98814CE76C1E',
1508              'GETID3_ASF_Binary_Media'                        => '3AFB65E2-47EF-40F2-AC2C-70A90D71D343',
1509              'GETID3_ASF_Timecode_Index_Object'               => '3CB73FD0-0C4A-4803-953D-EDF7B6228F0C',
1510              'GETID3_ASF_Metadata_Library_Object'             => '44231C94-9498-49D1-A141-1D134E457054',
1511              'GETID3_ASF_Reserved_3'                          => '4B1ACBE3-100B-11D0-A39B-00A0C90348F6',
1512              'GETID3_ASF_Reserved_4'                          => '4CFEDB20-75F6-11CF-9C0F-00A0C90349CB',
1513              'GETID3_ASF_Command_Media'                       => '59DACFC0-59E6-11D0-A3AC-00A0C90348F6',
1514              'GETID3_ASF_Header_Extension_Object'             => '5FBF03B5-A92E-11CF-8EE3-00C00C205365',
1515              'GETID3_ASF_Media_Object_Index_Parameters_Obj'   => '6B203BAD-3F11-4E84-ACA8-D7613DE2CFA7',
1516              'GETID3_ASF_Header_Object'                       => '75B22630-668E-11CF-A6D9-00AA0062CE6C',
1517              'GETID3_ASF_Content_Description_Object'          => '75B22633-668E-11CF-A6D9-00AA0062CE6C',
1518              'GETID3_ASF_Error_Correction_Object'             => '75B22635-668E-11CF-A6D9-00AA0062CE6C',
1519              'GETID3_ASF_Data_Object'                         => '75B22636-668E-11CF-A6D9-00AA0062CE6C',
1520              'GETID3_ASF_Web_Stream_Media_Subtype'            => '776257D4-C627-41CB-8F81-7AC7FF1C40CC',
1521              'GETID3_ASF_Stream_Bitrate_Properties_Object'    => '7BF875CE-468D-11D1-8D82-006097C9A2B2',
1522              'GETID3_ASF_Language_List_Object'                => '7C4346A9-EFE0-4BFC-B229-393EDE415C85',
1523              'GETID3_ASF_Codec_List_Object'                   => '86D15240-311D-11D0-A3A4-00A0C90348F6',
1524              'GETID3_ASF_Reserved_2'                          => '86D15241-311D-11D0-A3A4-00A0C90348F6',
1525              'GETID3_ASF_File_Properties_Object'              => '8CABDCA1-A947-11CF-8EE4-00C00C205365',
1526              'GETID3_ASF_File_Transfer_Media'                 => '91BD222C-F21C-497A-8B6D-5AA86BFC0185',
1527              'GETID3_ASF_Old_RTP_Extension_Data'              => '96800C63-4C94-11D1-837B-0080C7A37F95',
1528              'GETID3_ASF_Advanced_Mutual_Exclusion_Object'    => 'A08649CF-4775-4670-8A16-6E35357566CD',
1529              'GETID3_ASF_Bandwidth_Sharing_Object'            => 'A69609E6-517B-11D2-B6AF-00C04FD908E9',
1530              'GETID3_ASF_Reserved_1'                          => 'ABD3D211-A9BA-11cf-8EE6-00C00C205365',
1531              'GETID3_ASF_Bandwidth_Sharing_Exclusive'         => 'AF6060AA-5197-11D2-B6AF-00C04FD908E9',
1532              'GETID3_ASF_Bandwidth_Sharing_Partial'           => 'AF6060AB-5197-11D2-B6AF-00C04FD908E9',
1533              'GETID3_ASF_JFIF_Media'                          => 'B61BE100-5B4E-11CF-A8FD-00805F5C442B',
1534              'GETID3_ASF_Stream_Properties_Object'            => 'B7DC0791-A9B7-11CF-8EE6-00C00C205365',
1535              'GETID3_ASF_Video_Media'                         => 'BC19EFC0-5B4D-11CF-A8FD-00805F5C442B',
1536              'GETID3_ASF_Audio_Spread'                        => 'BFC3CD50-618F-11CF-8BB2-00AA00B4E220',
1537              'GETID3_ASF_Metadata_Object'                     => 'C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA',
1538              'GETID3_ASF_Payload_Ext_Syst_Sample_Duration'    => 'C6BD9450-867F-4907-83A3-C77921B733AD',
1539              'GETID3_ASF_Group_Mutual_Exclusion_Object'       => 'D1465A40-5A79-4338-B71B-E36B8FD6C249',
1540              'GETID3_ASF_Extended_Content_Description_Object' => 'D2D0A440-E307-11D2-97F0-00A0C95EA850',
1541              'GETID3_ASF_Stream_Prioritization_Object'        => 'D4FED15B-88D3-454F-81F0-ED5C45999E24',
1542              'GETID3_ASF_Payload_Ext_System_Content_Type'     => 'D590DC20-07BC-436C-9CF7-F3BBFBF1A4DC',
1543              'GETID3_ASF_Old_File_Properties_Object'          => 'D6E229D0-35DA-11D1-9034-00A0C90349BE',
1544              'GETID3_ASF_Old_ASF_Header_Object'               => 'D6E229D1-35DA-11D1-9034-00A0C90349BE',
1545              'GETID3_ASF_Old_ASF_Data_Object'                 => 'D6E229D2-35DA-11D1-9034-00A0C90349BE',
1546              'GETID3_ASF_Index_Object'                        => 'D6E229D3-35DA-11D1-9034-00A0C90349BE',
1547              'GETID3_ASF_Old_Stream_Properties_Object'        => 'D6E229D4-35DA-11D1-9034-00A0C90349BE',
1548              'GETID3_ASF_Old_Content_Description_Object'      => 'D6E229D5-35DA-11D1-9034-00A0C90349BE',
1549              'GETID3_ASF_Old_Script_Command_Object'           => 'D6E229D6-35DA-11D1-9034-00A0C90349BE',
1550              'GETID3_ASF_Old_Marker_Object'                   => 'D6E229D7-35DA-11D1-9034-00A0C90349BE',
1551              'GETID3_ASF_Old_Component_Download_Object'       => 'D6E229D8-35DA-11D1-9034-00A0C90349BE',
1552              'GETID3_ASF_Old_Stream_Group_Object'             => 'D6E229D9-35DA-11D1-9034-00A0C90349BE',
1553              'GETID3_ASF_Old_Scalable_Object'                 => 'D6E229DA-35DA-11D1-9034-00A0C90349BE',
1554              'GETID3_ASF_Old_Prioritization_Object'           => 'D6E229DB-35DA-11D1-9034-00A0C90349BE',
1555              'GETID3_ASF_Bitrate_Mutual_Exclusion_Object'     => 'D6E229DC-35DA-11D1-9034-00A0C90349BE',
1556              'GETID3_ASF_Old_Inter_Media_Dependency_Object'   => 'D6E229DD-35DA-11D1-9034-00A0C90349BE',
1557              'GETID3_ASF_Old_Rating_Object'                   => 'D6E229DE-35DA-11D1-9034-00A0C90349BE',
1558              'GETID3_ASF_Index_Parameters_Object'             => 'D6E229DF-35DA-11D1-9034-00A0C90349BE',
1559              'GETID3_ASF_Old_Color_Table_Object'              => 'D6E229E0-35DA-11D1-9034-00A0C90349BE',
1560              'GETID3_ASF_Old_Language_List_Object'            => 'D6E229E1-35DA-11D1-9034-00A0C90349BE',
1561              'GETID3_ASF_Old_Audio_Media'                     => 'D6E229E2-35DA-11D1-9034-00A0C90349BE',
1562              'GETID3_ASF_Old_Video_Media'                     => 'D6E229E3-35DA-11D1-9034-00A0C90349BE',
1563              'GETID3_ASF_Old_Image_Media'                     => 'D6E229E4-35DA-11D1-9034-00A0C90349BE',
1564              'GETID3_ASF_Old_Timecode_Media'                  => 'D6E229E5-35DA-11D1-9034-00A0C90349BE',
1565              'GETID3_ASF_Old_Text_Media'                      => 'D6E229E6-35DA-11D1-9034-00A0C90349BE',
1566              'GETID3_ASF_Old_MIDI_Media'                      => 'D6E229E7-35DA-11D1-9034-00A0C90349BE',
1567              'GETID3_ASF_Old_Command_Media'                   => 'D6E229E8-35DA-11D1-9034-00A0C90349BE',
1568              'GETID3_ASF_Old_No_Error_Concealment'            => 'D6E229EA-35DA-11D1-9034-00A0C90349BE',
1569              'GETID3_ASF_Old_Scrambled_Audio'                 => 'D6E229EB-35DA-11D1-9034-00A0C90349BE',
1570              'GETID3_ASF_Old_No_Color_Table'                  => 'D6E229EC-35DA-11D1-9034-00A0C90349BE',
1571              'GETID3_ASF_Old_SMPTE_Time'                      => 'D6E229ED-35DA-11D1-9034-00A0C90349BE',
1572              'GETID3_ASF_Old_ASCII_Text'                      => 'D6E229EE-35DA-11D1-9034-00A0C90349BE',
1573              'GETID3_ASF_Old_Unicode_Text'                    => 'D6E229EF-35DA-11D1-9034-00A0C90349BE',
1574              'GETID3_ASF_Old_HTML_Text'                       => 'D6E229F0-35DA-11D1-9034-00A0C90349BE',
1575              'GETID3_ASF_Old_URL_Command'                     => 'D6E229F1-35DA-11D1-9034-00A0C90349BE',
1576              'GETID3_ASF_Old_Filename_Command'                => 'D6E229F2-35DA-11D1-9034-00A0C90349BE',
1577              'GETID3_ASF_Old_ACM_Codec'                       => 'D6E229F3-35DA-11D1-9034-00A0C90349BE',
1578              'GETID3_ASF_Old_VCM_Codec'                       => 'D6E229F4-35DA-11D1-9034-00A0C90349BE',
1579              'GETID3_ASF_Old_QuickTime_Codec'                 => 'D6E229F5-35DA-11D1-9034-00A0C90349BE',
1580              'GETID3_ASF_Old_DirectShow_Transform_Filter'     => 'D6E229F6-35DA-11D1-9034-00A0C90349BE',
1581              'GETID3_ASF_Old_DirectShow_Rendering_Filter'     => 'D6E229F7-35DA-11D1-9034-00A0C90349BE',
1582              'GETID3_ASF_Old_No_Enhancement'                  => 'D6E229F8-35DA-11D1-9034-00A0C90349BE',
1583              'GETID3_ASF_Old_Unknown_Enhancement_Type'        => 'D6E229F9-35DA-11D1-9034-00A0C90349BE',
1584              'GETID3_ASF_Old_Temporal_Enhancement'            => 'D6E229FA-35DA-11D1-9034-00A0C90349BE',
1585              'GETID3_ASF_Old_Spatial_Enhancement'             => 'D6E229FB-35DA-11D1-9034-00A0C90349BE',
1586              'GETID3_ASF_Old_Quality_Enhancement'             => 'D6E229FC-35DA-11D1-9034-00A0C90349BE',
1587              'GETID3_ASF_Old_Number_of_Channels_Enhancement'  => 'D6E229FD-35DA-11D1-9034-00A0C90349BE',
1588              'GETID3_ASF_Old_Frequency_Response_Enhancement'  => 'D6E229FE-35DA-11D1-9034-00A0C90349BE',
1589              'GETID3_ASF_Old_Media_Object'                    => 'D6E229FF-35DA-11D1-9034-00A0C90349BE',
1590              'GETID3_ASF_Mutex_Language'                      => 'D6E22A00-35DA-11D1-9034-00A0C90349BE',
1591              'GETID3_ASF_Mutex_Bitrate'                       => 'D6E22A01-35DA-11D1-9034-00A0C90349BE',
1592              'GETID3_ASF_Mutex_Unknown'                       => 'D6E22A02-35DA-11D1-9034-00A0C90349BE',
1593              'GETID3_ASF_Old_ASF_Placeholder_Object'          => 'D6E22A0E-35DA-11D1-9034-00A0C90349BE',
1594              'GETID3_ASF_Old_Data_Unit_Extension_Object'      => 'D6E22A0F-35DA-11D1-9034-00A0C90349BE',
1595              'GETID3_ASF_Web_Stream_Format'                   => 'DA1E6B13-8359-4050-B398-388E965BF00C',
1596              'GETID3_ASF_Payload_Ext_System_File_Name'        => 'E165EC0E-19ED-45D7-B4A7-25CBD1E28E9B',
1597              'GETID3_ASF_Marker_Object'                       => 'F487CD01-A951-11CF-8EE6-00C00C205365',
1598              'GETID3_ASF_Timecode_Index_Parameters_Object'    => 'F55E496D-9797-4B5D-8C8B-604DFE9BFB24',
1599              'GETID3_ASF_Audio_Media'                         => 'F8699E40-5B4D-11CF-A8FD-00805F5C442B',
1600              'GETID3_ASF_Media_Object_Index_Object'           => 'FEB103F8-12AD-4C64-840F-2A1D2F7AD48C',
1601              'GETID3_ASF_Alt_Extended_Content_Encryption_Obj' => 'FF889EF1-ADEE-40DA-9E71-98704BB928CE',
1602              'GETID3_ASF_Index_Placeholder_Object'            => 'D9AADE20-7C17-4F9C-BC28-8555DD98E2A2', // https://metacpan.org/dist/Audio-WMA/source/WMA.pm
1603              'GETID3_ASF_Compatibility_Object'                => '26F18B5D-4584-47EC-9F5F-0E651F0452C9', // https://metacpan.org/dist/Audio-WMA/source/WMA.pm
1604              'GETID3_ASF_Media_Object_Index_Parameters_Object'=> '6B203BAD-3F11-48E4-ACA8-D7613DE2CFA7',
1605          );
1606          return $GUIDarray;
1607      }
1608  
1609      /**
1610       * @param string $GUIDstring
1611       *
1612       * @return string|false
1613       */
1614  	public static function GUIDname($GUIDstring) {
1615          static $GUIDarray = array();
1616          if (empty($GUIDarray)) {
1617              $GUIDarray = self::KnownGUIDs();
1618          }
1619          return array_search($GUIDstring, $GUIDarray);
1620      }
1621  
1622      /**
1623       * @param int $id
1624       *
1625       * @return string
1626       */
1627  	public static function ASFIndexObjectIndexTypeLookup($id) {
1628          static $ASFIndexObjectIndexTypeLookup = array();
1629          if (empty($ASFIndexObjectIndexTypeLookup)) {
1630              $ASFIndexObjectIndexTypeLookup[1] = 'Nearest Past Data Packet';
1631              $ASFIndexObjectIndexTypeLookup[2] = 'Nearest Past Media Object';
1632              $ASFIndexObjectIndexTypeLookup[3] = 'Nearest Past Cleanpoint';
1633          }
1634          return (isset($ASFIndexObjectIndexTypeLookup[$id]) ? $ASFIndexObjectIndexTypeLookup[$id] : 'invalid');
1635      }
1636  
1637      /**
1638       * @param string $GUIDstring
1639       *
1640       * @return string
1641       */
1642  	public static function GUIDtoBytestring($GUIDstring) {
1643          // Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way:
1644          // first 4 bytes are in little-endian order
1645          // next 2 bytes are appended in little-endian order
1646          // next 2 bytes are appended in little-endian order
1647          // next 2 bytes are appended in big-endian order
1648          // next 6 bytes are appended in big-endian order
1649  
1650          // AaBbCcDd-EeFf-GgHh-IiJj-KkLlMmNnOoPp is stored as this 16-byte string:
1651          // $Dd $Cc $Bb $Aa $Ff $Ee $Hh $Gg $Ii $Jj $Kk $Ll $Mm $Nn $Oo $Pp
1652  
1653          $hexbytecharstring  = chr(hexdec(substr($GUIDstring,  6, 2)));
1654          $hexbytecharstring .= chr(hexdec(substr($GUIDstring,  4, 2)));
1655          $hexbytecharstring .= chr(hexdec(substr($GUIDstring,  2, 2)));
1656          $hexbytecharstring .= chr(hexdec(substr($GUIDstring,  0, 2)));
1657  
1658          $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 11, 2)));
1659          $hexbytecharstring .= chr(hexdec(substr($GUIDstring,  9, 2)));
1660  
1661          $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 16, 2)));
1662          $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 14, 2)));
1663  
1664          $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 19, 2)));
1665          $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 21, 2)));
1666  
1667          $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 24, 2)));
1668          $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 26, 2)));
1669          $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 28, 2)));
1670          $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 30, 2)));
1671          $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 32, 2)));
1672          $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 34, 2)));
1673  
1674          return $hexbytecharstring;
1675      }
1676  
1677      /**
1678       * @param string $Bytestring
1679       *
1680       * @return string
1681       */
1682  	public static function BytestringToGUID($Bytestring) {
1683          $GUIDstring  = str_pad(dechex(ord($Bytestring[3])),  2, '0', STR_PAD_LEFT);
1684          $GUIDstring .= str_pad(dechex(ord($Bytestring[2])),  2, '0', STR_PAD_LEFT);
1685          $GUIDstring .= str_pad(dechex(ord($Bytestring[1])),  2, '0', STR_PAD_LEFT);
1686          $GUIDstring .= str_pad(dechex(ord($Bytestring[0])),  2, '0', STR_PAD_LEFT);
1687          $GUIDstring .= '-';
1688          $GUIDstring .= str_pad(dechex(ord($Bytestring[5])),  2, '0', STR_PAD_LEFT);
1689          $GUIDstring .= str_pad(dechex(ord($Bytestring[4])),  2, '0', STR_PAD_LEFT);
1690          $GUIDstring .= '-';
1691          $GUIDstring .= str_pad(dechex(ord($Bytestring[7])),  2, '0', STR_PAD_LEFT);
1692          $GUIDstring .= str_pad(dechex(ord($Bytestring[6])),  2, '0', STR_PAD_LEFT);
1693          $GUIDstring .= '-';
1694          $GUIDstring .= str_pad(dechex(ord($Bytestring[8])),  2, '0', STR_PAD_LEFT);
1695          $GUIDstring .= str_pad(dechex(ord($Bytestring[9])),  2, '0', STR_PAD_LEFT);
1696          $GUIDstring .= '-';
1697          $GUIDstring .= str_pad(dechex(ord($Bytestring[10])), 2, '0', STR_PAD_LEFT);
1698          $GUIDstring .= str_pad(dechex(ord($Bytestring[11])), 2, '0', STR_PAD_LEFT);
1699          $GUIDstring .= str_pad(dechex(ord($Bytestring[12])), 2, '0', STR_PAD_LEFT);
1700          $GUIDstring .= str_pad(dechex(ord($Bytestring[13])), 2, '0', STR_PAD_LEFT);
1701          $GUIDstring .= str_pad(dechex(ord($Bytestring[14])), 2, '0', STR_PAD_LEFT);
1702          $GUIDstring .= str_pad(dechex(ord($Bytestring[15])), 2, '0', STR_PAD_LEFT);
1703  
1704          return strtoupper($GUIDstring);
1705      }
1706  
1707      /**
1708       * @param int  $FILETIME
1709       * @param bool $round
1710       *
1711       * @return float|int
1712       */
1713  	public static function FILETIMEtoUNIXtime($FILETIME, $round=true) {
1714          // FILETIME is a 64-bit unsigned integer representing
1715          // the number of 100-nanosecond intervals since January 1, 1601
1716          // UNIX timestamp is number of seconds since January 1, 1970
1717          // 116444736000000000 = 10000000 * 60 * 60 * 24 * 365 * 369 + 89 leap days
1718          if ($round) {
1719              return intval(round(($FILETIME - 116444736000000000) / 10000000));
1720          }
1721          return ($FILETIME - 116444736000000000) / 10000000;
1722      }
1723  
1724      /**
1725       * @param int $WMpictureType
1726       *
1727       * @return string
1728       */
1729  	public static function WMpictureTypeLookup($WMpictureType) {
1730          static $lookup = null;
1731          if ($lookup === null) {
1732              $lookup = array(
1733                  0x03 => 'Front Cover',
1734                  0x04 => 'Back Cover',
1735                  0x00 => 'User Defined',
1736                  0x05 => 'Leaflet Page',
1737                  0x06 => 'Media Label',
1738                  0x07 => 'Lead Artist',
1739                  0x08 => 'Artist',
1740                  0x09 => 'Conductor',
1741                  0x0A => 'Band',
1742                  0x0B => 'Composer',
1743                  0x0C => 'Lyricist',
1744                  0x0D => 'Recording Location',
1745                  0x0E => 'During Recording',
1746                  0x0F => 'During Performance',
1747                  0x10 => 'Video Screen Capture',
1748                  0x12 => 'Illustration',
1749                  0x13 => 'Band Logotype',
1750                  0x14 => 'Publisher Logotype'
1751              );
1752              $lookup = array_map(function($str) {
1753                  return getid3_lib::iconv_fallback('UTF-8', 'UTF-16LE', $str);
1754              }, $lookup);
1755          }
1756  
1757          return (isset($lookup[$WMpictureType]) ? $lookup[$WMpictureType] : '');
1758      }
1759  
1760      /**
1761       * @param string $asf_header_extension_object_data
1762       * @param int    $unhandled_sections
1763       *
1764       * @return array
1765       */
1766  	public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) {
1767          // https://web.archive.org/web/20140419205228/http://msdn.microsoft.com/en-us/library/bb643323.aspx
1768  
1769          $offset = 0;
1770          $objectOffset = 0;
1771          $HeaderExtensionObjectParsed = array();
1772          while ($objectOffset < strlen($asf_header_extension_object_data)) {
1773              $offset = $objectOffset;
1774              $thisObject = array();
1775  
1776              $thisObject['guid']                              =                              substr($asf_header_extension_object_data, $offset, 16);
1777              $offset += 16;
1778              $thisObject['guid_text'] = $this->BytestringToGUID($thisObject['guid']);
1779              $thisObject['guid_name'] = $this->GUIDname($thisObject['guid_text']);
1780  
1781              $thisObject['size']                              = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  8));
1782              $offset += 8;
1783              if ($thisObject['size'] <= 0) {
1784                  break;
1785              }
1786  
1787              switch ($thisObject['guid']) {
1788                  case GETID3_ASF_Extended_Stream_Properties_Object:
1789                      $thisObject['start_time']                        = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  8));
1790                      $offset += 8;
1791                      $thisObject['start_time_unix']                   = $this->FILETIMEtoUNIXtime($thisObject['start_time']);
1792  
1793                      $thisObject['end_time']                          = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  8));
1794                      $offset += 8;
1795                      $thisObject['end_time_unix']                     = $this->FILETIMEtoUNIXtime($thisObject['end_time']);
1796  
1797                      $thisObject['data_bitrate']                      = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  4));
1798                      $offset += 4;
1799  
1800                      $thisObject['buffer_size']                       = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  4));
1801                      $offset += 4;
1802  
1803                      $thisObject['initial_buffer_fullness']           = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  4));
1804                      $offset += 4;
1805  
1806                      $thisObject['alternate_data_bitrate']            = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  4));
1807                      $offset += 4;
1808  
1809                      $thisObject['alternate_buffer_size']             = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  4));
1810                      $offset += 4;
1811  
1812                      $thisObject['alternate_initial_buffer_fullness'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  4));
1813                      $offset += 4;
1814  
1815                      $thisObject['maximum_object_size']               = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  4));
1816                      $offset += 4;
1817  
1818                      $thisObject['flags_raw']                         = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  4));
1819                      $offset += 4;
1820                      $thisObject['flags']['reliable']                = (bool) $thisObject['flags_raw'] & 0x00000001;
1821                      $thisObject['flags']['seekable']                = (bool) $thisObject['flags_raw'] & 0x00000002;
1822                      $thisObject['flags']['no_cleanpoints']          = (bool) $thisObject['flags_raw'] & 0x00000004;
1823                      $thisObject['flags']['resend_live_cleanpoints'] = (bool) $thisObject['flags_raw'] & 0x00000008;
1824  
1825                      $thisObject['stream_number']                     = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1826                      $offset += 2;
1827  
1828                      $thisObject['stream_language_id_index']          = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1829                      $offset += 2;
1830  
1831                      $thisObject['average_time_per_frame']            = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  8));
1832                      $offset += 8;
1833  
1834                      $thisObject['stream_name_count']                 = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1835                      $offset += 2;
1836  
1837                      $thisObject['payload_extension_system_count']    = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1838                      $offset += 2;
1839  
1840                      for ($i = 0; $i < $thisObject['stream_name_count']; $i++) {
1841                          $streamName = array();
1842  
1843                          $streamName['language_id_index']             = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1844                          $offset += 2;
1845  
1846                          $streamName['stream_name_length']            = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1847                          $offset += 2;
1848  
1849                          $streamName['stream_name']                   =                              substr($asf_header_extension_object_data, $offset,  $streamName['stream_name_length']);
1850                          $offset += $streamName['stream_name_length'];
1851  
1852                          $thisObject['stream_names'][$i] = $streamName;
1853                      }
1854  
1855                      for ($i = 0; $i < $thisObject['payload_extension_system_count']; $i++) {
1856                          $payloadExtensionSystem = array();
1857  
1858                          $payloadExtensionSystem['extension_system_id']   =                              substr($asf_header_extension_object_data, $offset, 16);
1859                          $offset += 16;
1860                          $payloadExtensionSystem['extension_system_id_text'] = $this->BytestringToGUID($payloadExtensionSystem['extension_system_id']);
1861  
1862                          $payloadExtensionSystem['extension_system_size'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1863                          $offset += 2;
1864                          if ($payloadExtensionSystem['extension_system_size'] <= 0) {
1865                              break 2;
1866                          }
1867  
1868                          $payloadExtensionSystem['extension_system_info_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  4));
1869                          $offset += 4;
1870  
1871                          $payloadExtensionSystem['extension_system_info'] = substr($asf_header_extension_object_data, $offset,  $payloadExtensionSystem['extension_system_info_length']);
1872                          $offset += $payloadExtensionSystem['extension_system_info_length'];
1873  
1874                          $thisObject['payload_extension_systems'][$i] = $payloadExtensionSystem;
1875                      }
1876  
1877                      break;
1878  
1879                  case GETID3_ASF_Advanced_Mutual_Exclusion_Object:
1880                      $thisObject['exclusion_type']       = substr($asf_header_extension_object_data, $offset, 16);
1881                      $offset += 16;
1882                      $thisObject['exclusion_type_text']  = $this->BytestringToGUID($thisObject['exclusion_type']);
1883  
1884                      $thisObject['stream_numbers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1885                      $offset += 2;
1886  
1887                      for ($i = 0; $i < $thisObject['stream_numbers_count']; $i++) {
1888                          $thisObject['stream_numbers'][$i] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1889                          $offset += 2;
1890                      }
1891  
1892                      break;
1893  
1894                  case GETID3_ASF_Stream_Prioritization_Object:
1895                      $thisObject['priority_records_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1896                      $offset += 2;
1897  
1898                      for ($i = 0; $i < $thisObject['priority_records_count']; $i++) {
1899                          $priorityRecord = array();
1900  
1901                          $priorityRecord['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1902                          $offset += 2;
1903  
1904                          $priorityRecord['flags_raw']     = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
1905                          $offset += 2;
1906                          $priorityRecord['flags']['mandatory'] = (bool) $priorityRecord['flags_raw'] & 0x00000001;
1907  
1908                          $thisObject['priority_records'][$i] = $priorityRecord;
1909                      }
1910  
1911                      break;
1912  
1913                  case GETID3_ASF_Padding_Object:
1914                      // padding, skip it
1915                      break;
1916  
1917                  case GETID3_ASF_Metadata_Object:
1918                      $thisObject['description_record_counts'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1919                      $offset += 2;
1920  
1921                      for ($i = 0; $i < $thisObject['description_record_counts']; $i++) {
1922                          $descriptionRecord = array();
1923  
1924                          $descriptionRecord['reserved_1']         = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2)); // must be zero
1925                          $offset += 2;
1926  
1927                          $descriptionRecord['stream_number']      = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1928                          $offset += 2;
1929  
1930                          $descriptionRecord['name_length']        = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1931                          $offset += 2;
1932  
1933                          $descriptionRecord['data_type']          = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1934                          $offset += 2;
1935                          $descriptionRecord['data_type_text'] = self::metadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']);
1936  
1937                          $descriptionRecord['data_length']        = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  4));
1938                          $offset += 4;
1939  
1940                          $descriptionRecord['name']               =                              substr($asf_header_extension_object_data, $offset,  $descriptionRecord['name_length']);
1941                          $offset += $descriptionRecord['name_length'];
1942  
1943                          $descriptionRecord['data']               =                              substr($asf_header_extension_object_data, $offset,  $descriptionRecord['data_length']);
1944                          $offset += $descriptionRecord['data_length'];
1945                          switch ($descriptionRecord['data_type']) {
1946                              case 0x0000: // Unicode string
1947                                  break;
1948  
1949                              case 0x0001: // BYTE array
1950                                  // do nothing
1951                                  break;
1952  
1953                              case 0x0002: // BOOL
1954                                  $descriptionRecord['data'] = (bool) getid3_lib::LittleEndian2Int($descriptionRecord['data']);
1955                                  break;
1956  
1957                              case 0x0003: // DWORD
1958                              case 0x0004: // QWORD
1959                              case 0x0005: // WORD
1960                                  $descriptionRecord['data'] = getid3_lib::LittleEndian2Int($descriptionRecord['data']);
1961                                  break;
1962  
1963                              case 0x0006: // GUID
1964                                  $descriptionRecord['data_text'] = $this->BytestringToGUID($descriptionRecord['data']);
1965                                  break;
1966                          }
1967  
1968                          $thisObject['description_record'][$i] = $descriptionRecord;
1969                      }
1970                      break;
1971  
1972                  case GETID3_ASF_Language_List_Object:
1973                      $thisObject['language_id_record_counts'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1974                      $offset += 2;
1975  
1976                      for ($i = 0; $i < $thisObject['language_id_record_counts']; $i++) {
1977                          $languageIDrecord = array();
1978  
1979                          $languageIDrecord['language_id_length']         = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  1));
1980                          $offset += 1;
1981  
1982                          $languageIDrecord['language_id']                =                              substr($asf_header_extension_object_data, $offset,  $languageIDrecord['language_id_length']);
1983                          $offset += $languageIDrecord['language_id_length'];
1984  
1985                          $thisObject['language_id_record'][$i] = $languageIDrecord;
1986                      }
1987                      break;
1988  
1989                  case GETID3_ASF_Metadata_Library_Object:
1990                      $thisObject['description_records_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1991                      $offset += 2;
1992  
1993                      for ($i = 0; $i < $thisObject['description_records_count']; $i++) {
1994                          $descriptionRecord = array();
1995  
1996                          $descriptionRecord['language_list_index'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
1997                          $offset += 2;
1998  
1999                          $descriptionRecord['stream_number']       = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
2000                          $offset += 2;
2001  
2002                          $descriptionRecord['name_length']         = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
2003                          $offset += 2;
2004  
2005                          $descriptionRecord['data_type']           = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
2006                          $offset += 2;
2007                          $descriptionRecord['data_type_text'] = self::metadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']);
2008  
2009                          $descriptionRecord['data_length']         = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  4));
2010                          $offset += 4;
2011  
2012                          $descriptionRecord['name']                =                              substr($asf_header_extension_object_data, $offset,  $descriptionRecord['name_length']);
2013                          $offset += $descriptionRecord['name_length'];
2014  
2015                          $descriptionRecord['data']                =                              substr($asf_header_extension_object_data, $offset,  $descriptionRecord['data_length']);
2016                          $offset += $descriptionRecord['data_length'];
2017  
2018                          if (preg_match('#^WM/Picture$#', str_replace("\x00", '', trim($descriptionRecord['name'])))) {
2019                              $WMpicture = $this->ASF_WMpicture($descriptionRecord['data']);
2020                              foreach ($WMpicture as $key => $value) {
2021                                  $descriptionRecord['data'] = $WMpicture;
2022                              }
2023                              unset($WMpicture);
2024                          }
2025  
2026                          $thisObject['description_record'][$i] = $descriptionRecord;
2027                      }
2028                      break;
2029  
2030                  case GETID3_ASF_Index_Parameters_Object:
2031                      $thisObject['index_entry_time_interval'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4));
2032                      $offset += 4;
2033  
2034                      $thisObject['index_specifiers_count']    = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
2035                      $offset += 2;
2036  
2037                      for ($i = 0; $i < $thisObject['index_specifiers_count']; $i++) {
2038                          $indexSpecifier = array();
2039  
2040                          $indexSpecifier['stream_number']   = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
2041                          $offset += 2;
2042  
2043                          $indexSpecifier['index_type']      = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
2044                          $offset += 2;
2045                          $indexSpecifier['index_type_text'] = isset(static::$ASFIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']])
2046                              ? static::$ASFIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']]
2047                              : 'invalid'
2048                          ;
2049  
2050                          $thisObject['index_specifiers'][$i] = $indexSpecifier;
2051                      }
2052  
2053                      break;
2054  
2055                  case GETID3_ASF_Media_Object_Index_Parameters_Object:
2056                      $thisObject['index_entry_count_interval'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4));
2057                      $offset += 4;
2058  
2059                      $thisObject['index_specifiers_count']     = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
2060                      $offset += 2;
2061  
2062                      for ($i = 0; $i < $thisObject['index_specifiers_count']; $i++) {
2063                          $indexSpecifier = array();
2064  
2065                          $indexSpecifier['stream_number']   = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
2066                          $offset += 2;
2067  
2068                          $indexSpecifier['index_type']      = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
2069                          $offset += 2;
2070                          $indexSpecifier['index_type_text'] = isset(static::$ASFMediaObjectIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']])
2071                              ? static::$ASFMediaObjectIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']]
2072                              : 'invalid'
2073                          ;
2074  
2075                          $thisObject['index_specifiers'][$i] = $indexSpecifier;
2076                      }
2077  
2078                      break;
2079  
2080                  case GETID3_ASF_Timecode_Index_Parameters_Object:
2081                      // 4.11    Timecode Index Parameters Object (mandatory only if TIMECODE index is present in file, 0 or 1)
2082                      // Field name                     Field type   Size (bits)
2083                      // Object ID                      GUID         128             // GUID for the Timecode Index Parameters Object - ASF_Timecode_Index_Parameters_Object
2084                      // Object Size                    QWORD        64              // Specifies the size, in bytes, of the Timecode Index Parameters Object. Valid values are at least 34 bytes.
2085                      // Index Entry Count Interval     DWORD        32              // This value is ignored for the Timecode Index Parameters Object.
2086                      // Index Specifiers Count         WORD         16              // Specifies the number of entries in the Index Specifiers list. Valid values are 1 and greater.
2087                      // Index Specifiers               array of:    varies          //
2088                      // * Stream Number                WORD         16              // Specifies the stream number that the Index Specifiers refer to. Valid values are between 1 and 127.
2089                      // * Index Type                   WORD         16              // Specifies the type of index. Values are defined as follows (1 is not a valid value):
2090                                                                                     // 2 = Nearest Past Media Object - indexes point to the closest data packet containing an entire video frame or the first fragment of a video frame
2091                                                                                     // 3 = Nearest Past Cleanpoint - indexes point to the closest data packet containing an entire video frame (or first fragment of a video frame) that is a key frame.
2092                                                                                     // Nearest Past Media Object is the most common value
2093  
2094                      $thisObject['index_entry_count_interval'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4));
2095                      $offset += 4;
2096  
2097                      $thisObject['index_specifiers_count']     = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
2098                      $offset += 2;
2099  
2100                      for ($i = 0; $i < $thisObject['index_specifiers_count']; $i++) {
2101                          $indexSpecifier = array();
2102  
2103                          $indexSpecifier['stream_number']   = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
2104                          $offset += 2;
2105  
2106                          $indexSpecifier['index_type']      = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
2107                          $offset += 2;
2108                          $indexSpecifier['index_type_text'] = isset(static::$ASFTimecodeIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']])
2109                              ? static::$ASFTimecodeIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']]
2110                              : 'invalid'
2111                          ;
2112  
2113                          $thisObject['index_specifiers'][$i] = $indexSpecifier;
2114                      }
2115  
2116                      break;
2117  
2118                  case GETID3_ASF_Compatibility_Object:
2119                      $thisObject['profile'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 1));
2120                      $offset += 1;
2121  
2122                      $thisObject['mode']    = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 1));
2123                      $offset += 1;
2124  
2125                      break;
2126  
2127                  default:
2128                      $unhandled_sections++;
2129                      if ($this->GUIDname($thisObject['guid_text'])) {
2130                          $this->warning('unhandled Header Extension Object GUID "'.$this->GUIDname($thisObject['guid_text']).'" {'.$thisObject['guid_text'].'} at offset '.($offset - 16 - 8));
2131                      } else {
2132                          $this->warning('unknown Header Extension Object GUID {'.$thisObject['guid_text'].'} in at offset '.($offset - 16 - 8));
2133                      }
2134                      break;
2135              }
2136              $HeaderExtensionObjectParsed[] = $thisObject;
2137  
2138              $objectOffset += $thisObject['size'];
2139          }
2140          return $HeaderExtensionObjectParsed;
2141      }
2142  
2143      /**
2144       * @param int $id
2145       *
2146       * @return string
2147       */
2148  	public static function metadataLibraryObjectDataTypeLookup($id) {
2149          static $lookup = array(
2150              0x0000 => 'Unicode string', // The data consists of a sequence of Unicode characters
2151              0x0001 => 'BYTE array',     // The type of the data is implementation-specific
2152              0x0002 => 'BOOL',           // The data is 2 bytes long and should be interpreted as a 16-bit unsigned integer. Only 0x0000 or 0x0001 are permitted values
2153              0x0003 => 'DWORD',          // The data is 4 bytes long and should be interpreted as a 32-bit unsigned integer
2154              0x0004 => 'QWORD',          // The data is 8 bytes long and should be interpreted as a 64-bit unsigned integer
2155              0x0005 => 'WORD',           // The data is 2 bytes long and should be interpreted as a 16-bit unsigned integer
2156              0x0006 => 'GUID',           // The data is 16 bytes long and should be interpreted as a 128-bit GUID
2157          );
2158          return (isset($lookup[$id]) ? $lookup[$id] : 'invalid');
2159      }
2160  
2161      /**
2162       * @param string $data
2163       *
2164       * @return array
2165       */
2166  	public function ASF_WMpicture(&$data) {
2167          //typedef struct _WMPicture{
2168          //  LPWSTR  pwszMIMEType;
2169          //  BYTE  bPictureType;
2170          //  LPWSTR  pwszDescription;
2171          //  DWORD  dwDataLen;
2172          //  BYTE*  pbData;
2173          //} WM_PICTURE;
2174  
2175          $WMpicture = array();
2176  
2177          $offset = 0;
2178          $WMpicture['image_type_id'] = getid3_lib::LittleEndian2Int(substr($data, $offset, 1));
2179          $offset += 1;
2180          $WMpicture['image_type']    = self::WMpictureTypeLookup($WMpicture['image_type_id']);
2181          $WMpicture['image_size']    = getid3_lib::LittleEndian2Int(substr($data, $offset, 4));
2182          $offset += 4;
2183  
2184          $WMpicture['image_mime'] = '';
2185          do {
2186              $next_byte_pair = substr($data, $offset, 2);
2187              $offset += 2;
2188              $WMpicture['image_mime'] .= $next_byte_pair;
2189          } while ($next_byte_pair !== "\x00\x00");
2190  
2191          $WMpicture['image_description'] = '';
2192          do {
2193              $next_byte_pair = substr($data, $offset, 2);
2194              $offset += 2;
2195              $WMpicture['image_description'] .= $next_byte_pair;
2196          } while ($next_byte_pair !== "\x00\x00");
2197  
2198          $WMpicture['dataoffset'] = $offset;
2199          $WMpicture['data'] = substr($data, $offset);
2200  
2201          $imageinfo = array();
2202          $WMpicture['image_mime'] = '';
2203          $imagechunkcheck = getid3_lib::GetDataImageSize($WMpicture['data'], $imageinfo);
2204          unset($imageinfo);
2205          if (!empty($imagechunkcheck)) {
2206              $WMpicture['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]);
2207          }
2208          if (!isset($this->getid3->info['asf']['comments']['picture'])) {
2209              $this->getid3->info['asf']['comments']['picture'] = array();
2210          }
2211          $this->getid3->info['asf']['comments']['picture'][] = array('data'=>$WMpicture['data'], 'image_mime'=>$WMpicture['image_mime']);
2212  
2213          return $WMpicture;
2214      }
2215  
2216      /**
2217       * Remove terminator 00 00 and convert UTF-16LE to Latin-1.
2218       *
2219       * @param string $string
2220       *
2221       * @return string
2222       */
2223  	public static function TrimConvert($string) {
2224          return trim(getid3_lib::iconv_fallback('UTF-16LE', 'ISO-8859-1', self::TrimTerm($string)), ' ');
2225      }
2226  
2227      /**
2228       * Remove terminator 00 00.
2229       *
2230       * @param string $string
2231       *
2232       * @return string
2233       */
2234  	public static function TrimTerm($string) {
2235          // remove terminator, only if present (it should be, but...)
2236          if (substr($string, -2) === "\x00\x00") {
2237              $string = substr($string, 0, -2);
2238          }
2239          return $string;
2240      }
2241  
2242  }


Generated : Thu Apr 25 08:20:02 2024 Cross-referenced by PHPXref