source: gsdl/trunk/perllib/cpan/Image/ExifTool/MPEG.pm@ 16842

Last change on this file since 16842 was 16842, checked in by davidb, 16 years ago

ExifTool added to cpan area to support metadata extraction from files such as JPEG. Primarily targetted as Image files (hence the Image folder name decided upon by the ExifTool author) it also can handle video such as flash and audio such as Wav

File size: 14.7 KB
Line 
1#------------------------------------------------------------------------------
2# File: MPEG.pm
3#
4# Description: Read MPEG-1 and MPEG-2 meta information
5#
6# Revisions: 05/11/2006 - P. Harvey Created
7#
8# References: 1) http://www.mp3-tech.org/
9# 2) http://www.getid3.org/
10#------------------------------------------------------------------------------
11
12package Image::ExifTool::MPEG;
13
14use strict;
15use vars qw($VERSION);
16use Image::ExifTool qw(:DataAccess :Utils);
17
18$VERSION = '1.04';
19
20%Image::ExifTool::MPEG::Audio = (
21 GROUPS => { 2 => 'Audio' },
22 'Bit11-12' => {
23 Name => 'MPEGAudioVersion',
24 RawConv => '$self->{MPEG_Vers} = $val',
25 PrintConv => {
26 0 => 2.5,
27 2 => 2,
28 3 => 1,
29 },
30 },
31 'Bit13-14' => {
32 Name => 'AudioLayer',
33 RawConv => '$self->{MPEG_Layer} = $val',
34 PrintConv => {
35 1 => 3,
36 2 => 2,
37 3 => 1,
38 },
39 },
40 # Bit 15 indicates CRC protection
41 'Bit16-19' => [
42 {
43 Name => 'AudioBitrate',
44 Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 3',
45 Notes => 'version 1, layer 1',
46 PrintConv => {
47 0 => 'free',
48 1 => 32000,
49 2 => 64000,
50 3 => 96000,
51 4 => 128000,
52 5 => 160000,
53 6 => 192000,
54 7 => 224000,
55 8 => 256000,
56 9 => 288000,
57 10 => 320000,
58 11 => 352000,
59 12 => 384000,
60 13 => 416000,
61 14 => 448000,
62 },
63 },
64 {
65 Name => 'AudioBitrate',
66 Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 2',
67 Notes => 'version 1, layer 2',
68 PrintConv => {
69 0 => 'free',
70 1 => 32000,
71 2 => 48000,
72 3 => 56000,
73 4 => 64000,
74 5 => 80000,
75 6 => 96000,
76 7 => 112000,
77 8 => 128000,
78 9 => 160000,
79 10 => 192000,
80 11 => 224000,
81 12 => 256000,
82 13 => 320000,
83 14 => 384000,
84 },
85 },
86 {
87 Name => 'AudioBitrate',
88 Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 1',
89 Notes => 'version 1, layer 3',
90 PrintConv => {
91 0 => 'free',
92 1 => 32000,
93 2 => 40000,
94 3 => 48000,
95 4 => 56000,
96 5 => 64000,
97 6 => 80000,
98 7 => 96000,
99 8 => 112000,
100 9 => 128000,
101 10 => 160000,
102 11 => 192000,
103 12 => 224000,
104 13 => 256000,
105 14 => 320000,
106 },
107 },
108 {
109 Name => 'AudioBitrate',
110 Condition => '$self->{MPEG_Vers} != 3 and $self->{MPEG_Layer} == 3',
111 Notes => 'version 2 or 2.5, layer 1',
112 PrintConv => {
113 0 => 'free',
114 1 => 32000,
115 2 => 48000,
116 3 => 56000,
117 4 => 64000,
118 5 => 80000,
119 6 => 96000,
120 7 => 112000,
121 8 => 128000,
122 9 => 144000,
123 10 => 160000,
124 11 => 176000,
125 12 => 192000,
126 13 => 224000,
127 14 => 256000,
128 },
129 },
130 {
131 Name => 'AudioBitrate',
132 Condition => '$self->{MPEG_Vers} != 3 and $self->{MPEG_Layer}',
133 Notes => 'version 2 or 2.5, layer 2 or 3',
134 PrintConv => {
135 0 => 'free',
136 1 => 8000,
137 2 => 16000,
138 3 => 24000,
139 4 => 32000,
140 5 => 40000,
141 6 => 48000,
142 7 => 56000,
143 8 => 64000,
144 9 => 80000,
145 10 => 96000,
146 11 => 112000,
147 12 => 128000,
148 13 => 144000,
149 14 => 160000,
150 },
151 },
152 ],
153 'Bit20-21' => [
154 {
155 Name => 'SampleRate',
156 Condition => '$self->{MPEG_Vers} == 3',
157 Notes => 'version 1',
158 PrintConv => {
159 0 => 44100,
160 1 => 48000,
161 2 => 32000,
162 },
163 },
164 {
165 Name => 'SampleRate',
166 Condition => '$self->{MPEG_Vers} == 2',
167 Notes => 'version 2',
168 PrintConv => {
169 0 => 22050,
170 1 => 24000,
171 2 => 16000,
172 },
173 },
174 {
175 Name => 'SampleRate',
176 Condition => '$self->{MPEG_Vers} == 0',
177 Notes => 'version 2.5',
178 PrintConv => {
179 0 => 11025,
180 1 => 12000,
181 2 => 8000,
182 },
183 },
184 ],
185 # Bit 22 - padding flag
186 # Bit 23 - private bit
187 'Bit24-25' => {
188 Name => 'ChannelMode',
189 PrintConv => {
190 0 => 'Stereo',
191 1 => 'Joint Stereo',
192 2 => 'Dual Channel',
193 3 => 'Single Channel',
194 },
195 },
196 'Bit26' => {
197 Name => 'MSStereo',
198 Condition => '$self->{MPEG_Layer} == 1',
199 Notes => 'layer 3',
200 PrintConv => { 0 => 'Off', 1 => 'On' },
201 },
202 'Bit27' => {
203 Name => 'IntensityStereo',
204 Condition => '$self->{MPEG_Layer} == 1',
205 Notes => 'layer 3',
206 PrintConv => { 0 => 'Off', 1 => 'On' },
207 },
208 'Bit26-27' => {
209 Name => 'ModeExtension',
210 Condition => '$self->{MPEG_Layer} > 1',
211 Notes => 'layer 1 or 2',
212 PrintConv => {
213 0 => 'Bands 4-31',
214 1 => 'Bands 8-31',
215 2 => 'Bands 12-31',
216 3 => 'Bands 16-31',
217 },
218 },
219 'Bit28' => {
220 Name => 'CopyrightFlag',
221 PrintConv => {
222 0 => 'False',
223 1 => 'True',
224 },
225 },
226 'Bit29' => {
227 Name => 'OriginalMedia',
228 PrintConv => {
229 0 => 'False',
230 1 => 'True',
231 },
232 },
233 'Bit30-31' => {
234 Name => 'Emphasis',
235 PrintConv => {
236 0 => 'None',
237 1 => '50/15 ms',
238 2 => 'reserved',
239 3 => 'CCIT J.17',
240 },
241 },
242);
243
244%Image::ExifTool::MPEG::Video = (
245 GROUPS => { 2 => 'Video' },
246 'Bit00-11' => 'ImageWidth',
247 'Bit12-23' => 'ImageHeight',
248 'Bit24-27' => {
249 Name => 'AspectRatio',
250 ValueConv => {
251 1 => 1,
252 2 => 0.6735,
253 3 => 0.7031,
254 4 => 0.7615,
255 5 => 0.8055,
256 6 => 0.8437,
257 7 => 0.8935,
258 8 => 0.9157,
259 9 => 0.9815,
260 10 => 1.0255,
261 11 => 1.0695,
262 12 => 1.0950,
263 13 => 1.1575,
264 14 => 1.2015,
265 },
266 PrintConv => {
267 1 => '1:1',
268 0.6735 => '0.6735',
269 0.7031 => '16:9, 625 line, PAL',
270 0.7615 => '0.7615',
271 0.8055 => '0.8055',
272 0.8437 => '16:9, 525 line, NTSC',
273 0.8935 => '0.8935',
274 0.9157 => '4:3, 625 line, PAL, CCIR601',
275 0.9815 => '0.9815',
276 1.0255 => '1.0255',
277 1.0695 => '1.0695',
278 1.0950 => '4:3, 525 line, NTSC, CCIR601',
279 1.1575 => '1.1575',
280 1.2015 => '1.2015',
281 },
282 },
283 'Bit28-31' => {
284 Name => 'FrameRate',
285 ValueConv => {
286 1 => 23.976,
287 2 => 24,
288 3 => 25,
289 4 => 29.97,
290 5 => 30,
291 6 => 50,
292 7 => 59.94,
293 8 => 60,
294 },
295 PrintConv => '"$val fps"',
296 },
297 'Bit32-49' => {
298 Name => 'VideoBitrate',
299 ValueConv => '$val eq 0x3ffff ? "Variable" : $val * 400',
300 },
301 # these tags not very interesting
302 #'Bit50' => 'MarkerBit',
303 #'Bit51-60' => 'VBVBufferSize',
304 #'Bit61' => 'ConstrainedParamFlag',
305 #'Bit62' => 'IntraQuantMatrixFlag',
306);
307
308# composite tags
309%Image::ExifTool::MPEG::Composite = (
310 Duration => {
311 Groups => { 2 => 'Video' },
312 Require => {
313 0 => 'FileSize',
314 },
315 Desire => {
316 1 => 'MPEG:AudioBitrate',
317 2 => 'MPEG:VideoBitrate',
318 },
319 # calculate duration as file size divided by total bitrate
320 # (note: this is only approximate!)
321 ValueConv => q{
322 return undef unless $val[1] or $val[2];
323 return undef if $prt[1] and not $prt[1] =~ /^\d+$/;
324 return undef if $val[2] and not $val[2] =~ /^\d+$/;
325 return (8 * $val[0]) / (($prt[1]||0) + ($val[2]||0));
326 },
327 PrintConv => q{
328 my $h = int($val / 3600);
329 my $m = int($val / 60 - $h * 60);
330 my $s = $val - $h * 3600 - $m * 60;
331 return sprintf("%d:%.2d:%05.2f (approx)",$h,$m,$s);
332 },
333 },
334);
335
336# add our composite tags
337Image::ExifTool::AddCompositeTags('Image::ExifTool::MPEG');
338
339
340#------------------------------------------------------------------------------
341# Process information in an MPEG audio or video frame header
342# Inputs: 0) ExifTool object ref, 1) tag table ref, 2-N) list of 32-bit data words
343sub ProcessFrameHeader($$@)
344{
345 my ($exifTool, $tagTablePtr, @data) = @_;
346 my $tag;
347 foreach $tag (sort keys %$tagTablePtr) {
348 next unless $tag =~ /^Bit(\d{2})-?(\d{2})?/;
349 my ($b1, $b2) = ($1, $2 || $1);
350 my $index = int($b1 / 32);
351 my $word = $data[$index];
352 my $mask = 0;
353 foreach (0 .. ($b2 - $b1)) {
354 $mask += (1 << $_);
355 }
356 my $val = ($word >> (31 + 32*$index - $b2)) & $mask;
357 $exifTool->HandleTag($tagTablePtr, $tag, $val);
358 }
359}
360
361#------------------------------------------------------------------------------
362# Read MPEG audio frame header
363# Inputs: 0) ExifTool object reference, 1) Reference to audio data
364# Returns: 1 on success, 0 if no audio header was found
365sub ProcessMPEGAudio($$)
366{
367 my ($exifTool, $buffPt) = @_;
368 my $word;
369
370 for (;;) {
371 # find frame sync
372 return 0 unless $$buffPt =~ m{(\xff.{3})}sg;
373 $word = unpack('N', $1); # get audio frame header word
374 unless (($word & 0xffe00000) == 0xffe00000) {
375 pos($$buffPt) = pos($$buffPt) - 2; # next possible location for frame sync
376 next;
377 }
378 # validate header as much as possible
379 if (($word & 0x180000) == 0x080000 or # 01 is a reserved version ID
380 ($word & 0x060000) == 0x000000 or # 00 is a reserved layer description
381 ($word & 0x00f000) == 0x00f000 or # 1111 is a bad bitrate index
382 ($word & 0x000600) == 0x000600 or # 11 is a reserved sampling frequency
383 ($word & 0x000003) == 0x000002) # 10 is a reserved emphasis
384 {
385 return 0; # invalid frame header
386 }
387 last;
388 }
389 # set file type if not done already
390 $exifTool->SetFileType() unless $exifTool->{VALUE}->{FileType};
391
392 my $tagTablePtr = GetTagTable('Image::ExifTool::MPEG::Audio');
393 ProcessFrameHeader($exifTool, $tagTablePtr, $word);
394 return 1;
395}
396
397#------------------------------------------------------------------------------
398# Read MPEG video frame header
399# Inputs: 0) ExifTool object reference, 1) Reference to video data
400# Returns: 1 on success, 0 if no video header was found
401sub ProcessMPEGVideo($$)
402{
403 my ($exifTool, $buffPt) = @_;
404
405 return 0 unless length $$buffPt >= 4;
406 my ($w1, $w2) = unpack('N2', $$buffPt);
407 # validate as much as possible
408 if (($w1 & 0x000000f0) == 0x00000000 or # 0000 is a forbidden aspect ratio
409 ($w1 & 0x000000f0) == 0x000000f0 or # 1111 is a reserved aspect ratio
410 ($w1 & 0x0000000f) == 0 or # frame rate must be 1-8
411 ($w1 & 0x0000000f) > 8)
412 {
413 return 0;
414 }
415 # set file type if not done already
416 $exifTool->SetFileType('MPEG') unless $exifTool->{VALUE}->{FileType};
417
418 my $tagTablePtr = GetTagTable('Image::ExifTool::MPEG::Video');
419 ProcessFrameHeader($exifTool, $tagTablePtr, $w1, $w2);
420 return 1;
421}
422
423#------------------------------------------------------------------------------
424# Read MPEG audio and video frame headers
425# Inputs: 0) ExifTool object reference, 1) Reference to audio/video data
426# Returns: 1 on success, 0 if no video header was found
427sub ProcessMPEGAudioVideo($$)
428{
429 my ($exifTool, $buffPt) = @_;
430 my %found;
431 my $rtnVal = 0;
432 my %proc = ( audio => \&ProcessMPEGAudio, video => \&ProcessMPEGVideo );
433
434 delete $exifTool->{AudioBitrate};
435 delete $exifTool->{VideoBitrate};
436
437 while ($$buffPt =~ /\0\0\x01(\xb3|\xc0)/g) {
438 my $type = $1 eq "\xb3" ? 'video' : 'audio';
439 next if $found{$type};
440 my $len = length($$buffPt) - pos($$buffPt);
441 last if $len < 4;
442 $len > 256 and $len = 256;
443 my $dat = substr($$buffPt, pos($$buffPt), $len);
444 # process MPEG audio or video
445 if (&{$proc{$type}}($exifTool, \$dat)) {
446 $rtnVal = 1;
447 $found{$type} = 1;
448 # done if we found audio and video
449 last if scalar(keys %found) == 2;
450 }
451 }
452 return $rtnVal;
453}
454
455#------------------------------------------------------------------------------
456# Read information frame an MPEG file
457# Inputs: 0) ExifTool object reference, 1) Directory information reference
458# Returns: 1 on success, 0 if this wasn't a valid MPEG file
459sub ProcessMPEG($$)
460{
461 my ($exifTool, $dirInfo) = @_;
462 my $raf = $$dirInfo{RAF};
463 my $buff;
464
465 $raf->Read($buff, 4) == 4 or return 0;
466 return 0 unless $buff =~ /^\0\0\x01[\xb0-\xbf]/;
467 $exifTool->SetFileType();
468
469 $raf->Seek(0,0);
470 $raf->Read($buff, 65536*4) or return 0;
471
472 return ProcessMPEGAudioVideo($exifTool, \$buff);
473}
474
4751; # end
476
477__END__
478
479=head1 NAME
480
481Image::ExifTool::MPEG - Read MPEG-1 and MPEG-2 meta information
482
483=head1 SYNOPSIS
484
485This module is used by Image::ExifTool
486
487=head1 DESCRIPTION
488
489This module contains definitions required by Image::ExifTool to read MPEG-1
490and MPEG-2 audio/video files.
491
492=head1 NOTES
493
494Since ISO charges money for the official MPEG specification, this module is
495based on unofficial sources which may be incomplete, inaccurate or outdated.
496
497=head1 AUTHOR
498
499Copyright 2003-2007, Phil Harvey (phil at owl.phy.queensu.ca)
500
501This library is free software; you can redistribute it and/or modify it
502under the same terms as Perl itself.
503
504=head1 REFERENCES
505
506=over 4
507
508=item L<http://www.mp3-tech.org/>
509
510=item L<http://www.getid3.org/>
511
512=back
513
514=head1 SEE ALSO
515
516L<Image::ExifTool::TagNames/MPEG Tags>,
517L<Image::ExifTool(3pm)|Image::ExifTool>
518
519=cut
520
Note: See TracBrowser for help on using the repository browser.