--- amv.pl 2007/07/19 20:17:37 3 +++ amv.pl 2007/07/19 21:16:30 7 @@ -3,6 +3,10 @@ # amv.pl # # 07/19/07 19:21:39 CEST Dobrica Pavlinusic +# +# Various useful links used to produce this: +# http://www.moviecodec.com/topics/15431p1.html +# http://en.wikipedia.org/wiki/RIFF_(File_format) use strict; @@ -13,6 +17,12 @@ open(my $fh, '<', $path) || die "can't open $path: $!"; +# offset in file +my $o = 0; + +# shared data hash +my $d; + sub hex_dump { my $bytes = shift || return; @@ -20,17 +30,20 @@ $ascii =~ s/\W/./gs; my $hex = unpack('h*', $bytes); $hex =~ s/(..)/$1 /g; - my $o = 0; # calculate number of characters for offset - my $d = length( sprintf("%x",length($bytes)) ); + #my $d = length( sprintf("%x",length($bytes)) ); + my $d = 4; + my $prefix = '#.'; while ( $hex =~ s/^((?:\w\w\s){1,16})// ) { - printf "## %0${d}x | %-48s| %s\n", $o, $1, substr( $ascii, 0, 16 ); + printf "$prefix %0${d}x | %-48s| %s\n", $o, $1, substr( $ascii, 0, 16 ); + $prefix = '##'; if ( length($ascii) >= 16 ) { $ascii = substr( $ascii, 16 ); + $o += 16; } else { + $o += length($ascii); last; } - $o += 16; } } @@ -45,9 +58,15 @@ hex_dump( $bytes ); + if ( $bytes eq 'AMV_END_' ) { + warn "> end of file marker AMV_END_\n"; + $d->{eof}++; + return; + } + if ( $format ) { my @data = unpack($format, $bytes); - dump(@data); + warn "## unpacked = ",dump(@data),"\n"; return @data; } else { return $bytes; @@ -57,11 +76,12 @@ sub next_part { my ( $expected_part, $expected_len, $skip ) = @_; my ( $part, $len ) = x(8,'A4V'); + return unless $len; confess "not $expected_part but $part" if $expected_part ne $part; if ( $expected_len ) { confess "expected $expected_len bytes for $part got $len" if $len != $expected_len; } - printf ">> %s | %d 0x%x bytes\n", $part, $len, $len; + printf ">> %s - %d 0x%x bytes\n", $part, $len, $len; x($len) if $skip; return $len; } @@ -70,9 +90,7 @@ die "not RIFF but $riff" if $riff ne 'RIFF'; die "not AMV but $amv" if $amv ne 'AMV '; -my $d; - -while ( 1 ) { +while ( ! defined($d->{eof}) ) { my ( $list, $name ) = x(12,'A4x4A4'); die "not LIST but $list" if $list ne 'LIST'; print "> $list .. $name\n"; @@ -80,18 +98,7 @@ if ( $name eq 'hdrl' ) { my $len = next_part( 'amvh', hex(38) ); - - print ">> $name $len\n"; - my ( - $ms_per_frame, - $width, - $height, - $fps, - $ss, - $mm, - $hh, - ) = my @names = ( qw/ms_per_frame width height fps ss mm hh/ ); my $h; map { @@ -112,6 +119,19 @@ next_part( 'strh', 0, 1 ); next_part( 'strf', 0, 1 ); + } elsif ( $name eq 'movi' ) { + + while (1) { + my $frame = $d->{movi}++; + + my $len = next_part( '00dc', 0, 1 ); + last unless $len; + printf ">> %s 00dc - frame %d jpeg %d 0x%x bytes\n", $name, $frame, $len, $len; + + my $len = next_part( '01wb', 0, 1 ); + printf ">> %s 01wb - frame %d audio %d 0x%x bytes\n", $name, $frame, $len, $len; + }; + } else { die "unknown $list $name"; }