/[amv]/amv.pl
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /amv.pl

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 23 by dpavlin, Sat Jul 21 17:03:56 2007 UTC revision 24 by dpavlin, Sun Jul 22 11:05:47 2007 UTC
# Line 9  Line 9 
9  # http://en.wikipedia.org/wiki/RIFF_(File_format)  # http://en.wikipedia.org/wiki/RIFF_(File_format)
10  # http://www.obrador.com/essentialjpeg/HeaderInfo.htm  # http://www.obrador.com/essentialjpeg/HeaderInfo.htm
11  # http://lists.helixcommunity.org/pipermail/datatype-dev/2005-January/001886.html  # http://lists.helixcommunity.org/pipermail/datatype-dev/2005-January/001886.html
12    # http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm
13    
14  use strict;  use strict;
15    
# Line 19  use Getopt::Long; Line 20  use Getopt::Long;
20    
21  my $dump = 0;  my $dump = 0;
22  my $debug = 0;  my $debug = 0;
23    my $verbose = 0;
24  my $dump_dir = '/tmp/dump/';  my $dump_dir = '/tmp/dump/';
25  my $dump_avi = "dump.avi";  my $dump_avi = "dump.avi";
26  my $no_jpeg_header = 0;  my $no_jpeg_header = 0;
27  my $jpeg_q = 100;  my $jpeg_q = 100;
28  my $jpegtran = '-flip vertical';  my $jpegtran;
29    
30  GetOptions(  GetOptions(
31          "dump!"                 => \$dump,          "dump!"                 => \$dump,
32          "debug!"                => \$debug,          "debug!"                => \$debug,
33          "dump-dir=s"    => \$dump_dir,          "dump-dir=s"    => \$dump_dir,
34          "no-jpeg-headers!" => \$no_jpeg_header,          "no-jpeg-headers!" => \$no_jpeg_header,
35          "jpegtran=s"    => \$jpegtran          "jpegtran=s"    => \$jpegtran,
36            "verbose!"              => \$verbose,
37  );  );
38    
39  my $path = shift @ARGV || die "usage: $0 movie.amv\n";  my $path = shift @ARGV || die "usage: $0 movie.amv\n";
40    
41    # by default, flip frames
42    #$jpegtran = '-flip vertical' unless defined($jpegtran);
43    
44  rmtree $dump_dir if -e $dump_dir;  rmtree $dump_dir if -e $dump_dir;
45  mkpath $dump_dir || die "can't create $dump_dir: $!";  mkpath $dump_dir || die "can't create $dump_dir: $!";
# Line 116  sub next_part { Line 121  sub next_part {
121          if ( $expected_len ) {          if ( $expected_len ) {
122                  confess "expected $expected_len bytes for $part got $len" if $len != $expected_len;                  confess "expected $expected_len bytes for $part got $len" if $len != $expected_len;
123          }          }
124          printf "<< %s - %d 0x%x bytes\n", $part, $len, $len;          printf "## next_part %s - %d 0x%x bytes\n", $part, $len, $len if $debug;
125          x($len) if $skip;          x($len) if $skip;
126          return $len;          return $len;
127  }  }
# Line 144  sub quality { Line 149  sub quality {
149          return $out;          return $out;
150  }  }
151    
152    sub mp3_frame {
153            my $frame = join('',
154                    # Frame sync (all bits set)
155                    1 x 11 .
156                    # MPEG Audio version ID
157                    # 00 - MPEG Version 2.5 (unofficial)
158                    # 01 - reserved
159                    # 10 - MPEG Version 2 (ISO/IEC 13818-3)
160                    # 11 - MPEG Version 1 (ISO/IEC 11172-3)
161                    1,0,
162                    # Layer description
163                    # 00 - reserved
164                    # 01 - Layer III
165                    # 10 - Layer II
166                    # 11 - Layer I
167                    0,1,
168                    # Protection bit
169                    # 0 - Protected by CRC (16bit crc follows header)
170                    # 1 - Not protected
171                    0,
172                    # Bitrate index
173                    0,0,0,0,
174                    # Sampling rate frequency index (22050)
175                    0,0,
176                    # Padding bit
177                    # 0 - frame is not padded
178                    # 1 - frame is padded with one extra slot
179                    0,
180                    # Private bit
181                    0,
182                    # Channel Mode
183                    # 00 - Stereo
184                    # 01 - Joint stereo (Stereo)
185                    # 10 - Dual channel (2 mono channels)
186                    # 11 - Single channel (Mono)
187                    1,1,
188                    # Mode extension (Only if Joint stereo)
189                    0,0,
190                    # Copyright
191                    0,
192                    # Original
193                    0,
194                    # Emphasis
195                    # 00 - none
196                    # 01 - 50/15 ms
197                    # 10 - reserved
198                    # 11 - CCIT J.17
199                    0,0,
200            );
201    
202            die "frame must have 32 bits, not ", length($frame), " for $frame" if length($frame) != 32;
203    
204            my $bits = pack("b32", $frame);
205    
206            die "packed bits must be 4 bytes, not $bits" if length($bits) != 4;
207    
208            my $t = $frame;
209            $t =~ s/(.{8})/$1 /g;
210            warn "## mp3 frame frame = $t\n";
211    
212            return $bits;
213    }
214    
215  my @subframes;  my @subframes;
216  my $frame_nr = 1;  my $frame_nr = 1;
217    
# Line 159  sub mkjpg { Line 227  sub mkjpg {
227    
228          if ( $#subframes < ( $join_subframes - 1 ) ) {          if ( $#subframes < ( $join_subframes - 1 ) ) {
229                  push @subframes, $data;                  push @subframes, $data;
230                  print "## saved $frame_nr/", $#subframes + 1, " subframe of ", length($data), " bytes\n";                  print "## saved $frame_nr/", $#subframes + 1, " subframe of ", length($data), " bytes\n" if $debug;
231                  return;                  return;
232          }          }
233    
# Line 293  sub mkjpg { Line 361  sub mkjpg {
361          my $frame = join('', @subframes ) . $data;          my $frame = join('', @subframes ) . $data;
362          @subframes = ();          @subframes = ();
363    
364          my $path = sprintf("$dump_dir/%04d.jpg", $frame_nr++ );          my $path = sprintf("$dump_dir/%04d.jpg", $frame_nr );
365    
366          my $fh;          my $fh;
367          if ( $jpegtran ) {          if ( $jpegtran ) {
# Line 308  sub mkjpg { Line 376  sub mkjpg {
376                  print $fh $frame || die "can't write raw jpeg $path: $!";                  print $fh $frame || die "can't write raw jpeg $path: $!";
377          }          }
378          close $fh || die "can't close $path: $!";          close $fh || die "can't close $path: $!";
379          print ">> created $frame_nr ", $no_jpeg_header ? 'raw' : '', " jpeg $path ", -s $path, " bytes\n";          print ">> created $frame_nr ", $no_jpeg_header ? 'raw' : '', " jpeg $path ", -s $path, " bytes\n" if $verbose;
380  }  }
381    
382  my ( $riff, $amv ) = x(12, 'Z4x4Z4');  my ( $riff, $amv ) = x(12, 'Z4x4Z4');
383  die "$path not RIFF but $riff" if $riff ne 'RIFF';  die "$path not RIFF but $riff" if $riff ne 'RIFF';
384  die "$path not AMV but $amv" if $amv ne 'AMV ';  die "$path not AMV but $amv" if $amv ne 'AMV ';
385    
386    my $apath = "$dump_dir/audio.wav";
387    open(my $audio_fh, '>', $apath) || die "can't open audio file $apath: $!";
388    
389    print $audio_fh pack 'a4Va4a4VvvVVv4', (
390            # header 'RIFF', size
391            'RIFF',-1,
392            # type: 'WAVE'
393            'WAVE',
394            'fmt ',0x14,
395            # format: DVI (IMA) ADPCM Wave Type
396            0x11,
397            # channels
398            1,
399            # samples/sec
400            22050,
401            # avg. bytes/sec (for esimation)
402            11567,
403            # block align (size of block)
404            0x800,
405            # bits per sample (mono data)
406            4,
407            # cbSize (ADPCM with 7 soefficient pairs)
408            2,
409            # nSamplesPerBlock
410            # (((nBlockAlign - (7 * nChannels)) * 8) / (wBitsPerSample * nChannels)) + 2
411            0x0ff9,
412    );
413    
414    print $audio_fh pack 'a4VVa4V', (
415            # time length of the data in samples
416            'fact',4,
417            220500,
418            #
419            'data',-1,
420    );
421    
422    my $riff_header_len = tell($audio_fh);
423    
424  while ( ! defined($d->{eof}) ) {  while ( ! defined($d->{eof}) ) {
425          my ( $list, $name ) = x(12,'A4x4A4');          my ( $list, $name ) = x(12,'A4x4A4');
426          die "not LIST but $list" if $list ne 'LIST';          die "not LIST but $list" if $list ne 'LIST';
427          print "< $list * $name\n";          print "< $list * $name\n" if $verbose;
428    
429          if ( $name eq 'hdrl' ) {          if ( $name eq 'hdrl' ) {
430    
# Line 351  while ( ! defined($d->{eof}) ) { Line 457  while ( ! defined($d->{eof}) ) {
457                                    
458                          my $len = next_part( '00dc' );                          my $len = next_part( '00dc' );
459                          last unless $len;                          last unless $len;
460                          printf "<< %s 00dc - frame %d jpeg %d 0x%x bytes\n", $name, $frame, $len, $len;                          printf "<< %s 00dc - part %d jpeg %d 0x%x bytes\n", $name, $frame, $len, $len if $verbose;
461                          mkjpg( x($len) );                          mkjpg( x($len) );
462    
463                          $len = next_part( '01wb', 0, 1 );                          $len = next_part( '01wb' );
464                          printf "<< %s 01wb - frame %d audio %d 0x%x bytes\n", $name, $frame, $len, $len;                          printf "<< %s 01wb - part %d audio %d 0x%x bytes\n", $name, $frame, $len, $len if $verbose;
465    
466                            my $audio_frame = x( $len );
467    
468                            # remove 8 bytes of something
469                            $audio_frame = substr( $audio_frame, 8 );
470    
471                            if ( length($audio_frame) % 2 == 0 ) {
472                                    print "#### even sized frame!";
473    #                               $audio_frame = substr( $audio_frame, 0, -1 );
474                            }
475    
476                            if ( $dump ) {
477                                    print "#### dumping audio frame ", length($audio_frame), " bytes\n";
478                                    hex_dump( $audio_frame );
479                            }
480    
481    #                       print $audio_fh mp3_frame;
482                            print $audio_fh $audio_frame || die "can't write audio frame in $apath: $!";
483    
484                            $frame_nr++;
485                  };                  };
486    
487          } else {          } else {
# Line 366  while ( ! defined($d->{eof}) ) { Line 492  while ( ! defined($d->{eof}) ) {
492  my $cmd = "ffmpeg -i $dump_dir/%04d.jpg -r 16 -y $dump_avi";  my $cmd = "ffmpeg -i $dump_dir/%04d.jpg -r 16 -y $dump_avi";
493  system($cmd) == 0 || die "can't convert frames to avi using $cmd: $!";  system($cmd) == 0 || die "can't convert frames to avi using $cmd: $!";
494    
495    my $size = tell($audio_fh);
496    warn "## wav file size: $size\n";
497    
498    seek( $audio_fh, 4, 0 );
499    print $audio_fh pack("V", $size - 8);
500    seek( $audio_fh, $riff_header_len - 4, 0 );
501    print $audio_fh pack("V", $size - $riff_header_len);
502    
503    close($audio_fh) || die "can't close audio file $apath: $!";
504    
505    print ">>>> created $frame_nr frames $dump_avi ", -s $dump_avi, " and $apath ", -s $apath, "\n";

Legend:
Removed from v.23  
changed lines
  Added in v.24

  ViewVC Help
Powered by ViewVC 1.1.26