template-project/node_modules/exiftool-vendored.pl/bin/lib/Image/ExifTool/AAC.pm
2025-05-30 18:13:30 +08:00

178 lines
5.1 KiB
Perl

#------------------------------------------------------------------------------
# File: AAC.pm
#
# Description: Read AAC audio files
#
# Revisions: 2023-12-29 - P. Harvey Created
#------------------------------------------------------------------------------
package Image::ExifTool::AAC;
use strict;
use vars qw($VERSION);
use Image::ExifTool qw(:DataAccess :Utils);
use Image::ExifTool::FLAC;
$VERSION = '1.00';
my %convSampleRate = (
0 => 96000, 7 => 22050,
1 => 88200, 8 => 16000,
2 => 64000, 9 => 12000,
3 => 48000, 10 => 11025,
4 => 44100, 11 => 8000,
5 => 32000, 12 => 7350,
6 => 24000,
);
%Image::ExifTool::AAC::Main = (
PROCESS_PROC => \&Image::ExifTool::FLAC::ProcessBitStream,
GROUPS => { 2 => 'Audio' },
NOTES => 'Tags extracted from Advanced Audio Coding (AAC) files.',
# Bit000-011 - sync word (all 1's)
# Bit012 - ID (seems to be always 0)
# Bit013-014 - layer (00)
# Bit015 - CRC absent (0=crc exists, 1=no crc)
'Bit016-017' => {
Name => 'ProfileType',
PrintConv => {
0 => 'Main',
1 => 'Low Complexity',
2 => 'Scalable Sampling Rate',
},
},
'Bit018-021' => {
Name => 'SampleRate',
ValueConv => \%convSampleRate,
},
# Bit022 - private
'Bit023-025' => {
Name => 'Channels',
PrintConv => {
0 => '?',
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => '5+1',
7 => '7+1',
},
},
# Bit026 - original/copy
# Bit027 - home
# Bit028 - copyright ID
# Bit029 - copyright start
# Bit030-042 - FrameLength
# Bit043-053 - buffer fullness
# Bit054-055 - BlocksInFrame (minus 1)
# Note: Bitrate for frame = FrameLength * 8 * SampleRate / ((BlocksInFrame+1) * 1024)
# - but all frames must be scanned to calculate average bitrate
Encoder => {
Name => 'Encoder',
Notes => 'taken from filler payload of first frame',
},
);
#------------------------------------------------------------------------------
# Read information from an AAC file
# Inputs: 0) ExifTool object reference, 1) Directory information reference
# Returns: 1 on success, 0 if this wasn't a valid AAC file
sub ProcessAAC($$)
{
my ($et, $dirInfo) = @_;
my $raf = $$dirInfo{RAF};
my ($buff, $buf2);
# format of frame header (7 bytes):
# SSSS SSSS SSSS ILLC PPRR RRpC CCoh csff ffff ffff fffb bbbb bbbb bbNN
# 1111 1111 1111 0001 0110 0000 0100 0000 0000 0101 0101 1111 1111 1100 (eg.)
# S = sync word o = original/copy
# I = ID h = home
# L = layer (00) c = copyright ID
# C = CRC absent s = copyright start
# P = profile object type f = frame length
# R = sampling rate index b = buffer fullness
# p = private N = number of raw data blocks in frame
# C = channel configuration
$raf->Read($buff, 7) == 7 or return 0;
return 0 unless $buff =~ /^\xff[\xf0\xf1]/;
my @t = unpack('NnC', $buff);
return 0 if (($t[0] >> 16) & 0x03) == 3; # (reserved profile type)
return 0 if (($t[0] >> 12) & 0x0f) > 12; # validate sampling frequency index
my $len = (($t[0] << 11) & 0x1800) | (($t[1] >> 5) & 0x07ff);
return 0 if $len < 7;
$et->SetFileType();
my $tagTablePtr = GetTagTable('Image::ExifTool::AAC::Main');
$et->ProcessDirectory({ DataPt => \$buff }, $tagTablePtr);
# read the first frame data to check for a filler with the encoder name
while ($len > 8 and $raf->Read($buff, $len-7) == $len-7) {
my $noCRC = ($t[0] & 0x00010000);
my $blocks = ($t[2] & 0x03);
my $pos = 0;
$pos += 2 + 2 * $blocks unless $noCRC;
last if $pos + 2 > length($buff);
my $tmp = unpack("x${pos}n", $buff);
my $id = $tmp >> 13;
# read filler payload
if ($id == 6) {
my $cnt = ($tmp >> 9) & 0x0f;
++$pos;
if ($cnt == 15) {
$cnt += (($tmp >> 1) & 0xff) - 1;
++$pos;
}
if ($pos + $cnt <= length($buff)) {
my $dat = substr($buff, $pos, $cnt);
$dat =~ s/^\0+//;
$dat =~ s/\0+$//;
$et->HandleTag($tagTablePtr, Encoder => $dat) if $dat =~ /^[\x20-\x7e]+$/;
}
}
last;
}
return 1;
}
1; # end
__END__
=head1 NAME
Image::ExifTool::AAC - Read AAC audio files
=head1 SYNOPSIS
This module is used by Image::ExifTool
=head1 DESCRIPTION
This module contains definitions required by Image::ExifTool to read
Advanced Audio Coding (AAC) files.
=head1 NOTES
Since ISO charges money for the official AAC specification, this module is
based on unofficial sources which may be incomplete, inaccurate or outdated.
=head1 AUTHOR
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
=head1 SEE ALSO
L<Image::ExifTool::TagNames/AAC Tags>,
L<Image::ExifTool(3pm)|Image::ExifTool>
=cut