125 $info = &$this->getid3->info;
127 $atom_parent = end($atomHierarchy);
128 array_push($atomHierarchy, $atomname);
129 $atom_structure[
'hierarchy'] = implode(
' ', $atomHierarchy);
130 $atom_structure[
'name'] = $atomname;
131 $atom_structure[
'size'] = $atomsize;
132 $atom_structure[
'offset'] = $baseoffset;
154 $allnumericnames =
true;
155 foreach ($atom_structure[
'subatoms'] as $subatomarray) {
156 if (!is_integer($subatomarray[
'name']) || (count($subatomarray[
'subatoms']) != 1)) {
157 $allnumericnames =
false;
161 if ($allnumericnames) {
163 foreach ($atom_structure[
'subatoms'] as $subatomarray) {
164 foreach ($subatomarray[
'subatoms'] as $newData_subatomarray) {
165 unset($newData_subatomarray[
'hierarchy'], $newData_subatomarray[
'name']);
166 $newData[$subatomarray[
'name']] = $newData_subatomarray;
170 $atom_structure[
'data'] = $newData;
171 unset($atom_structure[
'subatoms']);
176 case "\x00\x00\x00\x01":
177 case "\x00\x00\x00\x02":
178 case "\x00\x00\x00\x03":
179 case "\x00\x00\x00\x04":
180 case "\x00\x00\x00\x05":
182 $atom_structure[
'name'] = $atomname;
191 foreach ($atom_structure[
'subatoms'] as $key => $value_array) {
192 if (isset($value_array[
'sample_description_table'])) {
193 foreach ($value_array[
'sample_description_table'] as $key2 => $value_array2) {
194 if (isset($value_array2[
'data_format'])) {
195 switch ($value_array2[
'data_format']) {
207 } elseif (isset($value_array[
'time_to_sample_table'])) {
208 foreach ($value_array[
'time_to_sample_table'] as $key2 => $value_array2) {
209 if (isset($value_array2[
'sample_count']) && isset($value_array2[
'sample_duration']) && ($value_array2[
'sample_duration'] > 0)) {
210 $framerate = round(
$info[
'quicktime'][
'time_scale'] / $value_array2[
'sample_duration'], 3);
211 $framecount = $value_array2[
'sample_count'];
216 if ($isVideo && $framerate) {
217 $info[
'quicktime'][
'video'][
'frame_rate'] = $framerate;
218 $info[
'video'][
'frame_rate'] =
$info[
'quicktime'][
'video'][
'frame_rate'];
220 if ($isVideo && $framecount) {
221 $info[
'quicktime'][
'video'][
'frame_count'] = $framecount;
308 if ($atom_parent ==
'udta') {
312 $atom_structure[
'data'] = substr($atom_data, 4);
315 if (empty(
$info[
'comments'][
'language']) || (!in_array($atom_structure[
'language'],
$info[
'comments'][
'language']))) {
316 $info[
'comments'][
'language'][] = $atom_structure[
'language'];
321 if (substr($atom_data, 2, 2) ==
"\x10\xB5") {
324 while ($atomoffset < strlen($atom_data)) {
326 $boxsmalltype = substr($atom_data, $atomoffset + 2, 2);
327 $boxsmalldata = substr($atom_data, $atomoffset + 4, $boxsmallsize);
328 if ($boxsmallsize <= 1) {
329 $info[
'warning'][] =
'Invalid QuickTime atom smallbox size "'.$boxsmallsize.
'" in atom "'.preg_replace(
'#[^a-zA-Z0-9 _\\-]#',
'?', $atomname).
'" at offset: '.($atom_structure[
'offset'] + $atomoffset);
330 $atom_structure[
'data'] = null;
331 $atomoffset = strlen($atom_data);
334 switch ($boxsmalltype) {
336 $atom_structure[
'data'] = $boxsmalldata;
339 $info[
'warning'][] =
'Unknown QuickTime smallbox type: "'.preg_replace(
'#[^a-zA-Z0-9 _\\-]#',
'?', $boxsmalltype).
'" ('.trim(
getid3_lib::PrintHexBytes($boxsmalltype)).
') at offset '.$baseoffset;
340 $atom_structure[
'data'] = $atom_data;
343 $atomoffset += (4 + $boxsmallsize);
346 while ($atomoffset < strlen($atom_data)) {
348 $boxtype = substr($atom_data, $atomoffset + 4, 4);
349 $boxdata = substr($atom_data, $atomoffset + 8, $boxsize - 8);
351 $info[
'warning'][] =
'Invalid QuickTime atom box size "'.$boxsize.
'" in atom "'.preg_replace(
'#[^a-zA-Z0-9 _\\-]#',
'?', $atomname).
'" at offset: '.($atom_structure[
'offset'] + $atomoffset);
352 $atom_structure[
'data'] = null;
353 $atomoffset = strlen($atom_data);
356 $atomoffset += $boxsize;
361 $atom_structure[$boxtype] = substr($boxdata, 4);
367 switch ($atom_structure[
'flags_raw']) {
389 $atom_structure[
'data'] = empty($num) ?
'' : $num;
390 $atom_structure[
'data'] .= empty($num_total) ?
'' :
'/'.$num_total;
419 $atom_structure[
'data'] = substr($boxdata, 8);
440 $atom_structure[
'data'] = substr($boxdata, 8);
441 if ($atomname ==
'covr') {
443 if (preg_match(
'#^\xFF\xD8\xFF#', $atom_structure[
'data'])) {
444 $atom_structure[
'image_mime'] =
'image/jpeg';
445 } elseif (preg_match(
'#^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A#', $atom_structure[
'data'])) {
446 $atom_structure[
'image_mime'] =
'image/png';
447 } elseif (preg_match(
'#^GIF#', $atom_structure[
'data'])) {
448 $atom_structure[
'image_mime'] =
'image/gif';
457 $info[
'warning'][] =
'Unknown QuickTime box type: "'.preg_replace(
'#[^a-zA-Z0-9 _\\-]#',
'?', $boxtype).
'" ('.trim(
getid3_lib::PrintHexBytes($boxtype)).
') at offset '.$baseoffset;
458 $atom_structure[
'data'] = $atom_data;
471 $info[
'quicktime'][
'autoplay'] = $atom_structure[
'autoplay'];
492 $atom_structure[
'data'] = $atom_data;
501 $CompressedFileData = substr($atom_data, 4);
502 if ($UncompressedHeader = @gzuncompress($CompressedFileData)) {
505 $info[
'warning'][] =
'Error decompressing compressed MOV atom at offset '.$atom_structure[
'offset'];
511 $atom_structure[
'compression_id'] = $atom_data;
519 $atom_structure[
'flags'][
'internal_data'] = (bool) ($atom_structure[
'flags_raw'] & 0x000001);
521 $atom_structure[
'reference_type_name'] = substr($atom_data, 4, 4);
523 switch ($atom_structure[
'reference_type_name']) {
525 $atom_structure[
'url'] = $this->
NoNullString(substr($atom_data, 12));
529 $atom_structure[
'file_alias'] = substr($atom_data, 12);
533 $atom_structure[
'resource_alias'] = substr($atom_data, 12);
537 $atom_structure[
'data'] = substr($atom_data, 12);
558 $atom_structure[
'gestalt_selector'] = substr($atom_data, 4, 4);
568 $atom_structure[
'component_type'] = substr($atom_data, 4, 4);
569 $atom_structure[
'component_subtype'] = substr($atom_data, 8, 4);
570 $atom_structure[
'component_manufacturer'] = substr($atom_data, 12, 4);
582 $atom_structure[
'data_rate_bps'] = $atom_structure[
'data_rate'] * 10;
592 if (empty(
$info[
'comments'][
'language']) || (!in_array($atom_structure[
'language'],
$info[
'comments'][
'language']))) {
593 $info[
'comments'][
'language'][] = $atom_structure[
'language'];
613 $atom_structure[
'flags'][
'play_on_open'] = (bool) $atom_structure[
'play_on_open_flag'];
614 $atom_structure[
'flags'][
'slide_show'] = (bool) $atom_structure[
'slide_show_flag'];
616 $ptv_lookup[0] =
'normal';
617 $ptv_lookup[1] =
'double';
618 $ptv_lookup[2] =
'half';
619 $ptv_lookup[3] =
'full';
620 $ptv_lookup[4] =
'current';
621 if (isset($ptv_lookup[$atom_structure[
'display_size_raw']])) {
622 $atom_structure[
'display_size'] = $ptv_lookup[$atom_structure[
'display_size_raw']];
624 $info[
'warning'][] =
'unknown "ptv " display constant ('.$atom_structure[
'display_size_raw'].
')';
633 $stsdEntriesDataOffset = 8;
634 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++) {
635 $atom_structure[
'sample_description_table'][$i][
'size'] =
getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4));
636 $stsdEntriesDataOffset += 4;
637 $atom_structure[
'sample_description_table'][$i][
'data_format'] = substr($atom_data, $stsdEntriesDataOffset, 4);
638 $stsdEntriesDataOffset += 4;
639 $atom_structure[
'sample_description_table'][$i][
'reserved'] =
getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 6));
640 $stsdEntriesDataOffset += 6;
641 $atom_structure[
'sample_description_table'][$i][
'reference_index'] =
getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 2));
642 $stsdEntriesDataOffset += 2;
643 $atom_structure[
'sample_description_table'][$i][
'data'] = substr($atom_data, $stsdEntriesDataOffset, ($atom_structure[
'sample_description_table'][$i][
'size'] - 4 - 4 - 6 - 2));
644 $stsdEntriesDataOffset += ($atom_structure[
'sample_description_table'][$i][
'size'] - 4 - 4 - 6 - 2);
646 $atom_structure[
'sample_description_table'][$i][
'encoder_version'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 0, 2));
647 $atom_structure[
'sample_description_table'][$i][
'encoder_revision'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 2, 2));
648 $atom_structure[
'sample_description_table'][$i][
'encoder_vendor'] = substr($atom_structure[
'sample_description_table'][$i][
'data'], 4, 4);
650 switch ($atom_structure[
'sample_description_table'][$i][
'encoder_vendor']) {
652 case "\x00\x00\x00\x00":
654 $atom_structure[
'sample_description_table'][$i][
'audio_channels'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 8, 2));
655 $atom_structure[
'sample_description_table'][$i][
'audio_bit_depth'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 10, 2));
656 $atom_structure[
'sample_description_table'][$i][
'audio_compression_id'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 12, 2));
657 $atom_structure[
'sample_description_table'][$i][
'audio_packet_size'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 14, 2));
658 $atom_structure[
'sample_description_table'][$i][
'audio_sample_rate'] =
getid3_lib::FixedPoint16_16(substr($atom_structure[
'sample_description_table'][$i][
'data'], 16, 4));
662 $atom_structure[
'sample_description_table'][$i][
'temporal_quality'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 8, 4));
663 $atom_structure[
'sample_description_table'][$i][
'spatial_quality'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 12, 4));
664 $atom_structure[
'sample_description_table'][$i][
'width'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 16, 2));
665 $atom_structure[
'sample_description_table'][$i][
'height'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 18, 2));
666 $atom_structure[
'sample_description_table'][$i][
'resolution_x'] =
getid3_lib::FixedPoint16_16(substr($atom_structure[
'sample_description_table'][$i][
'data'], 24, 4));
667 $atom_structure[
'sample_description_table'][$i][
'resolution_y'] =
getid3_lib::FixedPoint16_16(substr($atom_structure[
'sample_description_table'][$i][
'data'], 28, 4));
668 $atom_structure[
'sample_description_table'][$i][
'data_size'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 32, 4));
669 $atom_structure[
'sample_description_table'][$i][
'frame_count'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 36, 2));
670 $atom_structure[
'sample_description_table'][$i][
'compressor_name'] = substr($atom_structure[
'sample_description_table'][$i][
'data'], 38, 4);
671 $atom_structure[
'sample_description_table'][$i][
'pixel_depth'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 42, 2));
672 $atom_structure[
'sample_description_table'][$i][
'color_table_id'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 44, 2));
674 switch ($atom_structure[
'sample_description_table'][$i][
'data_format']) {
701 $info[
'fileformat'] =
'mp4';
702 $info[
'video'][
'fourcc'] = $atom_structure[
'sample_description_table'][$i][
'data_format'];
705 if (!empty($atom_structure[
'sample_description_table'][$i][
'width']) && !empty($atom_structure[
'sample_description_table'][$i][
'height'])) {
707 $info[
'video'][
'resolution_x'] = $atom_structure[
'sample_description_table'][$i][
'width'];
708 $info[
'video'][
'resolution_y'] = $atom_structure[
'sample_description_table'][$i][
'height'];
709 $info[
'quicktime'][
'video'][
'resolution_x'] =
$info[
'video'][
'resolution_x'];
710 $info[
'quicktime'][
'video'][
'resolution_y'] =
$info[
'video'][
'resolution_y'];
715 $info[
'video'][
'dataformat'] =
'quicktimevr';
721 $info[
'quicktime'][
'audio'][
'sample_rate'] = $atom_structure[
'sample_description_table'][$i][
'audio_sample_rate'];
722 $info[
'quicktime'][
'audio'][
'channels'] = $atom_structure[
'sample_description_table'][$i][
'audio_channels'];
723 $info[
'quicktime'][
'audio'][
'bit_depth'] = $atom_structure[
'sample_description_table'][$i][
'audio_bit_depth'];
724 $info[
'audio'][
'codec'] =
$info[
'quicktime'][
'audio'][
'codec'];
725 $info[
'audio'][
'sample_rate'] =
$info[
'quicktime'][
'audio'][
'sample_rate'];
726 $info[
'audio'][
'channels'] =
$info[
'quicktime'][
'audio'][
'channels'];
727 $info[
'audio'][
'bits_per_sample'] =
$info[
'quicktime'][
'audio'][
'bit_depth'];
728 switch ($atom_structure[
'sample_description_table'][$i][
'data_format']) {
731 $info[
'audio'][
'lossless'] =
true;
734 $info[
'audio'][
'lossless'] =
false;
742 switch ($atom_structure[
'sample_description_table'][$i][
'data_format']) {
744 $info[
'fileformat'] =
'mp4';
749 $atom_structure[
'sample_description_table'][$i][
'video_temporal_quality'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 8, 4));
750 $atom_structure[
'sample_description_table'][$i][
'video_spatial_quality'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 12, 4));
751 $atom_structure[
'sample_description_table'][$i][
'video_frame_width'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 16, 2));
752 $atom_structure[
'sample_description_table'][$i][
'video_frame_height'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 18, 2));
753 $atom_structure[
'sample_description_table'][$i][
'video_resolution_x'] =
getid3_lib::FixedPoint16_16(substr($atom_structure[
'sample_description_table'][$i][
'data'], 20, 4));
754 $atom_structure[
'sample_description_table'][$i][
'video_resolution_y'] =
getid3_lib::FixedPoint16_16(substr($atom_structure[
'sample_description_table'][$i][
'data'], 24, 4));
755 $atom_structure[
'sample_description_table'][$i][
'video_data_size'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 28, 4));
756 $atom_structure[
'sample_description_table'][$i][
'video_frame_count'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 32, 2));
757 $atom_structure[
'sample_description_table'][$i][
'video_encoder_name_len'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 34, 1));
758 $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']);
759 $atom_structure[
'sample_description_table'][$i][
'video_pixel_color_depth'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 66, 2));
760 $atom_structure[
'sample_description_table'][$i][
'video_color_table_id'] =
getid3_lib::BigEndian2Int(substr($atom_structure[
'sample_description_table'][$i][
'data'], 68, 2));
762 $atom_structure[
'sample_description_table'][$i][
'video_pixel_color_type'] = (($atom_structure[
'sample_description_table'][$i][
'video_pixel_color_depth'] > 32) ?
'grayscale' :
'color');
763 $atom_structure[
'sample_description_table'][$i][
'video_pixel_color_name'] = $this->
QuicktimeColorNameLookup($atom_structure[
'sample_description_table'][$i][
'video_pixel_color_depth']);
765 if ($atom_structure[
'sample_description_table'][$i][
'video_pixel_color_name'] !=
'invalid') {
766 $info[
'quicktime'][
'video'][
'codec_fourcc'] = $atom_structure[
'sample_description_table'][$i][
'data_format'];
767 $info[
'quicktime'][
'video'][
'codec_fourcc_lookup'] = $this->
QuicktimeVideoCodecLookup($atom_structure[
'sample_description_table'][$i][
'data_format']);
768 $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']);
769 $info[
'quicktime'][
'video'][
'color_depth'] = $atom_structure[
'sample_description_table'][$i][
'video_pixel_color_depth'];
770 $info[
'quicktime'][
'video'][
'color_depth_name'] = $atom_structure[
'sample_description_table'][$i][
'video_pixel_color_name'];
772 $info[
'video'][
'codec'] =
$info[
'quicktime'][
'video'][
'codec'];
773 $info[
'video'][
'bits_per_sample'] =
$info[
'quicktime'][
'video'][
'color_depth'];
775 $info[
'video'][
'lossless'] =
false;
776 $info[
'video'][
'pixel_aspect_ratio'] = (float) 1;
781 switch (strtolower($atom_structure[
'sample_description_table'][$i][
'data_format'])) {
783 $info[
'audio'][
'dataformat'] =
'mp4';
784 $info[
'quicktime'][
'audio'][
'codec'] =
'mp4';
790 $info[
'video'][
'dataformat'] =
'3ivx';
794 $info[
'video'][
'dataformat'] =
'xvid';
798 $info[
'video'][
'dataformat'] =
'mpeg4';
808 $info[
'video'][
'dataformat'] =
'divx';
815 unset($atom_structure[
'sample_description_table'][$i][
'data']);
824 $sttsEntriesDataOffset = 8;
828 $max_stts_entries_to_scan = (
$info[
'php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure[
'number_entries']) : $atom_structure[
'number_entries']);
829 if ($max_stts_entries_to_scan < $atom_structure[
'number_entries']) {
830 $info[
'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).';
832 for ($i = 0; $i < $max_stts_entries_to_scan; $i++) {
833 $atom_structure[
'time_to_sample_table'][$i][
'sample_count'] =
getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
834 $sttsEntriesDataOffset += 4;
835 $atom_structure[
'time_to_sample_table'][$i][
'sample_duration'] =
getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
836 $sttsEntriesDataOffset += 4;
838 $frames_count += $atom_structure[
'time_to_sample_table'][$i][
'sample_count'];
851 $info[
'quicktime'][
'stts_framecount'][] = $frames_count;
877 $stssEntriesDataOffset = 8;
878 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++) {
880 $stssEntriesDataOffset += 4;
891 $stscEntriesDataOffset = 8;
892 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++) {
893 $atom_structure[
'sample_to_chunk_table'][$i][
'first_chunk'] =
getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
894 $stscEntriesDataOffset += 4;
895 $atom_structure[
'sample_to_chunk_table'][$i][
'samples_per_chunk'] =
getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
896 $stscEntriesDataOffset += 4;
897 $atom_structure[
'sample_to_chunk_table'][$i][
'sample_description'] =
getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
898 $stscEntriesDataOffset += 4;
910 $stszEntriesDataOffset = 12;
911 if ($atom_structure[
'sample_size'] == 0) {
912 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++) {
914 $stszEntriesDataOffset += 4;
926 $stcoEntriesDataOffset = 8;
927 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++) {
929 $stcoEntriesDataOffset += 4;
940 $stcoEntriesDataOffset = 8;
941 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++) {
943 $stcoEntriesDataOffset += 8;
954 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++) {
956 $drefDataOffset += 4;
957 $atom_structure[
'data_references'][$i][
'type'] = substr($atom_data, $drefDataOffset, 4);
958 $drefDataOffset += 4;
960 $drefDataOffset += 1;
962 $drefDataOffset += 3;
963 $atom_structure[
'data_references'][$i][
'data'] = substr($atom_data, $drefDataOffset, ($atom_structure[
'data_references'][$i][
'size'] - 4 - 4 - 1 - 3));
964 $drefDataOffset += ($atom_structure[
'data_references'][$i][
'size'] - 4 - 4 - 1 - 3);
966 $atom_structure[
'data_references'][$i][
'flags'][
'self_reference'] = (bool) ($atom_structure[
'data_references'][$i][
'flags_raw'] & 0x001);
999 $atom_structure[
'flags'][
'no_lean_ahead'] = (bool) ($atom_structure[
'flags_raw'] & 0x001);
1006 $atom_structure[
'component_type'] = substr($atom_data, 4, 4);
1007 $atom_structure[
'component_subtype'] = substr($atom_data, 8, 4);
1008 $atom_structure[
'component_manufacturer'] = substr($atom_data, 12, 4);
1011 $atom_structure[
'component_name'] = $this->
Pascal2String(substr($atom_data, 24));
1013 if (($atom_structure[
'component_subtype'] ==
'STpn') && ($atom_structure[
'component_manufacturer'] ==
'zzzz')) {
1014 $info[
'video'][
'dataformat'] =
'quicktimevr';
1029 if ($atom_structure[
'time_scale'] == 0) {
1030 $info[
'error'][] =
'Corrupt Quicktime file: mdhd.time_scale == zero';
1033 $info[
'quicktime'][
'time_scale'] = (isset(
$info[
'quicktime'][
'time_scale']) ? max(
$info[
'quicktime'][
'time_scale'], $atom_structure[
'time_scale']) : $atom_structure[
'time_scale']);
1037 $atom_structure[
'playtime_seconds'] = $atom_structure[
'duration'] / $atom_structure[
'time_scale'];
1039 if (empty(
$info[
'comments'][
'language']) || (!in_array($atom_structure[
'language'],
$info[
'comments'][
'language']))) {
1040 $info[
'comments'][
'language'][] = $atom_structure[
'language'];
1048 $atom_structure[
'atom_type'] = substr($atom_data, 6, 4);
1058 $atom_structure[
'clipping_data'] = substr($atom_data, 10);
1068 $atom_structure[
'default_hints'][
'double_buffer'] = (bool) ($atom_structure[
'default_hints_raw'] & 0x0020);
1069 $atom_structure[
'default_hints'][
'high_quality'] = (bool) ($atom_structure[
'default_hints_raw'] & 0x0100);
1078 for ($i = 0; $i < strlen($atom_data); $i += 4) {
1088 for ($i = 0; $i < $atom_structure[
'number_entries']; $i++ ) {
1089 $atom_structure[
'edit_list'][$i][
'track_duration'] =
getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 0, 4));
1099 $atom_structure[
'matte_data_raw'] = substr($atom_data, 4);
1107 for ($colortableentry = 0; $colortableentry < $atom_structure[
'color_table_size']; $colortableentry++) {
1108 $atom_structure[
'color_table'][$colortableentry][
'alpha'] =
getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 0, 2));
1109 $atom_structure[
'color_table'][$colortableentry][
'red'] =
getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 2, 2));
1110 $atom_structure[
'color_table'][$colortableentry][
'green'] =
getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 4, 2));
1111 $atom_structure[
'color_table'][$colortableentry][
'blue'] =
getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 6, 2));
1125 $atom_structure[
'reserved'] = substr($atom_data, 26, 10);
1143 if ($atom_structure[
'time_scale'] == 0) {
1144 $info[
'error'][] =
'Corrupt Quicktime file: mvhd.time_scale == zero';
1149 $info[
'quicktime'][
'time_scale'] = (isset(
$info[
'quicktime'][
'time_scale']) ? max(
$info[
'quicktime'][
'time_scale'], $atom_structure[
'time_scale']) : $atom_structure[
'time_scale']);
1150 $info[
'quicktime'][
'display_scale'] = $atom_structure[
'matrix_a'];
1151 $info[
'playtime_seconds'] = $atom_structure[
'duration'] / $atom_structure[
'time_scale'];
1181 $atom_structure[
'flags'][
'enabled'] = (bool) ($atom_structure[
'flags_raw'] & 0x0001);
1182 $atom_structure[
'flags'][
'in_movie'] = (bool) ($atom_structure[
'flags_raw'] & 0x0002);
1183 $atom_structure[
'flags'][
'in_preview'] = (bool) ($atom_structure[
'flags_raw'] & 0x0004);
1184 $atom_structure[
'flags'][
'in_poster'] = (bool) ($atom_structure[
'flags_raw'] & 0x0008);
1188 if ($atom_structure[
'flags'][
'enabled'] == 1) {
1189 if (!isset(
$info[
'video'][
'resolution_x']) || !isset(
$info[
'video'][
'resolution_y'])) {
1190 $info[
'video'][
'resolution_x'] = $atom_structure[
'width'];
1191 $info[
'video'][
'resolution_y'] = $atom_structure[
'height'];
1193 $info[
'video'][
'resolution_x'] = max(
$info[
'video'][
'resolution_x'], $atom_structure[
'width']);
1194 $info[
'video'][
'resolution_y'] = max(
$info[
'video'][
'resolution_y'], $atom_structure[
'height']);
1195 $info[
'quicktime'][
'video'][
'resolution_x'] =
$info[
'video'][
'resolution_x'];
1196 $info[
'quicktime'][
'video'][
'resolution_y'] =
$info[
'video'][
'resolution_y'];
1231 $atom_structure[
'num_iods_tracks'] = ($atom_structure[
'length'] - 7) / 6;
1232 for ($i = 0; $i < $atom_structure[
'num_iods_tracks']; $i++) {
1246 $atom_structure[
'signature'] = substr($atom_data, 0, 4);
1248 $atom_structure[
'fourcc'] = substr($atom_data, 8, 4);
1259 if (substr($atom_data, $mdat_offset, 8) ==
"\x00\x00\x00\x08".
'wide') {
1261 } elseif (substr($atom_data, $mdat_offset, 8) ==
"\x00\x00\x00\x00".
'mdat') {
1270 && ($chapter_string_length < 1000)
1271 && ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2))
1272 && preg_match(
'#^[\x20-\xFF]+$#', substr($atom_data, $mdat_offset + 2, $chapter_string_length), $chapter_matches)) {
1273 $mdat_offset += (2 + $chapter_string_length);
1274 @
$info[
'quicktime'][
'comments'][
'chapters'][] = $chapter_matches[0];
1279 if (($atomsize > 8) && (!isset(
$info[
'avdataend_tmp']) || (
$info[
'quicktime'][$atomname][
'size'] > (
$info[
'avdataend_tmp'] -
$info[
'avdataoffset'])))) {
1281 $info[
'avdataoffset'] = $atom_structure[
'offset'] + 8;
1282 $OldAVDataEnd =
$info[
'avdataend'];
1283 $info[
'avdataend'] = $atom_structure[
'offset'] + $atom_structure[
'size'];
1285 $getid3_temp =
new getID3();
1286 $getid3_temp->openfile($this->getid3->filename);
1287 $getid3_temp->info[
'avdataoffset'] =
$info[
'avdataoffset'];
1288 $getid3_temp->info[
'avdataend'] =
$info[
'avdataend'];
1290 if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode($this->fread(4)))) {
1291 $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info[
'avdataoffset'],
false);
1292 if (!empty($getid3_temp->info[
'warning'])) {
1293 foreach ($getid3_temp->info[
'warning'] as $value) {
1294 $info[
'warning'][] = $value;
1297 if (!empty($getid3_temp->info[
'mpeg'])) {
1298 $info[
'mpeg'] = $getid3_temp->info[
'mpeg'];
1299 if (isset(
$info[
'mpeg'][
'audio'])) {
1300 $info[
'audio'][
'dataformat'] =
'mp3';
1301 $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')));
1302 $info[
'audio'][
'sample_rate'] =
$info[
'mpeg'][
'audio'][
'sample_rate'];
1303 $info[
'audio'][
'channels'] =
$info[
'mpeg'][
'audio'][
'channels'];
1304 $info[
'audio'][
'bitrate'] =
$info[
'mpeg'][
'audio'][
'bitrate'];
1305 $info[
'audio'][
'bitrate_mode'] = strtolower(
$info[
'mpeg'][
'audio'][
'bitrate_mode']);
1306 $info[
'bitrate'] =
$info[
'audio'][
'bitrate'];
1310 unset($getid3_mp3, $getid3_temp);
1311 $info[
'avdataend'] = $OldAVDataEnd;
1312 unset($OldAVDataEnd);
1316 unset($mdat_offset, $chapter_string_length, $chapter_matches);
1344 $atom_structure[
'ctyp'] = substr($atom_data, 0, 4);
1345 $info[
'quicktime'][
'controller'] = $atom_structure[
'ctyp'];
1346 switch ($atom_structure[
'ctyp']) {
1348 $info[
'video'][
'dataformat'] =
'quicktimevr';
1361 $info[
'quicktime'][
'hinting'] =
true;
1365 for ($i = 0; $i < ($atom_structure[
'size'] - 8); $i += 4) {
1388 $atom_structure[
'data'] = $atom_data;
1389 if (preg_match(
'#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) {
1390 @list($all, $latitude, $longitude, $altitude) = $matches;
1391 $info[
'quicktime'][
'comments'][
'gps_latitude'][] = floatval($latitude);
1392 $info[
'quicktime'][
'comments'][
'gps_longitude'][] = floatval($longitude);
1393 if (!empty($altitude)) {
1394 $info[
'quicktime'][
'comments'][
'gps_altitude'][] = floatval($altitude);
1397 $info[
'warning'][] =
'QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.
'. Please report as getID3() bug.';
1409 if (preg_match(
'/^\xFF\xD8\xFF/', $atom_data)) {
1410 $atom_structure[
'data'] = $atom_data;
1411 $atom_structure[
'image_mime'] =
'image/jpeg';
1412 $atom_structure[
'description'] = (($atomname ==
'NCTH') ?
'Nikon Camera Thumbnail Image' : (($atomname ==
'NCVW') ?
'Nikon Camera Preview Image' :
'Nikon preview image'));
1413 $info[
'quicktime'][
'comments'][
'picture'][] = array(
'image_mime'=>$atom_structure[
'image_mime'],
'data'=>$atom_data,
'description'=>$atom_structure[
'description']);
1422 $atom_structure[
'data'] = $atom_data;
1425 case "\x00\x00\x00\x00":
1439 $atom_structure[
'language'] = substr($atom_data, 4 + 0, 2);
1441 $atom_structure[
'data'] = substr($atom_data, 4 + 4);
1445 $info[
'warning'][] =
'Unknown QuickTime atom type: "'.preg_replace(
'#[^a-zA-Z0-9 _\\-]#',
'?', $atomname).
'" ('.trim(
getid3_lib::PrintHexBytes($atomname)).
') at offset '.$baseoffset;
1446 $atom_structure[
'data'] = $atom_data;
1449 array_pop($atomHierarchy);
1450 return $atom_structure;
QuicktimeSTIKLookup($stik)
QuicktimeIODSaudioProfileName($audio_profile_id)
CopyToAppropriateCommentsSection($keyname, $data, &$ThisFileInfo)
QuicktimeAudioCodecLookup($codecid)
QuicktimeStoreFrontCodeLookup($sfid)
QuicktimeIODSvideoProfileName($video_profile_id)
quicktime_read_mp4_descr_length($data, &$offset)
FixedPoint16_16($rawdata)
QuicktimeColorNameLookup($colordepthid)
NoNullString($nullterminatedstring)
Pascal2String($pascalstring)
QuicktimeContentRatingLookup($rtng)
QuicktimeLanguageLookup($languageid)
QuicktimeParseContainerAtom($atomdata, &$ThisFileInfo, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms)
BigEndian2Int($byteword, $synchsafe=false, $signed=false)
QuicktimeVideoCodecLookup($codecid)
PrintHexBytes($string, $hex=true, $spaces=true, $htmlsafe=true)
QuicktimeDCOMLookup($compressionid)
LookupGenreName($genreid, $allowSCMPXextended=true)
QuicktimeParseNikonNCTG($atom_data)