204 $info = &$this->getid3->info;
206 $atom_parent = end($atomHierarchy);
207 array_push($atomHierarchy, $atomname);
208 $atom_structure[
'hierarchy'] = implode(
' ', $atomHierarchy);
209 $atom_structure[
'name'] = $atomname;
210 $atom_structure[
'size'] = $atomsize;
211 $atom_structure[
'offset'] = $baseoffset;
233 $allnumericnames =
true;
234 foreach ($atom_structure[
'subatoms'] as $subatomarray) {
235 if (!is_integer($subatomarray[
'name']) || (count($subatomarray[
'subatoms']) != 1)) {
236 $allnumericnames =
false;
240 if ($allnumericnames) {
242 foreach ($atom_structure[
'subatoms'] as $subatomarray) {
243 foreach ($subatomarray[
'subatoms'] as $newData_subatomarray) {
244 unset($newData_subatomarray[
'hierarchy'], $newData_subatomarray[
'name']);
245 $newData[$subatomarray[
'name']] = $newData_subatomarray;
249 $atom_structure[
'data'] = $newData;
250 unset($atom_structure[
'subatoms']);
255 case "\x00\x00\x00\x01":
256 case "\x00\x00\x00\x02":
257 case "\x00\x00\x00\x03":
258 case "\x00\x00\x00\x04":
259 case "\x00\x00\x00\x05":
261 $atom_structure[
'name'] = $atomname;
270 foreach ($atom_structure[
'subatoms'] as
$key => $value_array) {
271 if (isset($value_array[
'sample_description_table'])) {
272 foreach ($value_array[
'sample_description_table'] as $key2 => $value_array2) {
273 if (isset($value_array2[
'data_format'])) {
274 switch ($value_array2[
'data_format']) {
286 } elseif (isset($value_array[
'time_to_sample_table'])) {
287 foreach ($value_array[
'time_to_sample_table'] as $key2 => $value_array2) {
288 if (isset($value_array2[
'sample_count']) && isset($value_array2[
'sample_duration']) && ($value_array2[
'sample_duration'] > 0)) {
289 $framerate = round(
$info[
'quicktime'][
'time_scale'] / $value_array2[
'sample_duration'], 3);
290 $framecount = $value_array2[
'sample_count'];
295 if ($isVideo && $framerate) {
296 $info[
'quicktime'][
'video'][
'frame_rate'] = $framerate;
297 $info[
'video'][
'frame_rate'] =
$info[
'quicktime'][
'video'][
'frame_rate'];
299 if ($isVideo && $framecount) {
300 $info[
'quicktime'][
'video'][
'frame_count'] = $framecount;
387 if ($atom_parent ==
'udta') {
391 $atom_structure[
'data'] = substr($atom_data, 4);
394 if (empty(
$info[
'comments'][
'language']) || (!in_array($atom_structure[
'language'],
$info[
'comments'][
'language']))) {
395 $info[
'comments'][
'language'][] = $atom_structure[
'language'];
400 if (substr($atom_data, 2, 2) ==
"\x10\xB5") {
403 while ($atomoffset < strlen($atom_data)) {
405 $boxsmalltype = substr($atom_data, $atomoffset + 2, 2);
406 $boxsmalldata = substr($atom_data, $atomoffset + 4, $boxsmallsize);
407 if ($boxsmallsize <= 1) {
408 $this->
warning(
'Invalid QuickTime atom smallbox size "'.$boxsmallsize.
'" in atom "'.preg_replace(
'#[^a-zA-Z0-9 _\\-]#',
'?', $atomname).
'" at offset: '.($atom_structure[
'offset'] + $atomoffset));
409 $atom_structure[
'data'] = null;
410 $atomoffset = strlen($atom_data);
413 switch ($boxsmalltype) {
415 $atom_structure[
'data'] = $boxsmalldata;
418 $this->
warning(
'Unknown QuickTime smallbox type: "'.preg_replace(
'#[^a-zA-Z0-9 _\\-]#',
'?', $boxsmalltype).
'" ('.trim(
getid3_lib::PrintHexBytes($boxsmalltype)).
') at offset '.$baseoffset);
419 $atom_structure[
'data'] = $atom_data;
422 $atomoffset += (4 + $boxsmallsize);
425 while ($atomoffset < strlen($atom_data)) {
427 $boxtype = substr($atom_data, $atomoffset + 4, 4);
428 $boxdata = substr($atom_data, $atomoffset + 8, $boxsize - 8);
430 $this->
warning(
'Invalid QuickTime atom box size "'.$boxsize.
'" in atom "'.preg_replace(
'#[^a-zA-Z0-9 _\\-]#',
'?', $atomname).
'" at offset: '.($atom_structure[
'offset'] + $atomoffset));
431 $atom_structure[
'data'] = null;
432 $atomoffset = strlen($atom_data);
435 $atomoffset += $boxsize;
440 $atom_structure[$boxtype] = substr($boxdata, 4);
446 switch ($atom_structure[
'flags_raw']) {
468 $atom_structure[
'data'] = empty($num) ?
'' : $num;
469 $atom_structure[
'data'] .= empty($num_total) ?
'' :
'/'.$num_total;
498 $atom_structure[
'data'] = substr($boxdata, 8);
507 $atom_structure[
'data'] = substr($boxdata, 8);
509 if (preg_match(
'#^\\xFF\\xD8\\xFF#', $atom_structure[
'data'])) {
510 $atom_structure[
'image_mime'] =
'image/jpeg';
511 } elseif (preg_match(
'#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure[
'data'])) {
512 $atom_structure[
'image_mime'] =
'image/png';
513 } elseif (preg_match(
'#^GIF#', $atom_structure[
'data'])) {
514 $atom_structure[
'image_mime'] =
'image/gif';
532 $atom_structure[
'data'] = substr($boxdata, 8);
533 if ($atomname ==
'covr') {
535 if (preg_match(
'#^\\xFF\\xD8\\xFF#', $atom_structure[
'data'])) {
536 $atom_structure[
'image_mime'] =
'image/jpeg';
537 } elseif (preg_match(
'#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure[
'data'])) {
538 $atom_structure[
'image_mime'] =
'image/png';
539 } elseif (preg_match(
'#^GIF#', $atom_structure[
'data'])) {
540 $atom_structure[
'image_mime'] =
'image/gif';
549 $this->
warning(
'Unknown QuickTime box type: "'.preg_replace(
'#[^a-zA-Z0-9 _\\-]#',
'?', $boxtype).
'" ('.trim(
getid3_lib::PrintHexBytes($boxtype)).
') at offset '.$baseoffset);
550 $atom_structure[
'data'] = $atom_data;
563 $info[
'quicktime'][
'autoplay'] = $atom_structure[
'autoplay'];
584 $atom_structure[
'data'] = $atom_data;
593 $CompressedFileData = substr($atom_data, 4);
594 if ($UncompressedHeader = @gzuncompress($CompressedFileData)) {
597 $this->
warning(
'Error decompressing compressed MOV atom at offset '.$atom_structure[
'offset']);
603 $atom_structure[
'compression_id'] = $atom_data;
611 $atom_structure[
'flags'][
'internal_data'] = (bool) ($atom_structure[
'flags_raw'] & 0x000001);
613 $atom_structure[
'reference_type_name'] = substr($atom_data, 4, 4);
615 switch ($atom_structure[
'reference_type_name']) {
617 $atom_structure[
'url'] = $this->
NoNullString(substr($atom_data, 12));
621 $atom_structure[
'file_alias'] = substr($atom_data, 12);
625 $atom_structure[
'resource_alias'] = substr($atom_data, 12);
629 $atom_structure[
'data'] = substr($atom_data, 12);
650 $atom_structure[
'gestalt_selector'] = substr($atom_data, 4, 4);
660 $atom_structure[
'component_type'] = substr($atom_data, 4, 4);
661 $atom_structure[
'component_subtype'] = substr($atom_data, 8, 4);
662 $atom_structure[
'component_manufacturer'] = substr($atom_data, 12, 4);
674 $atom_structure[
'data_rate_bps'] = $atom_structure[
'data_rate'] * 10;
684 if (empty(
$info[
'comments'][
'language']) || (!in_array($atom_structure[
'language'],
$info[
'comments'][
'language']))) {
685 $info[
'comments'][
'language'][] = $atom_structure[
'language'];
705 $atom_structure[
'flags'][
'play_on_open'] = (bool) $atom_structure[
'play_on_open_flag'];
706 $atom_structure[
'flags'][
'slide_show'] = (bool) $atom_structure[
'slide_show_flag'];
708 $ptv_lookup[0] =
'normal';
709 $ptv_lookup[1] =
'double';
710 $ptv_lookup[2] =
'half';
711 $ptv_lookup[3] =
'full';
712 $ptv_lookup[4] =
'current';
713 if (isset($ptv_lookup[$atom_structure[
'display_size_raw']])) {
714 $atom_structure[
'display_size'] = $ptv_lookup[$atom_structure[
'display_size_raw']];
716 $this->
warning(
'unknown "ptv " display constant ('.$atom_structure[
'display_size_raw'].
')');
725 $stsdEntriesDataOffset = 8;
726 for (
$i = 0;
$i < $atom_structure[
'number_entries'];
$i++) {
727 $atom_structure[
'sample_description_table'][
$i][
'size'] =
getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4));
728 $stsdEntriesDataOffset += 4;
729 $atom_structure[
'sample_description_table'][
$i][
'data_format'] = substr($atom_data, $stsdEntriesDataOffset, 4);
730 $stsdEntriesDataOffset += 4;
731 $atom_structure[
'sample_description_table'][
$i][
'reserved'] =
getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 6));
732 $stsdEntriesDataOffset += 6;
733 $atom_structure[
'sample_description_table'][
$i][
'reference_index'] =
getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 2));
734 $stsdEntriesDataOffset += 2;
735 $atom_structure[
'sample_description_table'][
$i][
'data'] = substr($atom_data, $stsdEntriesDataOffset, ($atom_structure[
'sample_description_table'][
$i][
'size'] - 4 - 4 - 6 - 2));
736 $stsdEntriesDataOffset += ($atom_structure[
'sample_description_table'][
$i][
'size'] - 4 - 4 - 6 - 2);
738 $atom_structure[
'sample_description_table'][
$i][
'encoder_version'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][
$i][
'data'], 0, 2));
739 $atom_structure[
'sample_description_table'][
$i][
'encoder_revision'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][
$i][
'data'], 2, 2));
740 $atom_structure[
'sample_description_table'][
$i][
'encoder_vendor'] = substr($atom_structure[
'sample_description_table'][
$i][
'data'], 4, 4);
742 switch ($atom_structure[
'sample_description_table'][
$i][
'encoder_vendor']) {
744 case "\x00\x00\x00\x00":
746 $atom_structure[
'sample_description_table'][
$i][
'audio_channels'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 8, 2));
747 $atom_structure[
'sample_description_table'][
$i][
'audio_bit_depth'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 10, 2));
748 $atom_structure[
'sample_description_table'][
$i][
'audio_compression_id'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 12, 2));
749 $atom_structure[
'sample_description_table'][
$i][
'audio_packet_size'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 14, 2));
750 $atom_structure[
'sample_description_table'][
$i][
'audio_sample_rate'] =
getid3_lib::FixedPoint16_16(substr($atom_structure[
'sample_description_table'][$i][
'data'], 16, 4));
754 $atom_structure[
'sample_description_table'][
$i][
'temporal_quality'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 8, 4));
755 $atom_structure[
'sample_description_table'][
$i][
'spatial_quality'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 12, 4));
756 $atom_structure[
'sample_description_table'][
$i][
'width'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 16, 2));
757 $atom_structure[
'sample_description_table'][
$i][
'height'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 18, 2));
758 $atom_structure[
'sample_description_table'][
$i][
'resolution_x'] =
getid3_lib::FixedPoint16_16(substr($atom_structure[
'sample_description_table'][$i][
'data'], 24, 4));
759 $atom_structure[
'sample_description_table'][
$i][
'resolution_y'] =
getid3_lib::FixedPoint16_16(substr($atom_structure[
'sample_description_table'][$i][
'data'], 28, 4));
760 $atom_structure[
'sample_description_table'][
$i][
'data_size'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 32, 4));
761 $atom_structure[
'sample_description_table'][
$i][
'frame_count'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 36, 2));
762 $atom_structure[
'sample_description_table'][
$i][
'compressor_name'] = substr($atom_structure[
'sample_description_table'][$i][
'data'], 38, 4);
763 $atom_structure[
'sample_description_table'][
$i][
'pixel_depth'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 42, 2));
764 $atom_structure[
'sample_description_table'][
$i][
'color_table_id'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 44, 2));
766 switch ($atom_structure[
'sample_description_table'][$i][
'data_format']) {
793 $info[
'fileformat'] =
'mp4';
794 $info[
'video'][
'fourcc'] = $atom_structure[
'sample_description_table'][
$i][
'data_format'];
797 if (!empty($atom_structure[
'sample_description_table'][$i][
'width']) && !empty($atom_structure[
'sample_description_table'][$i][
'height'])) {
799 $info[
'video'][
'resolution_x'] = $atom_structure[
'sample_description_table'][
$i][
'width'];
800 $info[
'video'][
'resolution_y'] = $atom_structure[
'sample_description_table'][
$i][
'height'];
801 $info[
'quicktime'][
'video'][
'resolution_x'] =
$info[
'video'][
'resolution_x'];
802 $info[
'quicktime'][
'video'][
'resolution_y'] =
$info[
'video'][
'resolution_y'];
807 $info[
'video'][
'dataformat'] =
'quicktimevr';
813 $info[
'quicktime'][
'audio'][
'sample_rate'] = $atom_structure[
'sample_description_table'][
$i][
'audio_sample_rate'];
814 $info[
'quicktime'][
'audio'][
'channels'] = $atom_structure[
'sample_description_table'][
$i][
'audio_channels'];
815 $info[
'quicktime'][
'audio'][
'bit_depth'] = $atom_structure[
'sample_description_table'][
$i][
'audio_bit_depth'];
816 $info[
'audio'][
'codec'] =
$info[
'quicktime'][
'audio'][
'codec'];
817 $info[
'audio'][
'sample_rate'] =
$info[
'quicktime'][
'audio'][
'sample_rate'];
818 $info[
'audio'][
'channels'] =
$info[
'quicktime'][
'audio'][
'channels'];
819 $info[
'audio'][
'bits_per_sample'] =
$info[
'quicktime'][
'audio'][
'bit_depth'];
820 switch ($atom_structure[
'sample_description_table'][$i][
'data_format']) {
823 $info[
'audio'][
'lossless'] =
true;
826 $info[
'audio'][
'lossless'] =
false;
834 switch ($atom_structure[
'sample_description_table'][$i][
'data_format']) {
836 $info[
'fileformat'] =
'mp4';
841 $atom_structure[
'sample_description_table'][
$i][
'video_temporal_quality'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 8, 4));
842 $atom_structure[
'sample_description_table'][
$i][
'video_spatial_quality'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 12, 4));
843 $atom_structure[
'sample_description_table'][
$i][
'video_frame_width'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 16, 2));
844 $atom_structure[
'sample_description_table'][
$i][
'video_frame_height'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 18, 2));
845 $atom_structure[
'sample_description_table'][
$i][
'video_resolution_x'] =
getid3_lib::FixedPoint16_16(substr($atom_structure[
'sample_description_table'][$i][
'data'], 20, 4));
846 $atom_structure[
'sample_description_table'][
$i][
'video_resolution_y'] =
getid3_lib::FixedPoint16_16(substr($atom_structure[
'sample_description_table'][$i][
'data'], 24, 4));
847 $atom_structure[
'sample_description_table'][
$i][
'video_data_size'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 28, 4));
848 $atom_structure[
'sample_description_table'][
$i][
'video_frame_count'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 32, 2));
849 $atom_structure[
'sample_description_table'][
$i][
'video_encoder_name_len'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 34, 1));
850 $atom_structure[
'sample_description_table'][
$i][
'video_encoder_name'] = substr($atom_structure[
'sample_description_table'][$i][
'data'], 35, $atom_structure[
'sample_description_table'][$i][
'video_encoder_name_len']);
851 $atom_structure[
'sample_description_table'][
$i][
'video_pixel_color_depth'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 66, 2));
852 $atom_structure[
'sample_description_table'][
$i][
'video_color_table_id'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 68, 2));
854 $atom_structure[
'sample_description_table'][
$i][
'video_pixel_color_type'] = (($atom_structure[
'sample_description_table'][
$i][
'video_pixel_color_depth'] > 32) ?
'grayscale' :
'color');
855 $atom_structure[
'sample_description_table'][
$i][
'video_pixel_color_name'] = $this->
QuicktimeColorNameLookup($atom_structure[
'sample_description_table'][$i][
'video_pixel_color_depth']);
857 if ($atom_structure[
'sample_description_table'][$i][
'video_pixel_color_name'] !=
'invalid') {
858 $info[
'quicktime'][
'video'][
'codec_fourcc'] = $atom_structure[
'sample_description_table'][
$i][
'data_format'];
859 $info[
'quicktime'][
'video'][
'codec_fourcc_lookup'] = $this->
QuicktimeVideoCodecLookup($atom_structure[
'sample_description_table'][$i][
'data_format']);
860 $info[
'quicktime'][
'video'][
'codec'] = (($atom_structure[
'sample_description_table'][
$i][
'video_encoder_name_len'] > 0) ? $atom_structure[
'sample_description_table'][$i][
'video_encoder_name'] : $atom_structure[
'sample_description_table'][$i][
'data_format']);
861 $info[
'quicktime'][
'video'][
'color_depth'] = $atom_structure[
'sample_description_table'][
$i][
'video_pixel_color_depth'];
862 $info[
'quicktime'][
'video'][
'color_depth_name'] = $atom_structure[
'sample_description_table'][
$i][
'video_pixel_color_name'];
864 $info[
'video'][
'codec'] =
$info[
'quicktime'][
'video'][
'codec'];
865 $info[
'video'][
'bits_per_sample'] =
$info[
'quicktime'][
'video'][
'color_depth'];
867 $info[
'video'][
'lossless'] =
false;
868 $info[
'video'][
'pixel_aspect_ratio'] = (float) 1;
873 switch (strtolower($atom_structure[
'sample_description_table'][$i][
'data_format'])) {
875 $info[
'audio'][
'dataformat'] =
'mp4';
876 $info[
'quicktime'][
'audio'][
'codec'] =
'mp4';
882 $info[
'video'][
'dataformat'] =
'3ivx';
886 $info[
'video'][
'dataformat'] =
'xvid';
890 $info[
'video'][
'dataformat'] =
'mpeg4';
900 $info[
'video'][
'dataformat'] =
'divx';
907 unset($atom_structure[
'sample_description_table'][$i][
'data']);
916 $sttsEntriesDataOffset = 8;
920 $max_stts_entries_to_scan = (
$info[
'php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure[
'number_entries']) : $atom_structure[
'number_entries']);
921 if ($max_stts_entries_to_scan < $atom_structure[
'number_entries']) {
922 $this->
warning(
'QuickTime atom "stts" has '.$atom_structure[
'number_entries'].
' but only scanning the first '.$max_stts_entries_to_scan.
' entries due to limited PHP memory available ('.floor($atom_structure[
'number_entries'] / 1048576).
'MB).');
924 for ($i = 0; $i < $max_stts_entries_to_scan; $i++) {
925 $atom_structure[
'time_to_sample_table'][
$i][
'sample_count'] =
getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
926 $sttsEntriesDataOffset += 4;
927 $atom_structure[
'time_to_sample_table'][
$i][
'sample_duration'] =
getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
928 $sttsEntriesDataOffset += 4;
930 $frames_count += $atom_structure[
'time_to_sample_table'][
$i][
'sample_count'];
943 $info[
'quicktime'][
'stts_framecount'][] = $frames_count;
969 $stssEntriesDataOffset = 8;
970 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++) {
972 $stssEntriesDataOffset += 4;
983 $stscEntriesDataOffset = 8;
984 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++) {
985 $atom_structure[
'sample_to_chunk_table'][
$i][
'first_chunk'] =
getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
986 $stscEntriesDataOffset += 4;
987 $atom_structure[
'sample_to_chunk_table'][
$i][
'samples_per_chunk'] =
getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
988 $stscEntriesDataOffset += 4;
989 $atom_structure[
'sample_to_chunk_table'][
$i][
'sample_description'] =
getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
990 $stscEntriesDataOffset += 4;
1002 $stszEntriesDataOffset = 12;
1003 if ($atom_structure[
'sample_size'] == 0) {
1004 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++) {
1006 $stszEntriesDataOffset += 4;
1018 $stcoEntriesDataOffset = 8;
1019 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++) {
1021 $stcoEntriesDataOffset += 4;
1032 $stcoEntriesDataOffset = 8;
1033 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++) {
1035 $stcoEntriesDataOffset += 8;
1045 $drefDataOffset = 8;
1046 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++) {
1048 $drefDataOffset += 4;
1049 $atom_structure[
'data_references'][
$i][
'type'] = substr($atom_data, $drefDataOffset, 4);
1050 $drefDataOffset += 4;
1052 $drefDataOffset += 1;
1054 $drefDataOffset += 3;
1055 $atom_structure[
'data_references'][
$i][
'data'] = substr($atom_data, $drefDataOffset, ($atom_structure[
'data_references'][$i][
'size'] - 4 - 4 - 1 - 3));
1056 $drefDataOffset += ($atom_structure[
'data_references'][
$i][
'size'] - 4 - 4 - 1 - 3);
1058 $atom_structure[
'data_references'][
$i][
'flags'][
'self_reference'] = (bool) ($atom_structure[
'data_references'][$i][
'flags_raw'] & 0x001);
1091 $atom_structure[
'flags'][
'no_lean_ahead'] = (bool) ($atom_structure[
'flags_raw'] & 0x001);
1098 $atom_structure[
'component_type'] = substr($atom_data, 4, 4);
1099 $atom_structure[
'component_subtype'] = substr($atom_data, 8, 4);
1100 $atom_structure[
'component_manufacturer'] = substr($atom_data, 12, 4);
1103 $atom_structure[
'component_name'] = $this->
Pascal2String(substr($atom_data, 24));
1105 if (($atom_structure[
'component_subtype'] ==
'STpn') && ($atom_structure[
'component_manufacturer'] ==
'zzzz')) {
1106 $info[
'video'][
'dataformat'] =
'quicktimevr';
1121 if ($atom_structure[
'time_scale'] == 0) {
1122 $this->
error(
'Corrupt Quicktime file: mdhd.time_scale == zero');
1125 $info[
'quicktime'][
'time_scale'] = ((isset(
$info[
'quicktime'][
'time_scale']) && (
$info[
'quicktime'][
'time_scale'] < 1000)) ? max(
$info[
'quicktime'][
'time_scale'], $atom_structure[
'time_scale']) : $atom_structure[
'time_scale']);
1129 $atom_structure[
'playtime_seconds'] = $atom_structure[
'duration'] / $atom_structure[
'time_scale'];
1131 if (empty(
$info[
'comments'][
'language']) || (!in_array($atom_structure[
'language'],
$info[
'comments'][
'language']))) {
1132 $info[
'comments'][
'language'][] = $atom_structure[
'language'];
1140 $atom_structure[
'atom_type'] = substr($atom_data, 6, 4);
1150 $atom_structure[
'clipping_data'] = substr($atom_data, 10);
1160 $atom_structure[
'default_hints'][
'double_buffer'] = (bool) ($atom_structure[
'default_hints_raw'] & 0x0020);
1161 $atom_structure[
'default_hints'][
'high_quality'] = (bool) ($atom_structure[
'default_hints_raw'] & 0x0100);
1170 for ($i = 0; $i < strlen($atom_data); $i += 4) {
1180 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++ ) {
1191 $atom_structure[
'matte_data_raw'] = substr($atom_data, 4);
1199 for ($colortableentry = 0; $colortableentry < $atom_structure[
'color_table_size']; $colortableentry++) {
1200 $atom_structure[
'color_table'][$colortableentry][
'alpha'] =
getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 0, 2));
1201 $atom_structure[
'color_table'][$colortableentry][
'red'] =
getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 2, 2));
1202 $atom_structure[
'color_table'][$colortableentry][
'green'] =
getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 4, 2));
1203 $atom_structure[
'color_table'][$colortableentry][
'blue'] =
getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 6, 2));
1217 $atom_structure[
'reserved'] = substr($atom_data, 26, 10);
1235 if ($atom_structure[
'time_scale'] == 0) {
1236 $this->
error(
'Corrupt Quicktime file: mvhd.time_scale == zero');
1241 $info[
'quicktime'][
'time_scale'] = ((isset(
$info[
'quicktime'][
'time_scale']) && (
$info[
'quicktime'][
'time_scale'] < 1000)) ? max(
$info[
'quicktime'][
'time_scale'], $atom_structure[
'time_scale']) : $atom_structure[
'time_scale']);
1242 $info[
'quicktime'][
'display_scale'] = $atom_structure[
'matrix_a'];
1243 $info[
'playtime_seconds'] = $atom_structure[
'duration'] / $atom_structure[
'time_scale'];
1273 $atom_structure[
'flags'][
'enabled'] = (bool) ($atom_structure[
'flags_raw'] & 0x0001);
1274 $atom_structure[
'flags'][
'in_movie'] = (bool) ($atom_structure[
'flags_raw'] & 0x0002);
1275 $atom_structure[
'flags'][
'in_preview'] = (bool) ($atom_structure[
'flags_raw'] & 0x0004);
1276 $atom_structure[
'flags'][
'in_poster'] = (bool) ($atom_structure[
'flags_raw'] & 0x0008);
1280 if ($atom_structure[
'flags'][
'enabled'] == 1) {
1281 if (!isset(
$info[
'video'][
'resolution_x']) || !isset(
$info[
'video'][
'resolution_y'])) {
1282 $info[
'video'][
'resolution_x'] = $atom_structure[
'width'];
1283 $info[
'video'][
'resolution_y'] = $atom_structure[
'height'];
1285 $info[
'video'][
'resolution_x'] = max(
$info[
'video'][
'resolution_x'], $atom_structure[
'width']);
1286 $info[
'video'][
'resolution_y'] = max(
$info[
'video'][
'resolution_y'], $atom_structure[
'height']);
1287 $info[
'quicktime'][
'video'][
'resolution_x'] =
$info[
'video'][
'resolution_x'];
1288 $info[
'quicktime'][
'video'][
'resolution_y'] =
$info[
'video'][
'resolution_y'];
1323 $atom_structure[
'num_iods_tracks'] = ($atom_structure[
'length'] - 7) / 6;
1324 for ($i = 0; $i < $atom_structure[
'num_iods_tracks']; $i++) {
1338 $atom_structure[
'signature'] = substr($atom_data, 0, 4);
1340 $atom_structure[
'fourcc'] = substr($atom_data, 8, 4);
1351 if (substr($atom_data, $mdat_offset, 8) ==
"\x00\x00\x00\x08".
'wide') {
1353 } elseif (substr($atom_data, $mdat_offset, 8) ==
"\x00\x00\x00\x00".
'mdat') {
1361 while (($mdat_offset < (strlen($atom_data) - 8))
1363 && ($chapter_string_length < 1000)
1364 && ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2))
1365 && preg_match(
'#^([\x00-\xFF]{2})([\x20-\xFF]+)$#', substr($atom_data, $mdat_offset, $chapter_string_length + 2), $chapter_matches)) {
1366 list($dummy, $chapter_string_length_hex, $chapter_string) = $chapter_matches;
1367 $mdat_offset += (2 + $chapter_string_length);
1368 @
$info[
'quicktime'][
'comments'][
'chapters'][] = $chapter_string;
1371 if (substr($atom_data, $mdat_offset, 12) ==
"\x00\x00\x00\x0C\x65\x6E\x63\x64\x00\x00\x01\x00") {
1377 if (($atomsize > 8) && (!isset(
$info[
'avdataend_tmp']) || (
$info[
'quicktime'][$atomname][
'size'] > (
$info[
'avdataend_tmp'] -
$info[
'avdataoffset'])))) {
1379 $info[
'avdataoffset'] = $atom_structure[
'offset'] + 8;
1380 $OldAVDataEnd =
$info[
'avdataend'];
1381 $info[
'avdataend'] = $atom_structure[
'offset'] + $atom_structure[
'size'];
1383 $getid3_temp =
new getID3();
1384 $getid3_temp->openfile($this->getid3->filename);
1385 $getid3_temp->info[
'avdataoffset'] =
$info[
'avdataoffset'];
1386 $getid3_temp->info[
'avdataend'] =
$info[
'avdataend'];
1388 if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode($this->fread(4)))) {
1389 $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info[
'avdataoffset'],
false);
1390 if (!empty($getid3_temp->info[
'warning'])) {
1391 foreach ($getid3_temp->info[
'warning'] as $value) {
1395 if (!empty($getid3_temp->info[
'mpeg'])) {
1396 $info[
'mpeg'] = $getid3_temp->info[
'mpeg'];
1397 if (isset(
$info[
'mpeg'][
'audio'])) {
1398 $info[
'audio'][
'dataformat'] =
'mp3';
1399 $info[
'audio'][
'codec'] = (!empty(
$info[
'mpeg'][
'audio'][
'encoder']) ?
$info[
'mpeg'][
'audio'][
'encoder'] : (!empty(
$info[
'mpeg'][
'audio'][
'codec']) ?
$info[
'mpeg'][
'audio'][
'codec'] : (!empty(
$info[
'mpeg'][
'audio'][
'LAME']) ?
'LAME' :
'mp3')));
1400 $info[
'audio'][
'sample_rate'] =
$info[
'mpeg'][
'audio'][
'sample_rate'];
1401 $info[
'audio'][
'channels'] =
$info[
'mpeg'][
'audio'][
'channels'];
1402 $info[
'audio'][
'bitrate'] =
$info[
'mpeg'][
'audio'][
'bitrate'];
1403 $info[
'audio'][
'bitrate_mode'] = strtolower(
$info[
'mpeg'][
'audio'][
'bitrate_mode']);
1404 $info[
'bitrate'] =
$info[
'audio'][
'bitrate'];
1408 unset($getid3_mp3, $getid3_temp);
1409 $info[
'avdataend'] = $OldAVDataEnd;
1410 unset($OldAVDataEnd);
1414 unset($mdat_offset, $chapter_string_length, $chapter_matches);
1442 $atom_structure[
'ctyp'] = substr($atom_data, 0, 4);
1443 $info[
'quicktime'][
'controller'] = $atom_structure[
'ctyp'];
1444 switch ($atom_structure[
'ctyp']) {
1446 $info[
'video'][
'dataformat'] =
'quicktimevr';
1459 $info[
'quicktime'][
'hinting'] =
true;
1463 for ($i = 0; $i < ($atom_structure[
'size'] - 8); $i += 4) {
1486 $atom_structure[
'data'] = $atom_data;
1487 if (preg_match(
'#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) {
1488 @list($all, $latitude, $longitude, $altitude) = $matches;
1489 $info[
'quicktime'][
'comments'][
'gps_latitude'][] = floatval($latitude);
1490 $info[
'quicktime'][
'comments'][
'gps_longitude'][] = floatval($longitude);
1491 if (!empty($altitude)) {
1492 $info[
'quicktime'][
'comments'][
'gps_altitude'][] = floatval($altitude);
1495 $this->
warning(
'QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.
'. Please report as getID3() bug.');
1507 if (preg_match(
'/^\xFF\xD8\xFF/', $atom_data)) {
1508 $atom_structure[
'data'] = $atom_data;
1509 $atom_structure[
'image_mime'] =
'image/jpeg';
1510 $atom_structure[
'description'] = (($atomname ==
'NCTH') ?
'Nikon Camera Thumbnail Image' : (($atomname ==
'NCVW') ?
'Nikon Camera Preview Image' :
'Nikon preview image'));
1511 $info[
'quicktime'][
'comments'][
'picture'][] =
array(
'image_mime'=>$atom_structure[
'image_mime'],
'data'=>$atom_data,
'description'=>$atom_structure[
'description']);
1520 $atom_structure[
'data'] = $atom_data;
1523 case "\x00\x00\x00\x00":
1543 static $metaDATAkey = 1;
1545 $atom_structure[
'language'] = substr($atom_data, 4 + 0, 2);
1547 $atom_structure[
'data'] = substr($atom_data, 4 + 4);
1548 $atom_structure[
'key_name'] = @
$info[
'quicktime'][
'temp_meta_key_names'][$metaDATAkey++];
1550 if ($atom_structure[
'key_name'] && $atom_structure[
'data']) {
1551 @
$info[
'quicktime'][
'comments'][str_replace(
'com.apple.quicktime.',
'', $atom_structure[
'key_name'])][] = $atom_structure[
'data'];
1562 $keys_atom_offset = 8;
1563 for ($i = 1; $i <= $atom_structure[
'entry_count']; $i++) {
1565 $atom_structure[
'keys'][
$i][
'key_namespace'] = substr($atom_data, $keys_atom_offset + 4, 4);
1566 $atom_structure[
'keys'][
$i][
'key_value'] = substr($atom_data, $keys_atom_offset + 8, $atom_structure[
'keys'][$i][
'key_size'] - 8);
1567 $keys_atom_offset += $atom_structure[
'keys'][
$i][
'key_size'];
1569 $info[
'quicktime'][
'temp_meta_key_names'][
$i] = $atom_structure[
'keys'][
$i][
'key_value'];
1574 $this->
warning(
'Unknown QuickTime atom type: "'.preg_replace(
'#[^a-zA-Z0-9 _\\-]#',
'?', $atomname).
'" ('.trim(
getid3_lib::PrintHexBytes($atomname)).
') at offset '.$baseoffset);
1575 $atom_structure[
'data'] = $atom_data;
1578 array_pop($atomHierarchy);
1579 return $atom_structure;
QuicktimeSTIKLookup($stik)
QuicktimeIODSaudioProfileName($audio_profile_id)
CopyToAppropriateCommentsSection($keyname, $data, $boxname='')
QuicktimeAudioCodecLookup($codecid)
QuicktimeStoreFrontCodeLookup($sfid)
QuicktimeIODSvideoProfileName($video_profile_id)
quicktime_read_mp4_descr_length($data, &$offset)
static LookupGenreName($genreid, $allowSCMPXextended=true)
QuicktimeColorNameLookup($colordepthid)
NoNullString($nullterminatedstring)
Pascal2String($pascalstring)
QuicktimeContentRatingLookup($rtng)
QuicktimeLanguageLookup($languageid)
static DateMac2Unix($macdate)
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
static FixedPoint2_30($rawdata)
QuicktimeParseContainerAtom($atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms)
Create styles array
The data for the language used.
QuicktimeVideoCodecLookup($codecid)
static FixedPoint8_8($rawdata)
QuicktimeDCOMLookup($compressionid)
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
QuicktimeParseNikonNCTG($atom_data)
static FixedPoint16_16($rawdata)