Audio-M4P
view release on metacpan or search on metacpan
lib/Audio/M4P/Atom.pm view on Meta::CPAN
package Audio::M4P::Atom;
require 5.006;
use strict;
use warnings;
use Carp;
our $VERSION = '0.54';
use Scalar::Util 'weaken';
use Tree::Simple 'use_weak_refs';
use Tree::Simple::Visitor;
use Tree::Simple::View::HTML;
# see http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
my %container_atom_types = (
aaid => 1,
akid => 1,
'©alb' => 1,
apid => 1,
aART => 1,
'©ART' => 1,
atid => 1,
clip => 1,
'©cmt' => 1,
'©com' => 1,
covr => 1,
cpil => 1,
cprt => 1,
'©day' => 1,
dinf => 1,
disk => 1,
drms => 1,
edts => 1,
geid => 1,
gnre => 1,
'©grp' => 1,
hinf => 1,
hnti => 1,
ilst => 1,
matt => 1,
mdia => 1,
meta => 1,
minf => 1,
moof => 1,
moov => 1,
mp4a => 1,
'©nam' => 1,
pinf => 1,
plid => 1,
rtng => 1,
schi => 1,
sinf => 1,
stbl => 1,
stik => 1,
stsd => 1,
tmpo => 1,
'©too' => 1,
traf => 1,
trak => 1,
trkn => 1,
udta => 1,
'©wrt' => 1,
);
my %noncontainer_atom_types = (
chtb => 1,
ctts => 1,
data => 1,
esds => 1,
free => 1,
frma => 1,
ftyp => 1,
'©gen' => 1,
hmhd => 1,
iviv => 1,
'key ' => 1,
mdat => 1,
mdhd => 1,
mp4s => 1,
mpv4 => 1,
mvhd => 1,
name => 1,
priv => 1,
rtp => 1,
sign => 1,
stco => 1,
stsc => 1,
stp => 1,
stts => 1,
tfhd => 1,
tkhd => 1,
tref => 1,
trun => 1,
user => 1,
vmhd => 1,
wide => 1,
);
sub int64toN {
my ($int64) = @_;
my $high32bits = pack( 'N', int( $int64 / ( 2**32 ) + 0.0001 ) );
my $low32bits = pack( 'N', $int64 % ( 2**32 ) );
return $high32bits . $low32bits;
}
sub int64fromN {
my ($buf) = @_;
my ( $high32bits, $low32bits ) = unpack( "NN", $buf );
return ( $high32bits * ( 2**32 ) ) + $low32bits;
}
# begin class methods
sub new {
my ( $class, %args ) = @_;
my $self = \%args;
bless( $self, $class );
$self->{node} = Tree::Simple->new($self);
if( ref $self->{parent} ) {
$self->{parent}->addChild( $self->{node} );
weaken $self->{node};
weaken $self->{parent};
}
else {
$self->{parent} = 0;
}
if( ref $self->{rbuf} ) {
weaken $self->{rbuf};
$self->read_buffer( $self->{read_buffer_position} )
if exists $self->{read_buffer_position};
}
return $self;
}
sub DESTROY {
my($self) = @_;
delete $self->{parent};
delete $self->{rbuf};
return unless ref $self->{node};
my @kids = $self->{node}->getAllChildren();
foreach my $child (@kids) {
next unless ref $child;
my $val = $child->getNodeValue();
$val->DESTROY
if ref $val
and ref $val->{parent}
and $val->{parent} eq $self;
}
$self->{node}->DESTROY if ref $self->{node};
delete $self->{node};
}
sub parent { return shift->{parent} }
sub node { return shift->{node} }
sub rbuf { return shift->{rbuf} }
sub read_buffer {
my ( $self, $starting ) = @_;
$self->{start} = $starting;
$self->{offset} = 8;
( $self->{size}, $self->{type} ) = unpack 'Na4',
substr( ${ $self->{rbuf} }, $starting, 8 );
if ( $self->{size} == 1 ) {
$self->{size} =
int64fromN( substr( ${ $self->{rbuf} }, $starting + 8, 8 ) );
$self->{offset} = 16;
}
return $self->{size};
}
sub type {
my ( $self, $newtype ) = @_;
if ( defined $newtype ) {
$self->{type} = substr( $newtype, 0, 4 );
substr( ${ $self->{rbuf} }, $self->{start} + 4, 4, $self->{type} );
}
return $self->{type};
}
sub start {
my ( $self, $newstart ) = @_;
$self->{start} = $newstart if defined $newstart;
return $self->{start};
}
sub size {
( run in 1.737 second using v1.01-cache-2.11-cpan-97f6503c9c8 )