/[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 28 by dpavlin, Sun Aug 19 11:45:39 2007 UTC revision 33 by dpavlin, Mon Oct 1 20:26:13 2007 UTC
# Line 46  GetOptions( Line 46  GetOptions(
46  my $path = shift @ARGV || die "usage: $0 movie.amv\n";  my $path = shift @ARGV || die "usage: $0 movie.amv\n";
47    
48  # by default, flip frames  # by default, flip frames
49  #$jpegtran = '-flip vertical' unless defined($jpegtran);  $jpegtran = '-flip vertical' unless defined($jpegtran);
50    
51  rmtree $dump_dir if -e $dump_dir;  rmtree $dump_dir if -e $dump_dir;
52  mkpath $dump_dir || die "can't create $dump_dir: $!";  mkpath $dump_dir || die "can't create $dump_dir: $!";
53    
54    $| = 1;
55    
56  open(my $fh, '<', $path) || die "can't open $path: $!";  open(my $fh, '<', $path) || die "can't open $path: $!";
57    
58  # offset in file  # offset in file
# Line 121  sub x { Line 123  sub x {
123          }          }
124  }  }
125    
126    # my $len = next_part( 'boob' );
127    # my ( $len, $part ) = next_part();
128    
129  sub next_part {  sub next_part {
130          my ( $expected_part, $expected_len, $skip ) = @_;          my ( $expected_part, $expected_len, $skip ) = @_;
131          my ( $part, $len ) = x(8,'A4V');          my ( $part, $len ) = x(8,'A4V');
132          return unless $len;          return unless $len;
133          confess "not $expected_part but $part" if $expected_part ne $part;          confess "not $expected_part but $part" if $expected_part && $expected_part ne $part;
134          if ( $expected_len ) {          if ( $expected_len ) {
135                  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;
136          }          }
137          printf "## next_part %s - %d 0x%x bytes\n", $part, $len, $len if $debug;          printf "## next_part %s - %d 0x%x bytes\n", $part, $len, $len if $debug;
138          x($len) if $skip;          x($len) if $skip;
139            return ( $len, $part )  if wantarray;
140          return $len;          return $len;
141  }  }
142    
# Line 157  sub quality { Line 163  sub quality {
163          return $out;          return $out;
164  }  }
165    
 sub mp3_frame {  
         my $frame = join('',  
                 # Frame sync (all bits set)  
                 1 x 11 .  
                 # MPEG Audio version ID  
                 # 00 - MPEG Version 2.5 (unofficial)  
                 # 01 - reserved  
                 # 10 - MPEG Version 2 (ISO/IEC 13818-3)  
                 # 11 - MPEG Version 1 (ISO/IEC 11172-3)  
                 1,0,  
                 # Layer description  
                 # 00 - reserved  
                 # 01 - Layer III  
                 # 10 - Layer II  
                 # 11 - Layer I  
                 0,1,  
                 # Protection bit  
                 # 0 - Protected by CRC (16bit crc follows header)  
                 # 1 - Not protected  
                 0,  
                 # Bitrate index  
                 0,0,0,0,  
                 # Sampling rate frequency index (22050)  
                 0,0,  
                 # Padding bit  
                 # 0 - frame is not padded  
                 # 1 - frame is padded with one extra slot  
                 0,  
                 # Private bit  
                 0,  
                 # Channel Mode  
                 # 00 - Stereo  
                 # 01 - Joint stereo (Stereo)  
                 # 10 - Dual channel (2 mono channels)  
                 # 11 - Single channel (Mono)  
                 1,1,  
                 # Mode extension (Only if Joint stereo)  
                 0,0,  
                 # Copyright  
                 0,  
                 # Original  
                 0,  
                 # Emphasis  
                 # 00 - none  
                 # 01 - 50/15 ms  
                 # 10 - reserved  
                 # 11 - CCIT J.17  
                 0,0,  
         );  
   
         die "frame must have 32 bits, not ", length($frame), " for $frame" if length($frame) != 32;  
   
         my $bits = pack("b32", $frame);  
   
         die "packed bits must be 4 bytes, not $bits" if length($bits) != 4;  
   
         my $t = $frame;  
         $t =~ s/(.{8})/$1 /g;  
         warn "## mp3 frame frame = $t\n";  
   
         return $bits;  
 }  
   
166  my @subframes;  my @subframes;
167  my $frame_nr = 1;  my $frame_nr = 1;
168    
# Line 456  sub adpcm_decode_sample { Line 399  sub adpcm_decode_sample {
399          return $pred_val;          return $pred_val;
400  }  }
401    
402  open(my $au_fh, '>', 'out.au') || die "can't open out.au: $!";  my $au_path = "$dump_dir/sound.au";
403    open(my $au_fh, '>', $au_path) || die "can't open $au_path: $!";
404  print $au_fh pack 'a4N5', (  print $au_fh pack 'a4N5', (
405          # magic          # magic
406          '.snd',          '.snd',
# Line 477  sub audio_frame { Line 421  sub audio_frame {
421    
422          my ( $origin, $index, $bytes ) = unpack 'ssL', substr($data,0,8);          my ( $origin, $index, $bytes ) = unpack 'ssL', substr($data,0,8);
423    
 warn "audio_frame origin $origin index $index bytes $bytes\n";  
 hex_dump( substr($data,0,8) );  
   
424          $pred_val = $origin;          $pred_val = $origin;
425          $step_idx = $index;          $step_idx = $index;
426    
427            my $size = 0;
428    
429          foreach my $b ( map { ord($_) } split(//, substr($data,8)) ) {          foreach my $b ( map { ord($_) } split(//, substr($data,8)) ) {
430                  print $au_fh pack 'n', adpcm_decode_sample( $b >> 4 );                            print $au_fh pack 'n', adpcm_decode_sample( $b >> 4 );          
431                  print $au_fh pack 'n', adpcm_decode_sample( $b & 15 );                            print $au_fh pack 'n', adpcm_decode_sample( $b & 15 );          
432                    $size += 2;
433          }          }
 }  
   
   
 sub x_audio_frame {  
         my $data = shift || die "no data?";  
   
         my $apath = sprintf("$dump_dir/%04d.wav", $frame_nr );  
         open(my $audio_fh, '>', $apath) || die "can't open audio file $apath: $!";  
   
         print $audio_fh pack 'a4Va4a4VvvVVv4', (  
                 # header 'RIFF', size  
                 'RIFF',-1,  
                 # type: 'WAVE'  
                 'WAVE',  
                 'fmt ',0x14,  
                 # format: DVI (IMA) ADPCM Wave Type  
                 0x11,  
                 # channels  
                 1,  
                 # samples/sec  
                 22050,  
                 # avg. bytes/sec (for esimation)  
                 11567,  
                 # block align (size of block)  
                 0x800,  
                 # bits per sample (mono data)  
                 4,  
                 # cbSize (ADPCM with 7 soefficient pairs)  
                 2,  
                 # nSamplesPerBlock  
                 # (((nBlockAlign - (7 * nChannels)) * 8) / (wBitsPerSample * nChannels)) + 2  
                 0x03f9,  
         );  
   
         print $audio_fh pack 'a4VVa4V', (  
                 # time length of the data in samples  
                 'fact',4,  
                 220500,  
                 #  
                 'data',-1,  
         );  
434    
435          my $riff_header_len = tell($audio_fh);          warn "length isn't corrent $bytes != $size" if $bytes != $size;
   
         print $audio_fh $data;  
   
         my $size = tell($audio_fh);  
         warn "## wav file $apath size: $size\n";  
   
         seek( $audio_fh, 4, 0 );  
         print $audio_fh pack("V", $size - 8);  
         seek( $audio_fh, $riff_header_len - 4, 0 );  
         print $audio_fh pack("V", $size - $riff_header_len);  
   
         close($audio_fh) || die "can't close audio file $apath: $!";  
436  }  }
437    
438  #  #
# Line 552  my ( $riff, $amv ) = x(12, 'Z4x4Z4'); Line 443  my ( $riff, $amv ) = x(12, 'Z4x4Z4');
443  die "$path not RIFF but $riff" if $riff ne 'RIFF';  die "$path not RIFF but $riff" if $riff ne 'RIFF';
444  die "$path not AMV but $amv" if $amv ne 'AMV ';  die "$path not AMV but $amv" if $amv ne 'AMV ';
445    
446    my $fps = 16;
447    my $duration;
448    
449  while ( ! defined($d->{eof}) ) {  while ( ! defined($d->{eof}) ) {
450          my ( $list, $name ) = x(12,'A4x4A4');          my ( $list, $name ) = x(12,'A4x4A4');
451          die "not LIST but $list" if $list ne 'LIST';          die "not LIST but $list" if $list ne 'LIST';
# Line 569  while ( ! defined($d->{eof}) ) { Line 463  while ( ! defined($d->{eof}) ) {
463                          $h->{$n} = $v;                          $h->{$n} = $v;
464                  } x($len, 'Vx28VVVx8CCv');                  } x($len, 'Vx28VVVx8CCv');
465    
466                  printf "## %s %d*%d %s fps (%d ms/frame) %02d:%02d:%02d\n",                  $duration = sprintf('%02d:%02d:%02d', $h->{hh}, $h->{mm}, $h->{ss} );
467    
468                    printf "## %s %d*%d %s fps (%d ms/frame) %s\n",
469                          $path,                          $path,
470                          $h->{width}, $h->{height}, $h->{fps}, $h->{ms_per_frame},                          $h->{width}, $h->{height}, $h->{fps}, $h->{ms_per_frame},
471                          $h->{hh}, $h->{mm}, $h->{ss};                          $duration;
472    
473                  $d->{amvh} = $h;                  $d->{amvh} = $h;
474                    $fps = $h->{fps};
475    
476          } elsif ( $name eq 'strl' ) {          } elsif ( $name eq 'strl' ) {
477    
# Line 583  while ( ! defined($d->{eof}) ) { Line 480  while ( ! defined($d->{eof}) ) {
480    
481          } elsif ( $name eq 'movi' ) {          } elsif ( $name eq 'movi' ) {
482    
483                  while (1) {                  my $have_parts = 1;
484    
485                    while ( $have_parts ) {
486                          my $frame = $d->{movi}++;                          my $frame = $d->{movi}++;
                   
                         my $len = next_part( '00dc' );  
                         last unless $len;  
                         printf "<< %s 00dc - part %d jpeg %d 0x%x bytes\n", $name, $frame, $len, $len if $verbose;  
                         mkjpg( x($len) );  
   
                         $len = next_part( '01wb' );  
                         printf "<< %s 01wb - part %d audio %d 0x%x bytes\n", $name, $frame, $len, $len if $verbose;  
   
                         my $audio_frame = x( $len );  
   
                         if ( $dump_audio ) {  
                                 printf "#### dumping audio frame %d 0x%x bytes\n", length($audio_frame), length($audio_frame);  
                                 hex_dump( $audio_frame );  
                         }  
487    
488                          # remove 8 bytes of something                          my $parts = 0;
 #                       $audio_frame = substr( $audio_frame, 8 );  
489    
490                          if ( length($audio_frame) % 2 == 0 ) {                          while ( $parts < 2 ) {
491                                  print "#### even sized frame!";  
492  #                               $audio_frame = substr( $audio_frame, 0, -1 );                                  my ( $len, $part ) = next_part();
493                          }  
494                                    if ( ! $len ) {
495                                            $have_parts = 0;
496                                            last;
497                                    }
498    
499  #                       print $audio_fh mp3_frame;                                  if ( $part eq '00dc' ) {
500                          audio_frame( $audio_frame );  
501                                            printf "<< %s 00dc - part %d jpeg %d 0x%x bytes\n", $name, $frame, $len, $len if $verbose;
502                                            mkjpg( x($len) );
503                                            $parts++;
504    
505                                    } elsif ( $part eq '01wb' ) {
506                                            printf "<< %s 01wb - part %d audio %d 0x%x bytes\n", $name, $frame, $len, $len if $verbose;
507    
508                                            my $audio_frame = x( $len );
509    
510                                            if ( $dump_audio ) {
511                                                    printf "#### dumping audio frame %d 0x%x bytes\n", length($audio_frame), length($audio_frame);
512                                                    hex_dump( $audio_frame );
513                                            }
514    
515                    #                       print $audio_fh mp3_frame;
516                                            audio_frame( $audio_frame );
517    
518                                            $parts++;
519                                    } else {
520                                            warn "unknown next part $part with $len bytes, skipping!";
521                                    }
522    
523                                    warn "## #$frame_nr $name $part has $parts parts\n" if $debug;
524                            }
525    
526                          $frame_nr++;                          $frame_nr++;
527    
528                            if ( $frame_nr % $fps == 0 ) {
529                                    print "\n" if ( ( $frame_nr / $fps ) % 60 == 0 );
530                                    print ".";
531                            }
532                  };                  };
533    
534          } else {          } else {
# Line 620  while ( ! defined($d->{eof}) ) { Line 536  while ( ! defined($d->{eof}) ) {
536          }          }
537  }  }
538    
539  my $cmd = "ffmpeg -i $dump_dir/%04d.jpg -r 16 -y $dump_avi";  my $cmd = "ffmpeg -r $fps -i $dump_dir/%04d.jpg -i $au_path -y $dump_avi";
540  system($cmd) == 0 || die "can't convert frames to avi using $cmd: $!";  system($cmd) == 0 || die "can't convert frames to avi using $cmd: $!";
541    
542  print ">>>> created $frame_nr frames $dump_avi ", -s $dump_avi, "\n";  print ">>>> created $frame_nr frames $dump_avi ", -s $dump_avi, "\n";

Legend:
Removed from v.28  
changed lines
  Added in v.33

  ViewVC Help
Powered by ViewVC 1.1.26