123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736 |
- #------------------------------------------------------------------------------
- # File: MPEG.pm
- #
- # Description: Read MPEG-1 and MPEG-2 meta information
- #
- # Revisions: 05/11/2006 - P. Harvey Created
- #
- # References: 1) http://www.mp3-tech.org/
- # 2) http://www.getid3.org/
- # 3) http://dvd.sourceforge.net/dvdinfo/dvdmpeg.html
- # 4) http://ffmpeg.org/
- # 5) http://sourceforge.net/projects/mediainfo/
- #------------------------------------------------------------------------------
- package Image::ExifTool::MPEG;
- use strict;
- use vars qw($VERSION);
- use Image::ExifTool qw(:DataAccess :Utils);
- $VERSION = '1.15';
- %Image::ExifTool::MPEG::Audio = (
- GROUPS => { 2 => 'Audio' },
- 'Bit11-12' => {
- Name => 'MPEGAudioVersion',
- RawConv => '$self->{MPEG_Vers} = $val',
- PrintConv => {
- 0 => 2.5,
- 2 => 2,
- 3 => 1,
- },
- },
- 'Bit13-14' => {
- Name => 'AudioLayer',
- RawConv => '$self->{MPEG_Layer} = $val',
- PrintConv => {
- 1 => 3,
- 2 => 2,
- 3 => 1,
- },
- },
- # Bit 15 indicates CRC protection
- 'Bit16-19' => [
- {
- Name => 'AudioBitrate',
- Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 3',
- Notes => 'version 1, layer 1',
- PrintConvColumns => 3,
- ValueConv => {
- 0 => 'free',
- 1 => 32000,
- 2 => 64000,
- 3 => 96000,
- 4 => 128000,
- 5 => 160000,
- 6 => 192000,
- 7 => 224000,
- 8 => 256000,
- 9 => 288000,
- 10 => 320000,
- 11 => 352000,
- 12 => 384000,
- 13 => 416000,
- 14 => 448000,
- },
- PrintConv => 'ConvertBitrate($val)',
- },
- {
- Name => 'AudioBitrate',
- Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 2',
- Notes => 'version 1, layer 2',
- PrintConvColumns => 3,
- ValueConv => {
- 0 => 'free',
- 1 => 32000,
- 2 => 48000,
- 3 => 56000,
- 4 => 64000,
- 5 => 80000,
- 6 => 96000,
- 7 => 112000,
- 8 => 128000,
- 9 => 160000,
- 10 => 192000,
- 11 => 224000,
- 12 => 256000,
- 13 => 320000,
- 14 => 384000,
- },
- PrintConv => 'ConvertBitrate($val)',
- },
- {
- Name => 'AudioBitrate',
- Condition => '$self->{MPEG_Vers} == 3 and $self->{MPEG_Layer} == 1',
- Notes => 'version 1, layer 3',
- PrintConvColumns => 3,
- ValueConv => {
- 0 => 'free',
- 1 => 32000,
- 2 => 40000,
- 3 => 48000,
- 4 => 56000,
- 5 => 64000,
- 6 => 80000,
- 7 => 96000,
- 8 => 112000,
- 9 => 128000,
- 10 => 160000,
- 11 => 192000,
- 12 => 224000,
- 13 => 256000,
- 14 => 320000,
- },
- PrintConv => 'ConvertBitrate($val)',
- },
- {
- Name => 'AudioBitrate',
- Condition => '$self->{MPEG_Vers} != 3 and $self->{MPEG_Layer} == 3',
- Notes => 'version 2 or 2.5, layer 1',
- PrintConvColumns => 3,
- ValueConv => {
- 0 => 'free',
- 1 => 32000,
- 2 => 48000,
- 3 => 56000,
- 4 => 64000,
- 5 => 80000,
- 6 => 96000,
- 7 => 112000,
- 8 => 128000,
- 9 => 144000,
- 10 => 160000,
- 11 => 176000,
- 12 => 192000,
- 13 => 224000,
- 14 => 256000,
- },
- PrintConv => 'ConvertBitrate($val)',
- },
- {
- Name => 'AudioBitrate',
- Condition => '$self->{MPEG_Vers} != 3 and $self->{MPEG_Layer}',
- Notes => 'version 2 or 2.5, layer 2 or 3',
- PrintConvColumns => 3,
- ValueConv => {
- 0 => 'free',
- 1 => 8000,
- 2 => 16000,
- 3 => 24000,
- 4 => 32000,
- 5 => 40000,
- 6 => 48000,
- 7 => 56000,
- 8 => 64000,
- 9 => 80000,
- 10 => 96000,
- 11 => 112000,
- 12 => 128000,
- 13 => 144000,
- 14 => 160000,
- },
- PrintConv => 'ConvertBitrate($val)',
- },
- ],
- 'Bit20-21' => [
- {
- Name => 'SampleRate',
- Condition => '$self->{MPEG_Vers} == 3',
- Notes => 'version 1',
- PrintConv => {
- 0 => 44100,
- 1 => 48000,
- 2 => 32000,
- },
- },
- {
- Name => 'SampleRate',
- Condition => '$self->{MPEG_Vers} == 2',
- Notes => 'version 2',
- PrintConv => {
- 0 => 22050,
- 1 => 24000,
- 2 => 16000,
- },
- },
- {
- Name => 'SampleRate',
- Condition => '$self->{MPEG_Vers} == 0',
- Notes => 'version 2.5',
- PrintConv => {
- 0 => 11025,
- 1 => 12000,
- 2 => 8000,
- },
- },
- ],
- # Bit 22 - padding flag
- # Bit 23 - private bit
- 'Bit24-25' => {
- Name => 'ChannelMode',
- RawConv => '$self->{MPEG_Mode} = $val',
- PrintConv => {
- 0 => 'Stereo',
- 1 => 'Joint Stereo',
- 2 => 'Dual Channel',
- 3 => 'Single Channel',
- },
- },
- 'Bit26' => {
- Name => 'MSStereo',
- Condition => '$self->{MPEG_Layer} == 1',
- Notes => 'layer 3',
- PrintConv => { 0 => 'Off', 1 => 'On' },
- },
- 'Bit27' => {
- Name => 'IntensityStereo',
- Condition => '$self->{MPEG_Layer} == 1',
- Notes => 'layer 3',
- PrintConv => { 0 => 'Off', 1 => 'On' },
- },
- 'Bit26-27' => {
- Name => 'ModeExtension',
- Condition => '$self->{MPEG_Layer} > 1',
- Notes => 'layer 1 or 2',
- PrintConv => {
- 0 => 'Bands 4-31',
- 1 => 'Bands 8-31',
- 2 => 'Bands 12-31',
- 3 => 'Bands 16-31',
- },
- },
- 'Bit28' => {
- Name => 'CopyrightFlag',
- PrintConv => {
- 0 => 'False',
- 1 => 'True',
- },
- },
- 'Bit29' => {
- Name => 'OriginalMedia',
- PrintConv => {
- 0 => 'False',
- 1 => 'True',
- },
- },
- 'Bit30-31' => {
- Name => 'Emphasis',
- PrintConv => {
- 0 => 'None',
- 1 => '50/15 ms',
- 2 => 'reserved',
- 3 => 'CCIT J.17',
- },
- },
- );
- %Image::ExifTool::MPEG::Video = (
- GROUPS => { 2 => 'Video' },
- 'Bit00-11' => 'ImageWidth',
- 'Bit12-23' => 'ImageHeight',
- 'Bit24-27' => {
- Name => 'AspectRatio',
- ValueConv => {
- 1 => 1,
- 2 => 0.6735,
- 3 => 0.7031,
- 4 => 0.7615,
- 5 => 0.8055,
- 6 => 0.8437,
- 7 => 0.8935,
- 8 => 0.9157,
- 9 => 0.9815,
- 10 => 1.0255,
- 11 => 1.0695,
- 12 => 1.0950,
- 13 => 1.1575,
- 14 => 1.2015,
- },
- PrintConv => {
- 1 => '1:1',
- 0.6735 => '0.6735',
- 0.7031 => '16:9, 625 line, PAL',
- 0.7615 => '0.7615',
- 0.8055 => '0.8055',
- 0.8437 => '16:9, 525 line, NTSC',
- 0.8935 => '0.8935',
- 0.9157 => '4:3, 625 line, PAL, CCIR601',
- 0.9815 => '0.9815',
- 1.0255 => '1.0255',
- 1.0695 => '1.0695',
- 1.0950 => '4:3, 525 line, NTSC, CCIR601',
- 1.1575 => '1.1575',
- 1.2015 => '1.2015',
- },
- },
- 'Bit28-31' => {
- Name => 'FrameRate',
- ValueConv => {
- 1 => 23.976,
- 2 => 24,
- 3 => 25,
- 4 => 29.97,
- 5 => 30,
- 6 => 50,
- 7 => 59.94,
- 8 => 60,
- },
- PrintConv => '"$val fps"',
- },
- 'Bit32-49' => {
- Name => 'VideoBitrate',
- ValueConv => '$val eq 0x3ffff ? "Variable" : $val * 400',
- PrintConv => 'ConvertBitrate($val)',
- },
- # these tags not very interesting
- #'Bit50' => 'MarkerBit',
- #'Bit51-60' => 'VBVBufferSize',
- #'Bit61' => 'ConstrainedParamFlag',
- #'Bit62' => 'IntraQuantMatrixFlag',
- );
- %Image::ExifTool::MPEG::Xing = (
- GROUPS => { 2 => 'Audio' },
- VARS => { NO_ID => 1 },
- NOTES => 'These tags are extracted from the Xing/Info frame.',
- 1 => { Name => 'VBRFrames' },
- 2 => { Name => 'VBRBytes' },
- 3 => { Name => 'VBRScale' },
- 4 => { Name => 'Encoder' },
- 5 => { Name => 'LameVBRQuality' },
- 6 => { Name => 'LameQuality' },
- 7 => { # (for documentation only)
- Name => 'LameHeader',
- SubDirectory => { TagTable => 'Image::ExifTool::MPEG::Lame' },
- },
- );
- # Lame header tags (ref 5)
- %Image::ExifTool::MPEG::Lame = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- GROUPS => { 2 => 'Audio' },
- NOTES => 'Tags extracted from Lame 3.90 or later header.',
- 9 => {
- Name => 'LameMethod',
- Mask => 0x0f,
- PrintConv => {
- 1 => 'CBR',
- 2 => 'ABR',
- 3 => 'VBR (old/rh)',
- 4 => 'VBR (new/mtrh)',
- 5 => 'VBR (old/rh)',
- 6 => 'VBR',
- 8 => 'CBR (2-pass)',
- 9 => 'ABR (2-pass)',
- },
- },
- 10 => {
- Name => 'LameLowPassFilter',
- ValueConv => '$val * 100',
- PrintConv => '($val / 1000) . " kHz"',
- },
- # 19 - EncodingFlags
- 20 => {
- Name => 'LameBitrate',
- ValueConv => '$val * 1000',
- PrintConv => 'ConvertBitrate($val)',
- },
- 24 => {
- Name => 'LameStereoMode',
- Mask => 0x1c,
- ValueConv => '$val >> 2',
- PrintConv => {
- 0 => 'Mono',
- 1 => 'Stereo',
- 2 => 'Dual Channels',
- 3 => 'Joint Stereo',
- 4 => 'Forced Joint Stereo',
- 6 => 'Auto',
- 7 => 'Intensity Stereo',
- },
- },
- );
- # composite tags
- %Image::ExifTool::MPEG::Composite = (
- Duration => {
- Groups => { 2 => 'Video' },
- Require => {
- 0 => 'FileSize',
- },
- Desire => {
- 1 => 'ID3Size',
- 2 => 'MPEG:AudioBitrate',
- 3 => 'MPEG:VideoBitrate',
- 4 => 'MPEG:VBRFrames',
- 5 => 'MPEG:SampleRate',
- 6 => 'MPEG:MPEGAudioVersion',
- },
- Priority => -1, # (don't want to replace any other Duration tag)
- ValueConv => q{
- if ($val[4] and defined $val[5] and defined $val[6]) {
- # calculate from number of VBR audio frames
- my $mfs = $prt[5] / ($val[6] == 3 ? 144 : 72);
- # calculate using VBR length
- return 8 * $val[4] / $mfs;
- }
- # calculate duration as file size divided by total bitrate
- # (note: this is only approximate!)
- return undef unless $val[2] or $val[3];
- return undef if $val[2] and not $val[2] =~ /^\d+$/;
- return undef if $val[3] and not $val[3] =~ /^\d+$/;
- return (8 * ($val[0] - ($val[1]||0))) / (($val[2]||0) + ($val[3]||0));
- },
- PrintConv => 'ConvertDuration($val) . " (approx)"',
- },
- AudioBitrate => {
- Groups => { 2 => 'Audio' },
- Notes => 'calculated for variable-bitrate MPEG audio',
- Require => {
- 0 => 'MPEG:MPEGAudioVersion',
- 1 => 'MPEG:SampleRate',
- 2 => 'MPEG:VBRBytes',
- 3 => 'MPEG:VBRFrames',
- },
- ValueConv => q{
- return undef unless $val[3];
- my $mfs = $prt[1] / ($val[0] == 3 ? 144 : 72);
- return $mfs * $val[2] / $val[3];
- },
- PrintConv => 'ConvertBitrate($val)',
- },
- );
- # add our composite tags
- Image::ExifTool::AddCompositeTags('Image::ExifTool::MPEG');
- #------------------------------------------------------------------------------
- # Process information in an MPEG audio or video frame header
- # Inputs: 0) ExifTool object ref, 1) tag table ref, 2-N) list of 32-bit data words
- sub ProcessFrameHeader($$@)
- {
- my ($et, $tagTablePtr, @data) = @_;
- my $tag;
- foreach $tag (sort keys %$tagTablePtr) {
- next unless $tag =~ /^Bit(\d{2})-?(\d{2})?/;
- my ($b1, $b2) = ($1, $2 || $1);
- my $index = int($b1 / 32);
- my $word = $data[$index];
- my $mask = 0;
- foreach (0 .. ($b2 - $b1)) {
- $mask += (1 << $_);
- }
- my $val = ($word >> (31 + 32*$index - $b2)) & $mask;
- $et->HandleTag($tagTablePtr, $tag, $val);
- }
- }
- #------------------------------------------------------------------------------
- # Read MPEG audio frame header
- # Inputs: 0) ExifTool object reference, 1) Reference to audio data
- # 2) flag set if we are trying to recognized MP3 file only
- # Returns: 1 on success, 0 if no audio header was found
- sub ParseMPEGAudio($$;$)
- {
- my ($et, $buffPt, $mp3) = @_;
- my ($word, $pos);
- my $ext = $$et{FILE_EXT} || '';
- for (;;) {
- # find frame sync
- return 0 unless $$buffPt =~ m{(\xff.{3})}sg;
- $word = unpack('N', $1); # get audio frame header word
- unless (($word & 0xffe00000) == 0xffe00000) {
- pos($$buffPt) = pos($$buffPt) - 2; # next possible location for frame sync
- next;
- }
- # validate header as much as possible
- if (($word & 0x180000) == 0x080000 or # 01 is a reserved version ID
- ($word & 0x060000) == 0x000000 or # 00 is a reserved layer description
- ($word & 0x00f000) == 0x000000 or # 0000 is the "free" bitrate index
- ($word & 0x00f000) == 0x00f000 or # 1111 is a bad bitrate index
- ($word & 0x000c00) == 0x000c00 or # 11 is a reserved sampling frequency
- ($word & 0x000003) == 0x000002 or # 10 is a reserved emphasis
- (($mp3 and ($word & 0x060000) != 0x020000))) # must be layer 3 for MP3
- {
- # give up easily unless this really should be an MP3 file
- return 0 unless $ext eq 'MP3';
- pos($$buffPt) = pos($$buffPt) - 1;
- next;
- }
- $pos = pos($$buffPt);
- last;
- }
- # set file type if not done already
- $et->SetFileType();
- my $tagTablePtr = GetTagTable('Image::ExifTool::MPEG::Audio');
- ProcessFrameHeader($et, $tagTablePtr, $word);
- # extract the VBR information (ref MP3::Info)
- my ($v, $m) = ($$et{MPEG_Vers}, $$et{MPEG_Mode});
- while (defined $v and defined $m) {
- my $len = length $$buffPt;
- $pos += $v == 3 ? ($m == 3 ? 17 : 32) : ($m == 3 ? 9 : 17);
- last if $pos + 8 > $len;
- my $buff = substr($$buffPt, $pos, 8);
- last unless $buff =~ /^(Xing|Info)/;
- my $xingTable = GetTagTable('Image::ExifTool::MPEG::Xing');
- my $vbrScale;
- my $flags = unpack('x4N', $buff);
- my $isVBR = ($buff !~ /^Info/); # Info frame is not VBR (ref 5)
- $pos += 8;
- if ($flags & 0x01) { # VBRFrames
- last if $pos + 4 > $len;
- $et->HandleTag($xingTable, 1, unpack("x${pos}N", $$buffPt)) if $isVBR;
- $pos += 4;
- }
- if ($flags & 0x02) { # VBRBytes
- last if $pos + 4 > $len;
- $et->HandleTag($xingTable, 2, unpack("x${pos}N", $$buffPt)) if $isVBR;
- $pos += 4;
- }
- if ($flags & 0x04) { # VBR_TOC
- last if $pos + 100 > $len;
- # (ignore toc for now)
- $pos += 100;
- }
- if ($flags & 0x08) { # VBRScale
- last if $pos + 4 > $len;
- $vbrScale = unpack("x${pos}N", $$buffPt);
- $et->HandleTag($xingTable, 3, $vbrScale) if $isVBR;
- $pos += 4;
- }
- # process Lame header (ref 5)
- if ($flags & 0x10) { # Lame
- last if $pos + 348 > $len;
- } elsif ($pos + 4 <= $len) {
- my $lib = substr($$buffPt, $pos, 4);
- unless ($lib eq 'LAME' or $lib eq 'GOGO') {
- # attempt to identify other encoders
- my $n;
- if (index($$buffPt, 'RCA mp3PRO Encoder') >= 0) {
- $lib = 'RCA mp3PRO';
- } elsif (($n = index($$buffPt, 'THOMSON mp3PRO Encoder')) >= 0) {
- $lib = 'Thomson mp3PRO';
- $n += 22;
- $lib .= ' ' . substr($$buffPt, $n, 6) if length($$buffPt) - $n >= 6;
- } elsif (index($$buffPt, 'MPGE') >= 0) {
- $lib = 'Gogo (<3.0)';
- } else {
- last;
- }
- $et->HandleTag($xingTable, 4, $lib);
- last;
- }
- }
- my $lameLen = $len - $pos;
- last if $lameLen < 9;
- my $enc = substr($$buffPt, $pos, 9);
- if ($enc ge 'LAME3.90') {
- $et->HandleTag($xingTable, 4, $enc);
- if ($vbrScale <= 100) {
- $et->HandleTag($xingTable, 5, int((100 - $vbrScale) / 10));
- $et->HandleTag($xingTable, 6, (100 - $vbrScale) % 10);
- }
- my %dirInfo = (
- DataPt => $buffPt,
- DirStart => $pos,
- DirLen => length($$buffPt) - $pos,
- );
- my $subTablePtr = GetTagTable('Image::ExifTool::MPEG::Lame');
- $et->ProcessDirectory(\%dirInfo, $subTablePtr);
- } else {
- $et->HandleTag($xingTable, 4, substr($$buffPt, $pos, 20));
- }
- last; # (didn't want to loop anyway)
- }
- return 1;
- }
- #------------------------------------------------------------------------------
- # Read MPEG video frame header
- # Inputs: 0) ExifTool object reference, 1) Reference to video data
- # Returns: 1 on success, 0 if no video header was found
- sub ProcessMPEGVideo($$)
- {
- my ($et, $buffPt) = @_;
- return 0 unless length $$buffPt >= 4;
- my ($w1, $w2) = unpack('N2', $$buffPt);
- # validate as much as possible
- if (($w1 & 0x000000f0) == 0x00000000 or # 0000 is a forbidden aspect ratio
- ($w1 & 0x000000f0) == 0x000000f0 or # 1111 is a reserved aspect ratio
- ($w1 & 0x0000000f) == 0 or # frame rate must be 1-8
- ($w1 & 0x0000000f) > 8)
- {
- return 0;
- }
- # set file type if not done already
- $et->SetFileType('MPEG') unless $$et{VALUE}{FileType};
- my $tagTablePtr = GetTagTable('Image::ExifTool::MPEG::Video');
- ProcessFrameHeader($et, $tagTablePtr, $w1, $w2);
- return 1;
- }
- #------------------------------------------------------------------------------
- # Read MPEG audio and video frame headers
- # Inputs: 0) ExifTool object reference, 1) Reference to audio/video data
- # Returns: 1 on success, 0 if no video header was found
- # To Do: Properly parse MPEG streams:
- # 0xb7 - sequence end
- # 0xb9 - end code
- # 0xba - pack start code
- # 0xbb - system header
- # 0xbc - program map <-- should parse this
- # 0xbd - private stream 1 --> for VOB, this contains sub-streams:
- # 0x20-0x3f - pictures
- # 0x80-0x87 - audio (AC3,DTS,SDDS)
- # 0xa0-0xa7 - audio (LPCM)
- # 0xbe - padding
- # 0xbf - private stream 2
- # 0xc0-0xdf - audio stream
- # 0xe0-0xef - video stream
- sub ParseMPEGAudioVideo($$)
- {
- my ($et, $buffPt) = @_;
- my (%found, $didHdr);
- my $rtnVal = 0;
- my %proc = ( audio => \&ParseMPEGAudio, video => \&ProcessMPEGVideo );
- delete $$et{AudioBitrate};
- delete $$et{VideoBitrate};
- while ($$buffPt =~ /\0\0\x01(\xb3|\xc0)/g) {
- my $type = $1 eq "\xb3" ? 'video' : 'audio';
- unless ($didHdr) {
- # make sure we didn't miss an audio frame sync before this (eg. MP3 file)
- # (the last byte of the 4-byte MP3 audio frame header word may be zero,
- # but the 2nd last must be non-zero, so we need only check to pos-3)
- my $buff = substr($$buffPt, 0, pos($$buffPt) - 3);
- $found{audio} = 1 if ParseMPEGAudio($et, \$buff);
- $didHdr = 1;
- }
- next if $found{$type};
- my $len = length($$buffPt) - pos($$buffPt);
- last if $len < 4;
- $len > 256 and $len = 256;
- my $dat = substr($$buffPt, pos($$buffPt), $len);
- # process MPEG audio or video
- if (&{$proc{$type}}($et, \$dat)) {
- $rtnVal = 1;
- $found{$type} = 1;
- # done if we found audio and video
- last if scalar(keys %found) == 2;
- }
- }
- return $rtnVal;
- }
- #------------------------------------------------------------------------------
- # Read information from an MPEG file
- # Inputs: 0) ExifTool object reference, 1) Directory information reference
- # Returns: 1 on success, 0 if this wasn't a valid MPEG file
- sub ProcessMPEG($$)
- {
- my ($et, $dirInfo) = @_;
- my $raf = $$dirInfo{RAF};
- my $buff;
- $raf->Read($buff, 4) == 4 or return 0;
- return 0 unless $buff =~ /^\0\0\x01[\xb0-\xbf]/;
- $et->SetFileType();
- $raf->Seek(0,0);
- $raf->Read($buff, 65536*4) or return 0;
- return ParseMPEGAudioVideo($et, \$buff);
- }
- 1; # end
- __END__
- =head1 NAME
- Image::ExifTool::MPEG - Read MPEG-1 and MPEG-2 meta information
- =head1 SYNOPSIS
- This module is used by Image::ExifTool
- =head1 DESCRIPTION
- This module contains definitions required by Image::ExifTool to read MPEG-1
- and MPEG-2 audio/video files.
- =head1 NOTES
- Since ISO charges money for the official MPEG specification, this module is
- based on unofficial sources which may be incomplete, inaccurate or outdated.
- =head1 AUTHOR
- Copyright 2003-2016, Phil Harvey (phil at owl.phy.queensu.ca)
- This library is free software; you can redistribute it and/or modify it
- under the same terms as Perl itself.
- =head1 REFERENCES
- =over 4
- =item L<http://www.mp3-tech.org/>
- =item L<http://www.getid3.org/>
- =item L<http://dvd.sourceforge.net/dvdinfo/dvdmpeg.html>
- =item L<http://ffmpeg.org/>
- =item L<http://sourceforge.net/projects/mediainfo/>
- =back
- =head1 SEE ALSO
- L<Image::ExifTool::TagNames/MPEG Tags>,
- L<MP3::Info(3pm)|MP3::Info>,
- L<Image::ExifTool(3pm)|Image::ExifTool>
- =cut
|