Ignore:
Timestamp:
2011-06-01T12:33:42+12:00 (13 years ago)
Author:
sjm84
Message:

Updating the ExifTool perl modules

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone2/perllib/cpan/Image/ExifTool/MPEG.pm

    r16842 r24107  
    88# References:   1) http://www.mp3-tech.org/
    99#               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/
    1013#------------------------------------------------------------------------------
    1114
     
    1619use Image::ExifTool qw(:DataAccess :Utils);
    1720
    18 $VERSION = '1.04';
     21$VERSION = '1.13';
    1922
    2023%Image::ExifTool::MPEG::Audio = (
     
    4447            Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 3',
    4548            Notes => 'version 1, layer 1',
    46             PrintConv => {
     49            PrintConvColumns => 3,
     50            ValueConv => {
    4751                0 => 'free',
    4852                1 => 32000,
     
    6165                14 => 448000,
    6266            },
     67            PrintConv => 'ConvertBitrate($val)',
    6368        },
    6469        {
     
    6671            Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 2',
    6772            Notes => 'version 1, layer 2',
    68             PrintConv => {
     73            PrintConvColumns => 3,
     74            ValueConv => {
    6975                0 => 'free',
    7076                1 => 32000,
     
    8389                14 => 384000,
    8490            },
     91            PrintConv => 'ConvertBitrate($val)',
    8592        },
    8693        {
     
    8895            Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 1',
    8996            Notes => 'version 1, layer 3',
    90             PrintConv => {
     97            PrintConvColumns => 3,
     98            ValueConv => {
    9199                0 => 'free',
    92100                1 => 32000,
     
    105113                14 => 320000,
    106114            },
     115            PrintConv => 'ConvertBitrate($val)',
    107116        },
    108117        {
     
    110119            Condition => '$self->{MPEG_Vers} != 3 and $self->{MPEG_Layer} == 3',
    111120            Notes => 'version 2 or 2.5, layer 1',
    112             PrintConv => {
     121            PrintConvColumns => 3,
     122            ValueConv => {
    113123                0 => 'free',
    114124                1 => 32000,
     
    127137                14 => 256000,
    128138            },
     139            PrintConv => 'ConvertBitrate($val)',
    129140        },
    130141        {
     
    132143            Condition => '$self->{MPEG_Vers} != 3 and $self->{MPEG_Layer}',
    133144            Notes => 'version 2 or 2.5, layer 2 or 3',
    134             PrintConv => {
     145            PrintConvColumns => 3,
     146            ValueConv => {
    135147                0 => 'free',
    136148                1 => 8000,
     
    149161                14 => 160000,
    150162            },
     163            PrintConv => 'ConvertBitrate($val)',
    151164        },
    152165    ],
     
    187200    'Bit24-25' => {
    188201        Name => 'ChannelMode',
     202        RawConv => '$self->{MPEG_Mode} = $val',
    189203        PrintConv => {
    190204            0 => 'Stereo',
     
    298312        Name => 'VideoBitrate',
    299313        ValueConv => '$val eq 0x3ffff ? "Variable" : $val * 400',
     314        PrintConv => 'ConvertBitrate($val)',
    300315    },
    301316    # these tags not very interesting
     
    306321);
    307322
     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
    308385# composite tags
    309386%Image::ExifTool::MPEG::Composite = (
     
    314391        },
    315392        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)
    321401        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];
    324411            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)',
    333432    },
    334433);
     
    363462# Inputs: 0) ExifTool object reference, 1) Reference to audio data
    364463# Returns: 1 on success, 0 if no audio header was found
    365 sub ProcessMPEGAudio($$)
     464sub ParseMPEGAudio($$)
    366465{
    367466    my ($exifTool, $buffPt) = @_;
    368     my $word;
     467    my ($word, $pos);
     468    my $ext = $$exifTool{FILE_EXT} || '';
    369469
    370470    for (;;) {
     
    379479        if (($word & 0x180000) == 0x080000 or   # 01 is a reserved version ID
    380480            ($word & 0x060000) == 0x000000 or   # 00 is a reserved layer description
     481            ($word & 0x00f000) == 0x000000 or   # 0000 is the "free" bitrate index
    381482            ($word & 0x00f000) == 0x00f000 or   # 1111 is a bad bitrate index
    382             ($word & 0x000600) == 0x000600 or   # 11 is a reserved sampling frequency
     483            ($word & 0x000c00) == 0x000c00 or   # 11 is a reserved sampling frequency
    383484            ($word & 0x000003) == 0x000002)     # 10 is a reserved emphasis
    384485        {
    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);
    387492        last;
    388493    }
    389494    # set file type if not done already
    390     $exifTool->SetFileType() unless $exifTool->{VALUE}->{FileType};
     495    $exifTool->SetFileType();
    391496
    392497    my $tagTablePtr = GetTagTable('Image::ExifTool::MPEG::Audio');
    393498    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
    394579    return 1;
    395580}
     
    425610# Inputs: 0) ExifTool object reference, 1) Reference to audio/video data
    426611# 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
     626sub ParseMPEGAudioVideo($$)
    428627{
    429628    my ($exifTool, $buffPt) = @_;
    430     my %found;
     629    my (%found, $didHdr);
    431630    my $rtnVal = 0;
    432     my %proc = ( audio => \&ProcessMPEGAudio, video => \&ProcessMPEGVideo );
     631    my %proc = ( audio => \&ParseMPEGAudio, video => \&ProcessMPEGVideo );
    433632
    434633    delete $exifTool->{AudioBitrate};
     
    437636    while ($$buffPt =~ /\0\0\x01(\xb3|\xc0)/g) {
    438637        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        }
    439646        next if $found{$type};
    440647        my $len = length($$buffPt) - pos($$buffPt);
     
    454661
    455662#------------------------------------------------------------------------------
    456 # Read information frame an MPEG file
     663# Read information from an MPEG file
    457664# Inputs: 0) ExifTool object reference, 1) Directory information reference
    458665# Returns: 1 on success, 0 if this wasn't a valid MPEG file
     
    470677    $raf->Read($buff, 65536*4) or return 0;
    471678
    472     return ProcessMPEGAudioVideo($exifTool, \$buff);
     679    return ParseMPEGAudioVideo($exifTool, \$buff);
    473680}
    474681
     
    497704=head1 AUTHOR
    498705
    499 Copyright 2003-2007, Phil Harvey (phil at owl.phy.queensu.ca)
     706Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
    500707
    501708This library is free software; you can redistribute it and/or modify it
     
    510717=item L<http://www.getid3.org/>
    511718
     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
    512725=back
    513726
     
    515728
    516729L<Image::ExifTool::TagNames/MPEG Tags>,
     730L<MP3::Info(3pm)|MP3::Info>,
    517731L<Image::ExifTool(3pm)|Image::ExifTool>
    518732
Note: See TracChangeset for help on using the changeset viewer.