- Timestamp:
- 2011-06-01T12:33:42+12:00 (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone2/perllib/cpan/Image/ExifTool/MPEG.pm
r16842 r24107 8 8 # References: 1) http://www.mp3-tech.org/ 9 9 # 2) http://www.getid3.org/ 10 # 3) http://dvd.sourceforge.net/dvdinfo/dvdmpeg.html 11 # 4) http://ffmpeg.org/ 12 # 5) http://sourceforge.net/projects/mediainfo/ 10 13 #------------------------------------------------------------------------------ 11 14 … … 16 19 use Image::ExifTool qw(:DataAccess :Utils); 17 20 18 $VERSION = '1. 04';21 $VERSION = '1.13'; 19 22 20 23 %Image::ExifTool::MPEG::Audio = ( … … 44 47 Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 3', 45 48 Notes => 'version 1, layer 1', 46 PrintConv => { 49 PrintConvColumns => 3, 50 ValueConv => { 47 51 0 => 'free', 48 52 1 => 32000, … … 61 65 14 => 448000, 62 66 }, 67 PrintConv => 'ConvertBitrate($val)', 63 68 }, 64 69 { … … 66 71 Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 2', 67 72 Notes => 'version 1, layer 2', 68 PrintConv => { 73 PrintConvColumns => 3, 74 ValueConv => { 69 75 0 => 'free', 70 76 1 => 32000, … … 83 89 14 => 384000, 84 90 }, 91 PrintConv => 'ConvertBitrate($val)', 85 92 }, 86 93 { … … 88 95 Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 1', 89 96 Notes => 'version 1, layer 3', 90 PrintConv => { 97 PrintConvColumns => 3, 98 ValueConv => { 91 99 0 => 'free', 92 100 1 => 32000, … … 105 113 14 => 320000, 106 114 }, 115 PrintConv => 'ConvertBitrate($val)', 107 116 }, 108 117 { … … 110 119 Condition => '$self->{MPEG_Vers} != 3 and $self->{MPEG_Layer} == 3', 111 120 Notes => 'version 2 or 2.5, layer 1', 112 PrintConv => { 121 PrintConvColumns => 3, 122 ValueConv => { 113 123 0 => 'free', 114 124 1 => 32000, … … 127 137 14 => 256000, 128 138 }, 139 PrintConv => 'ConvertBitrate($val)', 129 140 }, 130 141 { … … 132 143 Condition => '$self->{MPEG_Vers} != 3 and $self->{MPEG_Layer}', 133 144 Notes => 'version 2 or 2.5, layer 2 or 3', 134 PrintConv => { 145 PrintConvColumns => 3, 146 ValueConv => { 135 147 0 => 'free', 136 148 1 => 8000, … … 149 161 14 => 160000, 150 162 }, 163 PrintConv => 'ConvertBitrate($val)', 151 164 }, 152 165 ], … … 187 200 'Bit24-25' => { 188 201 Name => 'ChannelMode', 202 RawConv => '$self->{MPEG_Mode} = $val', 189 203 PrintConv => { 190 204 0 => 'Stereo', … … 298 312 Name => 'VideoBitrate', 299 313 ValueConv => '$val eq 0x3ffff ? "Variable" : $val * 400', 314 PrintConv => 'ConvertBitrate($val)', 300 315 }, 301 316 # these tags not very interesting … … 306 321 ); 307 322 323 %Image::ExifTool::MPEG::Xing = ( 324 GROUPS => { 2 => 'Audio' }, 325 VARS => { NO_ID => 1 }, 326 NOTES => 'These tags are extracted from the Xing/Info frame.', 327 1 => { Name => 'VBRFrames' }, 328 2 => { Name => 'VBRBytes' }, 329 3 => { Name => 'VBRScale' }, 330 4 => { Name => 'Encoder' }, 331 5 => { Name => 'LameVBRQuality' }, 332 6 => { Name => 'LameQuality' }, 333 7 => { # (for documentation only) 334 Name => 'LameHeader', 335 SubDirectory => { TagTable => 'Image::ExifTool::MPEG::Lame' }, 336 }, 337 ); 338 339 # Lame header tags (ref 5) 340 %Image::ExifTool::MPEG::Lame = ( 341 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, 342 GROUPS => { 2 => 'Audio' }, 343 NOTES => 'Tags extracted from Lame 3.90 or later header.', 344 9 => { 345 Name => 'LameMethod', 346 Mask => 0x0f, 347 PrintConv => { 348 1 => 'CBR', 349 2 => 'ABR', 350 3 => 'VBR (old/rh)', 351 4 => 'VBR (new/mtrh)', 352 5 => 'VBR (old/rh)', 353 6 => 'VBR', 354 8 => 'CBR (2-pass)', 355 9 => 'ABR (2-pass)', 356 }, 357 }, 358 10 => { 359 Name => 'LameLowPassFilter', 360 ValueConv => '$val * 100', 361 PrintConv => '($val / 1000) . " kHz"', 362 }, 363 # 19 - EncodingFlags 364 20 => { 365 Name => 'LameBitrate', 366 ValueConv => '$val * 1000', 367 PrintConv => 'ConvertBitrate($val)', 368 }, 369 24 => { 370 Name => 'LameStereoMode', 371 Mask => 0x1c, 372 ValueConv => '$val >> 2', 373 PrintConv => { 374 0 => 'Mono', 375 1 => 'Stereo', 376 2 => 'Dual Channels', 377 3 => 'Joint Stereo', 378 4 => 'Forced Joint Stereo', 379 6 => 'Auto', 380 7 => 'Intensity Stereo', 381 }, 382 }, 383 ); 384 308 385 # composite tags 309 386 %Image::ExifTool::MPEG::Composite = ( … … 314 391 }, 315 392 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!) 393 1 => 'ID3Size', 394 2 => 'MPEG:AudioBitrate', 395 3 => 'MPEG:VideoBitrate', 396 4 => 'MPEG:VBRFrames', 397 5 => 'MPEG:SampleRate', 398 6 => 'MPEG:MPEGAudioVersion', 399 }, 400 Priority => -1, # (don't want to replace any other Duration tag) 321 401 ValueConv => q{ 322 return undef unless $val[1] or $val[2]; 323 return undef if $prt[1] and not $prt[1] =~ /^\d+$/; 402 if ($val[4] and defined $val[5] and defined $val[6]) { 403 # calculate from number of VBR audio frames 404 my $mfs = $prt[5] / ($val[6] == 3 ? 144 : 72); 405 # calculate using VBR length 406 return 8 * $val[4] / $mfs; 407 } 408 # calculate duration as file size divided by total bitrate 409 # (note: this is only approximate!) 410 return undef unless $val[2] or $val[3]; 324 411 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 }, 412 return undef if $val[3] and not $val[3] =~ /^\d+$/; 413 return (8 * ($val[0] - ($val[1]||0))) / (($val[2]||0) + ($val[3]||0)); 414 }, 415 PrintConv => 'ConvertDuration($val) . " (approx)"', 416 }, 417 AudioBitrate => { 418 Groups => { 2 => 'Audio' }, 419 Notes => 'calculated for variable-bitrate MPEG audio', 420 Require => { 421 0 => 'MPEG:MPEGAudioVersion', 422 1 => 'MPEG:SampleRate', 423 2 => 'MPEG:VBRBytes', 424 3 => 'MPEG:VBRFrames', 425 }, 426 ValueConv => q{ 427 return undef unless $val[3]; 428 my $mfs = $prt[1] / ($val[0] == 3 ? 144 : 72); 429 return $mfs * $val[2] / $val[3]; 430 }, 431 PrintConv => 'ConvertBitrate($val)', 333 432 }, 334 433 ); … … 363 462 # Inputs: 0) ExifTool object reference, 1) Reference to audio data 364 463 # Returns: 1 on success, 0 if no audio header was found 365 sub P rocessMPEGAudio($$)464 sub ParseMPEGAudio($$) 366 465 { 367 466 my ($exifTool, $buffPt) = @_; 368 my $word; 467 my ($word, $pos); 468 my $ext = $$exifTool{FILE_EXT} || ''; 369 469 370 470 for (;;) { … … 379 479 if (($word & 0x180000) == 0x080000 or # 01 is a reserved version ID 380 480 ($word & 0x060000) == 0x000000 or # 00 is a reserved layer description 481 ($word & 0x00f000) == 0x000000 or # 0000 is the "free" bitrate index 381 482 ($word & 0x00f000) == 0x00f000 or # 1111 is a bad bitrate index 382 ($word & 0x000 600) == 0x000600 or # 11 is a reserved sampling frequency483 ($word & 0x000c00) == 0x000c00 or # 11 is a reserved sampling frequency 383 484 ($word & 0x000003) == 0x000002) # 10 is a reserved emphasis 384 485 { 385 return 0; # invalid frame header 386 } 486 # give up easily unless this really should be an MP3 file 487 return 0 unless $ext eq 'MP3'; 488 pos($$buffPt) = pos($$buffPt) - 1; 489 next; 490 } 491 $pos = pos($$buffPt); 387 492 last; 388 493 } 389 494 # set file type if not done already 390 $exifTool->SetFileType() unless $exifTool->{VALUE}->{FileType};495 $exifTool->SetFileType(); 391 496 392 497 my $tagTablePtr = GetTagTable('Image::ExifTool::MPEG::Audio'); 393 498 ProcessFrameHeader($exifTool, $tagTablePtr, $word); 499 500 # extract the VBR information (ref MP3::Info) 501 my ($v, $m) = ($$exifTool{MPEG_Vers}, $$exifTool{MPEG_Mode}); 502 while (defined $v and defined $m) { 503 my $len = length $$buffPt; 504 $pos += $v == 3 ? ($m == 3 ? 17 : 32) : ($m == 3 ? 9 : 17); 505 last if $pos + 8 > $len; 506 my $buff = substr($$buffPt, $pos, 8); 507 last unless $buff =~ /^(Xing|Info)/; 508 my $xingTable = GetTagTable('Image::ExifTool::MPEG::Xing'); 509 my $vbrScale; 510 my $flags = unpack('x4N', $buff); 511 my $isVBR = ($buff !~ /^Info/); # Info frame is not VBR (ref 5) 512 $pos += 8; 513 if ($flags & 0x01) { # VBRFrames 514 last if $pos + 4 > $len; 515 $exifTool->HandleTag($xingTable, 1, unpack("x${pos}N", $$buffPt)) if $isVBR; 516 $pos += 4; 517 } 518 if ($flags & 0x02) { # VBRBytes 519 last if $pos + 4 > $len; 520 $exifTool->HandleTag($xingTable, 2, unpack("x${pos}N", $$buffPt)) if $isVBR; 521 $pos += 4; 522 } 523 if ($flags & 0x04) { # VBR_TOC 524 last if $pos + 100 > $len; 525 # (ignore toc for now) 526 $pos += 100; 527 } 528 if ($flags & 0x08) { # VBRScale 529 last if $pos + 4 > $len; 530 $vbrScale = unpack("x${pos}N", $$buffPt); 531 $exifTool->HandleTag($xingTable, 3, $vbrScale) if $isVBR; 532 $pos += 4; 533 } 534 # process Lame header (ref 5) 535 if ($flags & 0x10) { # Lame 536 last if $pos + 348 > $len; 537 } elsif ($pos + 4 <= $len) { 538 my $lib = substr($$buffPt, $pos, 4); 539 unless ($lib eq 'LAME' or $lib eq 'GOGO') { 540 # attempt to identify other encoders 541 my $n; 542 if (index($$buffPt, 'RCA mp3PRO Encoder') >= 0) { 543 $lib = 'RCA mp3PRO'; 544 } elsif (($n = index($$buffPt, 'THOMSON mp3PRO Encoder')) >= 0) { 545 $lib = 'Thomson mp3PRO'; 546 $n += 22; 547 $lib .= ' ' . substr($$buffPt, $n, 6) if length($$buffPt) - $n >= 6; 548 } elsif (index($$buffPt, 'MPGE') >= 0) { 549 $lib = 'Gogo (<3.0)'; 550 } else { 551 last; 552 } 553 $exifTool->HandleTag($xingTable, 4, $lib); 554 last; 555 } 556 } 557 my $lameLen = $len - $pos; 558 last if $lameLen < 9; 559 my $enc = substr($$buffPt, $pos, 9); 560 if ($enc ge 'LAME3.90') { 561 $exifTool->HandleTag($xingTable, 4, $enc); 562 if ($vbrScale <= 100) { 563 $exifTool->HandleTag($xingTable, 5, int((100 - $vbrScale) / 10)); 564 $exifTool->HandleTag($xingTable, 6, (100 - $vbrScale) % 10); 565 } 566 my %dirInfo = ( 567 DataPt => $buffPt, 568 DirStart => $pos, 569 DirLen => length($$buffPt) - $pos, 570 ); 571 my $subTablePtr = GetTagTable('Image::ExifTool::MPEG::Lame'); 572 $exifTool->ProcessDirectory(\%dirInfo, $subTablePtr); 573 } else { 574 $exifTool->HandleTag($xingTable, 4, substr($$buffPt, $pos, 20)); 575 } 576 last; # (didn't want to loop anyway) 577 } 578 394 579 return 1; 395 580 } … … 425 610 # Inputs: 0) ExifTool object reference, 1) Reference to audio/video data 426 611 # Returns: 1 on success, 0 if no video header was found 427 sub ProcessMPEGAudioVideo($$) 612 # To Do: Properly parse MPEG streams: 613 # 0xb7 - sequence end 614 # 0xb9 - end code 615 # 0xba - pack start code 616 # 0xbb - system header 617 # 0xbc - program map <-- should parse this 618 # 0xbd - private stream 1 --> for VOB, this contains sub-streams: 619 # 0x20-0x3f - pictures 620 # 0x80-0x87 - audio (AC3,DTS,SDDS) 621 # 0xa0-0xa7 - audio (LPCM) 622 # 0xbe - padding 623 # 0xbf - private stream 2 624 # 0xc0-0xdf - audio stream 625 # 0xe0-0xef - video stream 626 sub ParseMPEGAudioVideo($$) 428 627 { 429 628 my ($exifTool, $buffPt) = @_; 430 my %found;629 my (%found, $didHdr); 431 630 my $rtnVal = 0; 432 my %proc = ( audio => \&P rocessMPEGAudio, video => \&ProcessMPEGVideo );631 my %proc = ( audio => \&ParseMPEGAudio, video => \&ProcessMPEGVideo ); 433 632 434 633 delete $exifTool->{AudioBitrate}; … … 437 636 while ($$buffPt =~ /\0\0\x01(\xb3|\xc0)/g) { 438 637 my $type = $1 eq "\xb3" ? 'video' : 'audio'; 638 unless ($didHdr) { 639 # make sure we didn't miss an audio frame sync before this (ie. MP3 file) 640 # (the last byte of the 4-byte MP3 audio frame header word may be zero, 641 # but the 2nd last must be non-zero, so we need only check to pos-3) 642 my $buff = substr($$buffPt, 0, pos($$buffPt) - 3); 643 $found{audio} = 1 if ParseMPEGAudio($exifTool, \$buff); 644 $didHdr = 1; 645 } 439 646 next if $found{$type}; 440 647 my $len = length($$buffPt) - pos($$buffPt); … … 454 661 455 662 #------------------------------------------------------------------------------ 456 # Read information fr amean MPEG file663 # Read information from an MPEG file 457 664 # Inputs: 0) ExifTool object reference, 1) Directory information reference 458 665 # Returns: 1 on success, 0 if this wasn't a valid MPEG file … … 470 677 $raf->Read($buff, 65536*4) or return 0; 471 678 472 return P rocessMPEGAudioVideo($exifTool, \$buff);679 return ParseMPEGAudioVideo($exifTool, \$buff); 473 680 } 474 681 … … 497 704 =head1 AUTHOR 498 705 499 Copyright 2003-20 07, Phil Harvey (phil at owl.phy.queensu.ca)706 Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca) 500 707 501 708 This library is free software; you can redistribute it and/or modify it … … 510 717 =item L<http://www.getid3.org/> 511 718 719 =item L<http://dvd.sourceforge.net/dvdinfo/dvdmpeg.html> 720 721 =item L<http://ffmpeg.org/> 722 723 =item L<http://sourceforge.net/projects/mediainfo/> 724 512 725 =back 513 726 … … 515 728 516 729 L<Image::ExifTool::TagNames/MPEG Tags>, 730 L<MP3::Info(3pm)|MP3::Info>, 517 731 L<Image::ExifTool(3pm)|Image::ExifTool> 518 732
Note:
See TracChangeset
for help on using the changeset viewer.