28 |
29 |
29 $info['fileformat'] = 'quicktime'; |
30 $info['fileformat'] = 'quicktime'; |
30 $info['quicktime']['hinting'] = false; |
31 $info['quicktime']['hinting'] = false; |
31 $info['quicktime']['controller'] = 'standard'; // may be overridden if 'ctyp' atom is present |
32 $info['quicktime']['controller'] = 'standard'; // may be overridden if 'ctyp' atom is present |
32 |
33 |
33 fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET); |
34 $this->fseek($info['avdataoffset']); |
34 |
35 |
35 $offset = 0; |
36 $offset = 0; |
36 $atomcounter = 0; |
37 $atomcounter = 0; |
37 |
38 |
38 while ($offset < $info['avdataend']) { |
39 while ($offset < $info['avdataend']) { |
39 if (!getid3_lib::intValueSupported($offset)) { |
40 if (!getid3_lib::intValueSupported($offset)) { |
40 $info['error'][] = 'Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions'; |
41 $info['error'][] = 'Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions'; |
41 break; |
42 break; |
42 } |
43 } |
43 fseek($this->getid3->fp, $offset, SEEK_SET); |
44 $this->fseek($offset); |
44 $AtomHeader = fread($this->getid3->fp, 8); |
45 $AtomHeader = $this->fread(8); |
45 |
46 |
46 $atomsize = getid3_lib::BigEndian2Int(substr($AtomHeader, 0, 4)); |
47 $atomsize = getid3_lib::BigEndian2Int(substr($AtomHeader, 0, 4)); |
47 $atomname = substr($AtomHeader, 4, 4); |
48 $atomname = substr($AtomHeader, 4, 4); |
48 |
49 |
49 // 64-bit MOV patch by jlegateØktnc*com |
50 // 64-bit MOV patch by jlegateØktnc*com |
50 if ($atomsize == 1) { |
51 if ($atomsize == 1) { |
51 $atomsize = getid3_lib::BigEndian2Int(fread($this->getid3->fp, 8)); |
52 $atomsize = getid3_lib::BigEndian2Int($this->fread(8)); |
52 } |
53 } |
53 |
54 |
54 $info['quicktime'][$atomname]['name'] = $atomname; |
55 $info['quicktime'][$atomname]['name'] = $atomname; |
55 $info['quicktime'][$atomname]['size'] = $atomsize; |
56 $info['quicktime'][$atomname]['size'] = $atomsize; |
56 $info['quicktime'][$atomname]['offset'] = $offset; |
57 $info['quicktime'][$atomname]['offset'] = $offset; |
64 // Furthermore, for historical reasons the list of atoms is optionally |
65 // Furthermore, for historical reasons the list of atoms is optionally |
65 // terminated by a 32-bit integer set to 0. If you are writing a program |
66 // terminated by a 32-bit integer set to 0. If you are writing a program |
66 // to read user data atoms, you should allow for the terminating 0. |
67 // to read user data atoms, you should allow for the terminating 0. |
67 break; |
68 break; |
68 } |
69 } |
69 switch ($atomname) { |
70 $atomHierarchy = array(); |
70 case 'mdat': // Media DATa atom |
71 $info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, $this->fread(min($atomsize, round($this->getid3->memory_limit / 2))), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms); |
71 // 'mdat' contains the actual data for the audio/video |
|
72 if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) { |
|
73 |
|
74 $info['avdataoffset'] = $info['quicktime'][$atomname]['offset'] + 8; |
|
75 $OldAVDataEnd = $info['avdataend']; |
|
76 $info['avdataend'] = $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size']; |
|
77 |
|
78 $getid3_temp = new getID3(); |
|
79 $getid3_temp->openfile($this->getid3->filename); |
|
80 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; |
|
81 $getid3_temp->info['avdataend'] = $info['avdataend']; |
|
82 $getid3_mp3 = new getid3_mp3($getid3_temp); |
|
83 if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode(fread($this->getid3->fp, 4)))) { |
|
84 $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); |
|
85 if (!empty($getid3_temp->info['warning'])) { |
|
86 foreach ($getid3_temp->info['warning'] as $value) { |
|
87 $info['warning'][] = $value; |
|
88 } |
|
89 } |
|
90 if (!empty($getid3_temp->info['mpeg'])) { |
|
91 $info['mpeg'] = $getid3_temp->info['mpeg']; |
|
92 if (isset($info['mpeg']['audio'])) { |
|
93 $info['audio']['dataformat'] = 'mp3'; |
|
94 $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'))); |
|
95 $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; |
|
96 $info['audio']['channels'] = $info['mpeg']['audio']['channels']; |
|
97 $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; |
|
98 $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); |
|
99 $info['bitrate'] = $info['audio']['bitrate']; |
|
100 } |
|
101 } |
|
102 } |
|
103 unset($getid3_mp3, $getid3_temp); |
|
104 $info['avdataend'] = $OldAVDataEnd; |
|
105 unset($OldAVDataEnd); |
|
106 |
|
107 } |
|
108 break; |
|
109 |
|
110 case 'free': // FREE space atom |
|
111 case 'skip': // SKIP atom |
|
112 case 'wide': // 64-bit expansion placeholder atom |
|
113 // 'free', 'skip' and 'wide' are just padding, contains no useful data at all |
|
114 break; |
|
115 |
|
116 default: |
|
117 $atomHierarchy = array(); |
|
118 $info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, fread($this->getid3->fp, $atomsize), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms); |
|
119 break; |
|
120 } |
|
121 |
72 |
122 $offset += $atomsize; |
73 $offset += $atomsize; |
123 $atomcounter++; |
74 $atomcounter++; |
124 } |
75 } |
125 |
76 |
170 public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) { |
121 public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) { |
171 // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm |
122 // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm |
172 |
123 |
173 $info = &$this->getid3->info; |
124 $info = &$this->getid3->info; |
174 |
125 |
175 //$atom_parent = array_pop($atomHierarchy); |
126 $atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see http://www.getid3.org/phpBB3/viewtopic.php?t=1717 |
176 $atom_parent = end($atomHierarchy); // http://www.getid3.org/phpBB3/viewtopic.php?t=1717 |
|
177 array_push($atomHierarchy, $atomname); |
127 array_push($atomHierarchy, $atomname); |
178 $atom_structure['hierarchy'] = implode(' ', $atomHierarchy); |
128 $atom_structure['hierarchy'] = implode(' ', $atomHierarchy); |
179 $atom_structure['name'] = $atomname; |
129 $atom_structure['name'] = $atomname; |
180 $atom_structure['size'] = $atomsize; |
130 $atom_structure['size'] = $atomsize; |
181 $atom_structure['offset'] = $baseoffset; |
131 $atom_structure['offset'] = $baseoffset; |
182 //echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8)).'<br>'; |
|
183 //echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8), false).'<br><br>'; |
|
184 switch ($atomname) { |
132 switch ($atomname) { |
185 case 'moov': // MOVie container atom |
133 case 'moov': // MOVie container atom |
186 case 'trak': // TRAcK container atom |
134 case 'trak': // TRAcK container atom |
187 case 'clip': // CLIPping container atom |
135 case 'clip': // CLIPping container atom |
188 case 'matt': // track MATTe container atom |
136 case 'matt': // track MATTe container atom |
198 case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR) |
146 case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR) |
199 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); |
147 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); |
200 break; |
148 break; |
201 |
149 |
202 case 'ilst': // Item LiST container atom |
150 case 'ilst': // Item LiST container atom |
203 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); |
151 if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) { |
204 |
152 // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted |
205 // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted |
153 $allnumericnames = true; |
206 $allnumericnames = true; |
|
207 foreach ($atom_structure['subatoms'] as $subatomarray) { |
|
208 if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) { |
|
209 $allnumericnames = false; |
|
210 break; |
|
211 } |
|
212 } |
|
213 if ($allnumericnames) { |
|
214 $newData = array(); |
|
215 foreach ($atom_structure['subatoms'] as $subatomarray) { |
154 foreach ($atom_structure['subatoms'] as $subatomarray) { |
216 foreach ($subatomarray['subatoms'] as $newData_subatomarray) { |
155 if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) { |
217 unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']); |
156 $allnumericnames = false; |
218 $newData[$subatomarray['name']] = $newData_subatomarray; |
|
219 break; |
157 break; |
220 } |
158 } |
221 } |
159 } |
222 $atom_structure['data'] = $newData; |
160 if ($allnumericnames) { |
223 unset($atom_structure['subatoms']); |
161 $newData = array(); |
|
162 foreach ($atom_structure['subatoms'] as $subatomarray) { |
|
163 foreach ($subatomarray['subatoms'] as $newData_subatomarray) { |
|
164 unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']); |
|
165 $newData[$subatomarray['name']] = $newData_subatomarray; |
|
166 break; |
|
167 } |
|
168 } |
|
169 $atom_structure['data'] = $newData; |
|
170 unset($atom_structure['subatoms']); |
|
171 } |
224 } |
172 } |
225 break; |
173 break; |
226 |
174 |
227 case "\x00\x00\x00\x01": |
175 case "\x00\x00\x00\x01": |
228 case "\x00\x00\x00\x02": |
176 case "\x00\x00\x00\x02": |
306 case 'cmID': |
254 case 'cmID': |
307 case 'cnID': |
255 case 'cnID': |
308 case 'geID': |
256 case 'geID': |
309 case 'plID': |
257 case 'plID': |
310 case 'sfID': // iTunes store country |
258 case 'sfID': // iTunes store country |
311 case '©alb': // ALBum |
259 case "\xA9".'alb': // ALBum |
312 case '©art': // ARTist |
260 case "\xA9".'art': // ARTist |
313 case '©ART': |
261 case "\xA9".'ART': |
314 case '©aut': |
262 case "\xA9".'aut': |
315 case '©cmt': // CoMmenT |
263 case "\xA9".'cmt': // CoMmenT |
316 case '©com': // COMposer |
264 case "\xA9".'com': // COMposer |
317 case '©cpy': |
265 case "\xA9".'cpy': |
318 case '©day': // content created year |
266 case "\xA9".'day': // content created year |
319 case '©dir': |
267 case "\xA9".'dir': |
320 case '©ed1': |
268 case "\xA9".'ed1': |
321 case '©ed2': |
269 case "\xA9".'ed2': |
322 case '©ed3': |
270 case "\xA9".'ed3': |
323 case '©ed4': |
271 case "\xA9".'ed4': |
324 case '©ed5': |
272 case "\xA9".'ed5': |
325 case '©ed6': |
273 case "\xA9".'ed6': |
326 case '©ed7': |
274 case "\xA9".'ed7': |
327 case '©ed8': |
275 case "\xA9".'ed8': |
328 case '©ed9': |
276 case "\xA9".'ed9': |
329 case '©enc': |
277 case "\xA9".'enc': |
330 case '©fmt': |
278 case "\xA9".'fmt': |
331 case '©gen': // GENre |
279 case "\xA9".'gen': // GENre |
332 case '©grp': // GRouPing |
280 case "\xA9".'grp': // GRouPing |
333 case '©hst': |
281 case "\xA9".'hst': |
334 case '©inf': |
282 case "\xA9".'inf': |
335 case '©lyr': // LYRics |
283 case "\xA9".'lyr': // LYRics |
336 case '©mak': |
284 case "\xA9".'mak': |
337 case '©mod': |
285 case "\xA9".'mod': |
338 case '©nam': // full NAMe |
286 case "\xA9".'nam': // full NAMe |
339 case '©ope': |
287 case "\xA9".'ope': |
340 case '©PRD': |
288 case "\xA9".'PRD': |
341 case '©prd': |
289 case "\xA9".'prd': |
342 case '©prf': |
290 case "\xA9".'prf': |
343 case '©req': |
291 case "\xA9".'req': |
344 case '©src': |
292 case "\xA9".'src': |
345 case '©swr': |
293 case "\xA9".'swr': |
346 case '©too': // encoder |
294 case "\xA9".'too': // encoder |
347 case '©trk': // TRacK |
295 case "\xA9".'trk': // TRacK |
348 case '©url': |
296 case "\xA9".'url': |
349 case '©wrn': |
297 case "\xA9".'wrn': |
350 case '©wrt': // WRiTer |
298 case "\xA9".'wrt': // WRiTer |
351 case '----': // itunes specific |
299 case '----': // itunes specific |
352 if ($atom_parent == 'udta') { |
300 if ($atom_parent == 'udta') { |
353 // User data atom handler |
301 // User data atom handler |
354 $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); |
302 $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); |
355 $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); |
303 $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); |
368 while ($atomoffset < strlen($atom_data)) { |
316 while ($atomoffset < strlen($atom_data)) { |
369 $boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 2)); |
317 $boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 2)); |
370 $boxsmalltype = substr($atom_data, $atomoffset + 2, 2); |
318 $boxsmalltype = substr($atom_data, $atomoffset + 2, 2); |
371 $boxsmalldata = substr($atom_data, $atomoffset + 4, $boxsmallsize); |
319 $boxsmalldata = substr($atom_data, $atomoffset + 4, $boxsmallsize); |
372 if ($boxsmallsize <= 1) { |
320 if ($boxsmallsize <= 1) { |
373 $info['warning'][] = 'Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.$atomname.'" at offset: '.($atom_structure['offset'] + $atomoffset); |
321 $info['warning'][] = 'Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset); |
374 $atom_structure['data'] = null; |
322 $atom_structure['data'] = null; |
375 $atomoffset = strlen($atom_data); |
323 $atomoffset = strlen($atom_data); |
376 break; |
324 break; |
377 } |
325 } |
378 switch ($boxsmalltype) { |
326 switch ($boxsmalltype) { |
379 case "\x10\xB5": |
327 case "\x10\xB5": |
380 $atom_structure['data'] = $boxsmalldata; |
328 $atom_structure['data'] = $boxsmalldata; |
381 break; |
329 break; |
382 default: |
330 default: |
383 $info['warning'][] = 'Unknown QuickTime smallbox type: "'.getid3_lib::PrintHexBytes($boxsmalltype).'" at offset '.$baseoffset; |
331 $info['warning'][] = 'Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset; |
384 $atom_structure['data'] = $atom_data; |
332 $atom_structure['data'] = $atom_data; |
385 break; |
333 break; |
386 } |
334 } |
387 $atomoffset += (4 + $boxsmallsize); |
335 $atomoffset += (4 + $boxsmallsize); |
388 } |
336 } |
838 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 |
796 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 |
839 $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); |
797 $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); |
840 $sttsEntriesDataOffset = 8; |
798 $sttsEntriesDataOffset = 8; |
841 //$FrameRateCalculatorArray = array(); |
799 //$FrameRateCalculatorArray = array(); |
842 $frames_count = 0; |
800 $frames_count = 0; |
843 for ($i = 0; $i < $atom_structure['number_entries']; $i++) { |
801 |
|
802 $max_stts_entries_to_scan = min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']); |
|
803 if ($max_stts_entries_to_scan < $atom_structure['number_entries']) { |
|
804 $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($this->getid3->memory_limit / 1048576).'MB).'; |
|
805 } |
|
806 for ($i = 0; $i < $max_stts_entries_to_scan; $i++) { |
844 $atom_structure['time_to_sample_table'][$i]['sample_count'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); |
807 $atom_structure['time_to_sample_table'][$i]['sample_count'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); |
845 $sttsEntriesDataOffset += 4; |
808 $sttsEntriesDataOffset += 4; |
846 $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); |
809 $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); |
847 $sttsEntriesDataOffset += 4; |
810 $sttsEntriesDataOffset += 4; |
848 |
811 |
1258 $atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); |
1221 $atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); |
1259 $atom_structure['fourcc'] = substr($atom_data, 8, 4); |
1222 $atom_structure['fourcc'] = substr($atom_data, 8, 4); |
1260 break; |
1223 break; |
1261 |
1224 |
1262 case 'mdat': // Media DATa atom |
1225 case 'mdat': // Media DATa atom |
|
1226 // 'mdat' contains the actual data for the audio/video, possibly also subtitles |
|
1227 |
|
1228 /* due to lack of known documentation, this is a kludge implementation. If you know of documentation on how mdat is properly structed, please send it to info@getid3.org */ |
|
1229 |
|
1230 // first, skip any 'wide' padding, and second 'mdat' header (with specified size of zero?) |
|
1231 $mdat_offset = 0; |
|
1232 while (true) { |
|
1233 if (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x08".'wide') { |
|
1234 $mdat_offset += 8; |
|
1235 } elseif (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x00".'mdat') { |
|
1236 $mdat_offset += 8; |
|
1237 } else { |
|
1238 break; |
|
1239 } |
|
1240 } |
|
1241 |
|
1242 // check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field |
|
1243 while (($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2))) |
|
1244 && ($chapter_string_length < 1000) |
|
1245 && ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2)) |
|
1246 && preg_match('#^[\x20-\xFF]+$#', substr($atom_data, $mdat_offset + 2, $chapter_string_length), $chapter_matches)) { |
|
1247 $mdat_offset += (2 + $chapter_string_length); |
|
1248 @$info['quicktime']['comments']['chapters'][] = $chapter_matches[0]; |
|
1249 } |
|
1250 |
|
1251 |
|
1252 |
|
1253 if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) { |
|
1254 |
|
1255 $info['avdataoffset'] = $atom_structure['offset'] + 8; // $info['quicktime'][$atomname]['offset'] + 8; |
|
1256 $OldAVDataEnd = $info['avdataend']; |
|
1257 $info['avdataend'] = $atom_structure['offset'] + $atom_structure['size']; // $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size']; |
|
1258 |
|
1259 $getid3_temp = new getID3(); |
|
1260 $getid3_temp->openfile($this->getid3->filename); |
|
1261 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; |
|
1262 $getid3_temp->info['avdataend'] = $info['avdataend']; |
|
1263 $getid3_mp3 = new getid3_mp3($getid3_temp); |
|
1264 if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode($this->fread(4)))) { |
|
1265 $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); |
|
1266 if (!empty($getid3_temp->info['warning'])) { |
|
1267 foreach ($getid3_temp->info['warning'] as $value) { |
|
1268 $info['warning'][] = $value; |
|
1269 } |
|
1270 } |
|
1271 if (!empty($getid3_temp->info['mpeg'])) { |
|
1272 $info['mpeg'] = $getid3_temp->info['mpeg']; |
|
1273 if (isset($info['mpeg']['audio'])) { |
|
1274 $info['audio']['dataformat'] = 'mp3'; |
|
1275 $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'))); |
|
1276 $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; |
|
1277 $info['audio']['channels'] = $info['mpeg']['audio']['channels']; |
|
1278 $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; |
|
1279 $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); |
|
1280 $info['bitrate'] = $info['audio']['bitrate']; |
|
1281 } |
|
1282 } |
|
1283 } |
|
1284 unset($getid3_mp3, $getid3_temp); |
|
1285 $info['avdataend'] = $OldAVDataEnd; |
|
1286 unset($OldAVDataEnd); |
|
1287 |
|
1288 } |
|
1289 |
|
1290 unset($mdat_offset, $chapter_string_length, $chapter_matches); |
|
1291 break; |
|
1292 |
1263 case 'free': // FREE space atom |
1293 case 'free': // FREE space atom |
1264 case 'skip': // SKIP atom |
1294 case 'skip': // SKIP atom |
1265 case 'wide': // 64-bit expansion placeholder atom |
1295 case 'wide': // 64-bit expansion placeholder atom |
1266 // 'mdat' data is too big to deal with, contains no useful metadata |
|
1267 // 'free', 'skip' and 'wide' are just padding, contains no useful data at all |
1296 // 'free', 'skip' and 'wide' are just padding, contains no useful data at all |
1268 |
1297 |
1269 // When writing QuickTime files, it is sometimes necessary to update an atom's size. |
1298 // When writing QuickTime files, it is sometimes necessary to update an atom's size. |
1270 // It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom |
1299 // It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom |
1271 // is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime |
1300 // is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime |
1356 $atom_structure['image_mime'] = 'image/jpeg'; |
1385 $atom_structure['image_mime'] = 'image/jpeg'; |
1357 $atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image')); |
1386 $atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image')); |
1358 $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']); |
1387 $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']); |
1359 } |
1388 } |
1360 break; |
1389 break; |
1361 case 'NCHD': // MakerNoteVersion |
1390 case 'NCTG': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG |
1362 // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html |
|
1363 $atom_structure['data'] = $atom_data; |
|
1364 break; |
|
1365 case 'NCTG': // NikonTags |
|
1366 // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG |
|
1367 $atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data); |
1391 $atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data); |
1368 break; |
1392 break; |
1369 case 'NCDB': // NikonTags |
1393 case 'NCHD': // Nikon:MakerNoteVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html |
1370 // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html |
1394 case 'NCDB': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html |
|
1395 case 'CNCV': // Canon:CompressorVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html |
1371 $atom_structure['data'] = $atom_data; |
1396 $atom_structure['data'] = $atom_data; |
1372 break; |
1397 break; |
1373 |
1398 |
1374 case "\x00\x00\x00\x00": |
1399 case "\x00\x00\x00\x00": |
1375 case 'meta': // METAdata atom |
1400 case 'meta': // METAdata atom |
2084 |
2109 |
2085 |
2110 |
2086 public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') { |
2111 public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') { |
2087 static $handyatomtranslatorarray = array(); |
2112 static $handyatomtranslatorarray = array(); |
2088 if (empty($handyatomtranslatorarray)) { |
2113 if (empty($handyatomtranslatorarray)) { |
2089 $handyatomtranslatorarray['©cpy'] = 'copyright'; |
2114 $handyatomtranslatorarray["\xA9".'cpy'] = 'copyright'; |
2090 $handyatomtranslatorarray['©day'] = 'creation_date'; // iTunes 4.0 |
2115 $handyatomtranslatorarray["\xA9".'day'] = 'creation_date'; // iTunes 4.0 |
2091 $handyatomtranslatorarray['©dir'] = 'director'; |
2116 $handyatomtranslatorarray["\xA9".'dir'] = 'director'; |
2092 $handyatomtranslatorarray['©ed1'] = 'edit1'; |
2117 $handyatomtranslatorarray["\xA9".'ed1'] = 'edit1'; |
2093 $handyatomtranslatorarray['©ed2'] = 'edit2'; |
2118 $handyatomtranslatorarray["\xA9".'ed2'] = 'edit2'; |
2094 $handyatomtranslatorarray['©ed3'] = 'edit3'; |
2119 $handyatomtranslatorarray["\xA9".'ed3'] = 'edit3'; |
2095 $handyatomtranslatorarray['©ed4'] = 'edit4'; |
2120 $handyatomtranslatorarray["\xA9".'ed4'] = 'edit4'; |
2096 $handyatomtranslatorarray['©ed5'] = 'edit5'; |
2121 $handyatomtranslatorarray["\xA9".'ed5'] = 'edit5'; |
2097 $handyatomtranslatorarray['©ed6'] = 'edit6'; |
2122 $handyatomtranslatorarray["\xA9".'ed6'] = 'edit6'; |
2098 $handyatomtranslatorarray['©ed7'] = 'edit7'; |
2123 $handyatomtranslatorarray["\xA9".'ed7'] = 'edit7'; |
2099 $handyatomtranslatorarray['©ed8'] = 'edit8'; |
2124 $handyatomtranslatorarray["\xA9".'ed8'] = 'edit8'; |
2100 $handyatomtranslatorarray['©ed9'] = 'edit9'; |
2125 $handyatomtranslatorarray["\xA9".'ed9'] = 'edit9'; |
2101 $handyatomtranslatorarray['©fmt'] = 'format'; |
2126 $handyatomtranslatorarray["\xA9".'fmt'] = 'format'; |
2102 $handyatomtranslatorarray['©inf'] = 'information'; |
2127 $handyatomtranslatorarray["\xA9".'inf'] = 'information'; |
2103 $handyatomtranslatorarray['©prd'] = 'producer'; |
2128 $handyatomtranslatorarray["\xA9".'prd'] = 'producer'; |
2104 $handyatomtranslatorarray['©prf'] = 'performers'; |
2129 $handyatomtranslatorarray["\xA9".'prf'] = 'performers'; |
2105 $handyatomtranslatorarray['©req'] = 'system_requirements'; |
2130 $handyatomtranslatorarray["\xA9".'req'] = 'system_requirements'; |
2106 $handyatomtranslatorarray['©src'] = 'source_credit'; |
2131 $handyatomtranslatorarray["\xA9".'src'] = 'source_credit'; |
2107 $handyatomtranslatorarray['©wrt'] = 'writer'; |
2132 $handyatomtranslatorarray["\xA9".'wrt'] = 'writer'; |
2108 |
2133 |
2109 // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt |
2134 // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt |
2110 $handyatomtranslatorarray['©nam'] = 'title'; // iTunes 4.0 |
2135 $handyatomtranslatorarray["\xA9".'nam'] = 'title'; // iTunes 4.0 |
2111 $handyatomtranslatorarray['©cmt'] = 'comment'; // iTunes 4.0 |
2136 $handyatomtranslatorarray["\xA9".'cmt'] = 'comment'; // iTunes 4.0 |
2112 $handyatomtranslatorarray['©wrn'] = 'warning'; |
2137 $handyatomtranslatorarray["\xA9".'wrn'] = 'warning'; |
2113 $handyatomtranslatorarray['©hst'] = 'host_computer'; |
2138 $handyatomtranslatorarray["\xA9".'hst'] = 'host_computer'; |
2114 $handyatomtranslatorarray['©mak'] = 'make'; |
2139 $handyatomtranslatorarray["\xA9".'mak'] = 'make'; |
2115 $handyatomtranslatorarray['©mod'] = 'model'; |
2140 $handyatomtranslatorarray["\xA9".'mod'] = 'model'; |
2116 $handyatomtranslatorarray['©PRD'] = 'product'; |
2141 $handyatomtranslatorarray["\xA9".'PRD'] = 'product'; |
2117 $handyatomtranslatorarray['©swr'] = 'software'; |
2142 $handyatomtranslatorarray["\xA9".'swr'] = 'software'; |
2118 $handyatomtranslatorarray['©aut'] = 'author'; |
2143 $handyatomtranslatorarray["\xA9".'aut'] = 'author'; |
2119 $handyatomtranslatorarray['©ART'] = 'artist'; |
2144 $handyatomtranslatorarray["\xA9".'ART'] = 'artist'; |
2120 $handyatomtranslatorarray['©trk'] = 'track'; |
2145 $handyatomtranslatorarray["\xA9".'trk'] = 'track'; |
2121 $handyatomtranslatorarray['©alb'] = 'album'; // iTunes 4.0 |
2146 $handyatomtranslatorarray["\xA9".'alb'] = 'album'; // iTunes 4.0 |
2122 $handyatomtranslatorarray['©com'] = 'comment'; |
2147 $handyatomtranslatorarray["\xA9".'com'] = 'comment'; |
2123 $handyatomtranslatorarray['©gen'] = 'genre'; // iTunes 4.0 |
2148 $handyatomtranslatorarray["\xA9".'gen'] = 'genre'; // iTunes 4.0 |
2124 $handyatomtranslatorarray['©ope'] = 'composer'; |
2149 $handyatomtranslatorarray["\xA9".'ope'] = 'composer'; |
2125 $handyatomtranslatorarray['©url'] = 'url'; |
2150 $handyatomtranslatorarray["\xA9".'url'] = 'url'; |
2126 $handyatomtranslatorarray['©enc'] = 'encoder'; |
2151 $handyatomtranslatorarray["\xA9".'enc'] = 'encoder'; |
2127 |
2152 |
2128 // http://atomicparsley.sourceforge.net/mpeg-4files.html |
2153 // http://atomicparsley.sourceforge.net/mpeg-4files.html |
2129 $handyatomtranslatorarray['©art'] = 'artist'; // iTunes 4.0 |
2154 $handyatomtranslatorarray["\xA9".'art'] = 'artist'; // iTunes 4.0 |
2130 $handyatomtranslatorarray['aART'] = 'album_artist'; |
2155 $handyatomtranslatorarray['aART'] = 'album_artist'; |
2131 $handyatomtranslatorarray['trkn'] = 'track_number'; // iTunes 4.0 |
2156 $handyatomtranslatorarray['trkn'] = 'track_number'; // iTunes 4.0 |
2132 $handyatomtranslatorarray['disk'] = 'disc_number'; // iTunes 4.0 |
2157 $handyatomtranslatorarray['disk'] = 'disc_number'; // iTunes 4.0 |
2133 $handyatomtranslatorarray['gnre'] = 'genre'; // iTunes 4.0 |
2158 $handyatomtranslatorarray['gnre'] = 'genre'; // iTunes 4.0 |
2134 $handyatomtranslatorarray['©too'] = 'encoder'; // iTunes 4.0 |
2159 $handyatomtranslatorarray["\xA9".'too'] = 'encoder'; // iTunes 4.0 |
2135 $handyatomtranslatorarray['tmpo'] = 'bpm'; // iTunes 4.0 |
2160 $handyatomtranslatorarray['tmpo'] = 'bpm'; // iTunes 4.0 |
2136 $handyatomtranslatorarray['cprt'] = 'copyright'; // iTunes 4.0? |
2161 $handyatomtranslatorarray['cprt'] = 'copyright'; // iTunes 4.0? |
2137 $handyatomtranslatorarray['cpil'] = 'compilation'; // iTunes 4.0 |
2162 $handyatomtranslatorarray['cpil'] = 'compilation'; // iTunes 4.0 |
2138 $handyatomtranslatorarray['covr'] = 'picture'; // iTunes 4.0 |
2163 $handyatomtranslatorarray['covr'] = 'picture'; // iTunes 4.0 |
2139 $handyatomtranslatorarray['rtng'] = 'rating'; // iTunes 4.0 |
2164 $handyatomtranslatorarray['rtng'] = 'rating'; // iTunes 4.0 |
2140 $handyatomtranslatorarray['©grp'] = 'grouping'; // iTunes 4.2 |
2165 $handyatomtranslatorarray["\xA9".'grp'] = 'grouping'; // iTunes 4.2 |
2141 $handyatomtranslatorarray['stik'] = 'stik'; // iTunes 4.9 |
2166 $handyatomtranslatorarray['stik'] = 'stik'; // iTunes 4.9 |
2142 $handyatomtranslatorarray['pcst'] = 'podcast'; // iTunes 4.9 |
2167 $handyatomtranslatorarray['pcst'] = 'podcast'; // iTunes 4.9 |
2143 $handyatomtranslatorarray['catg'] = 'category'; // iTunes 4.9 |
2168 $handyatomtranslatorarray['catg'] = 'category'; // iTunes 4.9 |
2144 $handyatomtranslatorarray['keyw'] = 'keyword'; // iTunes 4.9 |
2169 $handyatomtranslatorarray['keyw'] = 'keyword'; // iTunes 4.9 |
2145 $handyatomtranslatorarray['purl'] = 'podcast_url'; // iTunes 4.9 |
2170 $handyatomtranslatorarray['purl'] = 'podcast_url'; // iTunes 4.9 |
2146 $handyatomtranslatorarray['egid'] = 'episode_guid'; // iTunes 4.9 |
2171 $handyatomtranslatorarray['egid'] = 'episode_guid'; // iTunes 4.9 |
2147 $handyatomtranslatorarray['desc'] = 'description'; // iTunes 5.0 |
2172 $handyatomtranslatorarray['desc'] = 'description'; // iTunes 5.0 |
2148 $handyatomtranslatorarray['©lyr'] = 'lyrics'; // iTunes 5.0 |
2173 $handyatomtranslatorarray["\xA9".'lyr'] = 'lyrics'; // iTunes 5.0 |
2149 $handyatomtranslatorarray['tvnn'] = 'tv_network_name'; // iTunes 6.0 |
2174 $handyatomtranslatorarray['tvnn'] = 'tv_network_name'; // iTunes 6.0 |
2150 $handyatomtranslatorarray['tvsh'] = 'tv_show_name'; // iTunes 6.0 |
2175 $handyatomtranslatorarray['tvsh'] = 'tv_show_name'; // iTunes 6.0 |
2151 $handyatomtranslatorarray['tvsn'] = 'tv_season'; // iTunes 6.0 |
2176 $handyatomtranslatorarray['tvsn'] = 'tv_season'; // iTunes 6.0 |
2152 $handyatomtranslatorarray['tves'] = 'tv_episode'; // iTunes 6.0 |
2177 $handyatomtranslatorarray['tves'] = 'tv_episode'; // iTunes 6.0 |
2153 $handyatomtranslatorarray['purd'] = 'purchase_date'; // iTunes 6.0.2 |
2178 $handyatomtranslatorarray['purd'] = 'purchase_date'; // iTunes 6.0.2 |