/[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 8 by dpavlin, Fri Jul 20 11:13:55 2007 UTC revision 21 by dpavlin, Sat Jul 21 15:17:48 2007 UTC
# Line 15  use strict; Line 15  use strict;
15  use Data::Dump qw/dump/;  use Data::Dump qw/dump/;
16  use Carp qw/confess/;  use Carp qw/confess/;
17  use File::Path;  use File::Path;
18    use Getopt::Long;
19    
20  my $dump = 0;  my $dump = 0;
21  my $debug = 0;  my $debug = 0;
22    my $dump_dir = '/tmp/dump/';
23    my $dump_avi = "dump.avi";
24    my $no_jpeg_header = 0;
25    my $jpeg_q = 100;
26    
27    GetOptions(
28            "dump!"                 => \$dump,
29            "debug!"                => \$debug,
30            "dump-dir=s"    => \$dump_dir,
31            "no-jpeg-headers!" => \$no_jpeg_header,
32    );
33    
34  my $path = shift @ARGV || die "usage: $0 movie.amv\n";  my $path = shift @ARGV || die "usage: $0 movie.amv\n";
35    
36  my $dump_dir = '/tmp/dump/';  
37  if ( ! -e $dump_dir ) {  rmtree $dump_dir if -e $dump_dir;
38          mkpath $dump_dir || die "can't create $dump_dir: $!";  mkpath $dump_dir || die "can't create $dump_dir: $!";
 }  
39    
40  open(my $fh, '<', $path) || die "can't open $path: $!";  open(my $fh, '<', $path) || die "can't open $path: $!";
41    
# Line 81  sub x { Line 92  sub x {
92          hex_dump( $bytes );          hex_dump( $bytes );
93    
94          if ( $bytes eq 'AMV_END_' ) {          if ( $bytes eq 'AMV_END_' ) {
95                  warn "> end of file marker AMV_END_\n";                  print "> end of file marker AMV_END_\n" if $dump;
96                  $d->{eof}++;                  $d->{eof}++;
97                  return;                  return;
98          }          }
99    
100          if ( $format ) {          if ( $format ) {
101                  my @data = unpack($format, $bytes);                  my @data = unpack($format, $bytes);
102                  warn "## unpacked = ",dump(@data),"\n" if $debug;                  print "## unpacked = ",dump(@data),"\n" if $debug;
103                  return @data;                  return @data;
104          } else {          } else {
105                  return $bytes;                  return $bytes;
# Line 108  sub next_part { Line 119  sub next_part {
119          return $len;          return $len;
120  }  }
121    
122  sub huffman {  sub quality {
123            my @table = @_;
124            die "quantization matrice needs to have 64 bytes!" if $#table != 63;
125    
126            my $in = join('', map { chr($_) } @table );
127            my $out;
128    
129            foreach my $t ( @table ) {
130                    $t = int( ( $t * $jpeg_q ) / 100 );
131                    $t = 255 if $t > 255;
132                    $out .= chr($t);
133            }
134    
135  # JPEG DHT Segment for YCrCb omitted from MJPG data          if ( $dump ) {
136  return                  print "## quantization table original\n";
137  "\xFF\xC4\x01\xA2" .                  hex_dump( $in );
138  "\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00" .                  print "## quantization table for $jpeg_q %\n";
139  "\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x01" .                  hex_dump( $out );
140  "\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00" .          }
 "\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x10\x00" .  
 "\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01\x7D" .  
 "\x01\x02\x03\x00\x04\x11\x05\x12\x21\x31\x41\x06\x13\x51\x61" .  
 "\x07\x22\x71\x14\x32\x81\x91\xA1\x08\x23\x42\xB1\xC1\x15\x52" .  
 "\xD1\xF0\x24\x33\x62\x72\x82\x09\x0A\x16\x17\x18\x19\x1A\x25" .  
 "\x26\x27\x28\x29\x2A\x34\x35\x36\x37\x38\x39\x3A\x43\x44\x45" .  
 "\x46\x47\x48\x49\x4A\x53\x54\x55\x56\x57\x58\x59\x5A\x63\x64" .  
 "\x65\x66\x67\x68\x69\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x83" .  
 "\x84\x85\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96\x97\x98\x99" .  
 "\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xB2\xB3\xB4\xB5\xB6" .  
 "\xB7\xB8\xB9\xBA\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2\xD3" .  
 "\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8" .  
 "\xE9\xEA\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\x11\x00\x02" .  
 "\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04\x00\x01\x02\x77\x00" .  
 "\x01\x02\x03\x11\x04\x05\x21\x31\x06\x12\x41\x51\x07\x61\x71" .  
 "\x13\x22\x32\x81\x08\x14\x42\x91\xA1\xB1\xC1\x09\x23\x33\x52" .  
 "\xF0\x15\x62\x72\xD1\x0A\x16\x24\x34\xE1\x25\xF1\x17\x18\x19" .  
 "\x1A\x26\x27\x28\x29\x2A\x35\x36\x37\x38\x39\x3A\x43\x44\x45" .  
 "\x46\x47\x48\x49\x4A\x53\x54\x55\x56\x57\x58\x59\x5A\x63\x64" .  
 "\x65\x66\x67\x68\x69\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x82" .  
 "\x83\x84\x85\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96\x97\x98" .  
 "\x99\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xB2\xB3\xB4\xB5" .  
 "\xB6\xB7\xB8\xB9\xBA\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2" .  
 "\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xE2\xE3\xE4\xE5\xE6\xE7\xE8" .  
 "\xE9\xEA\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA";  
141    
142            return $out;
143  }  }
144    
145    my @subframes;
146    my $frame_nr = 1;
147    
148    # how many subframes to join into single frame?
149    my $join_subframes = 0;
150    
151  sub mkjpg {  sub mkjpg {
152          my ($path,$data) = @_;          my ($data) = @_;
         open(my $fh, '>', $path) || die "can't create $path: $!";  
153    
154          confess "no SOI marker in data" if substr($data,0,2) ne "\xFF\xD8";          confess "no SOI marker in data" if substr($data,0,2) ne "\xFF\xD8";
155          $data = substr($data,2);          confess "no EOI marker in data" if substr($data,-2,2) ne "\xFF\xD9";
156            $data = substr($data,2,-2);
157    
158            if ( $#subframes < ( $join_subframes - 1 ) ) {
159                    push @subframes, $data;
160                    print "## saved $frame_nr/", $#subframes + 1, " subframe of ", length($data), " bytes\n";
161                    return;
162            }
163    
164            my $path = sprintf("$dump_dir/%04d.jpg", $frame_nr++ );
165    
166            open(my $fh, '>', $path) || die "can't create $path: $!";
167    
168            my $w = $d->{amvh}->{width} || die "no width?";
169            my $h = $d->{amvh}->{height} || confess "no height?";
170    
171          my $header =          my $header =
172                  "\xFF\xD8".     # Start of Image (SOI) marker          # Start of Image (SOI) marker
173  #------------------------------------------------------------------          "\xFF\xD8".
174                  "\xFF\xE0".     # JFIF marker          # JFIF marker
175            "\xFF\xE0".
176          pack("nZ5CCCnnCC",          pack("nZ5CCCnnCC",
177                  16,                     # length                  16,                     # length
178                  'JFIF',         # identifier                  'JFIF',         # identifier (JFIF)
179                  1,1,            # version                  1,1,            # version
180                  0,                      # units (none)                  0,                      # units (none)
181                  1,1,            # X,Y density                  1,1,            # X,Y density
182                  0,0,            # X,Y thumbnail                  0,0,            # X,Y thumbnail
183          ).          ).
184  #------------------------------------------------------------------          "\xFF\xFE".
185                  "\xFF\xDB".     # Define Quantization table marker          "\x00\x3CCREATOR: amv dumper (compat. IJG JPEG v62), quality = 100\n".
186                  "\x00\x43".     # len          # quantization table (quaility=100%)
187                  "\x00".         # the precision and the quantization table index          "\xFF\xDB".
188                  "\x00" x 64 .          "\x00\x43".
189  #------------------------------------------------------------------          # 8 bit values, table 1
190                  "\xFF\xC0".     # Start of frame          "\x00".
191            quality(
192        0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E,
193        0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
194        0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
195        0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33,
196        0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44,
197        0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57,
198        0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71,
199        0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63,
200            ).
201            "\xFF\xDB".
202            "\x00\x43".
203            # 8 bit values, table 1
204            "\x01".
205            quality(
206        0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2F, 0x1A,
207        0x1A, 0x2F, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
208        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
209        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
210        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
211        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
212        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
213        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
214            ).
215            # start of frame
216            "\xFF\xC0".
217          pack("ncnncc9",          pack("ncnncc9",
218                  17,                     # len                  17,                     # len
219                  8,                      # sample precision in bits                  8,                      # sample precision in bits
220                  120,160,        # X,Y size                  $h,$w,          # X,Y size
221                  3,                      # number of components                  3,                      # number of components
222                  1,0x22,0,       # Component ID, H+V sampling factors, Quantization table number                  1,0x22,0,       # Component ID, H+V sampling factors, Quantization table number
223                  2,0x11,0,                  2,0x11,1,
224                  3,0x11,0,                  3,0x11,1,
225          ).          ).
226  #------------------------------------------------------------------          # Define huffman table (section B.2.4.1)
227  #       huffman("\x00").        # 0 DC          "\xFF\xC4".     # Marker
228          huffman("\x01").        # 1 DC          "\x00\x1F".     # Length (31 bytes)
229  #       huffman("\x10").        # 0 AC          "\x00".         # DC luminance, table 0
230  #       huffman("\x11").        # 1 AC          "\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00".
231  #------------------------------------------------------------------          "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B".
232                  "\xFF\xDA".     # Start of Scan marker          # Define huffman table (section B.2.4.1)
233          pack("nC11",          "\xFF\xC4".     # Marker
234            "\x00\xB5".     # Length (181 bytes)
235            "\x10".         # AC luminance, table 0
236            "\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01\x7D".
237            "\x01\x02\x03\x00\x04\x11\x05\x12".
238            "\x21\x31\x41\x06\x13\x51\x61\x07\x22\x71\x14\x32".
239            "\x81\x91\xA1\x08\x23\x42\xB1\xC1\x15\x52\xD1\xF0".
240            "\x24\x33\x62\x72\x82\x09\x0A\x16\x17\x18\x19\x1A".
241            "\x25\x26\x27\x28\x29\x2A\x34\x35\x36\x37\x38\x39".
242            "\x3A\x43\x44\x45\x46\x47\x48\x49\x4A\x53\x54\x55".
243            "\x56\x57\x58\x59\x5A\x63\x64\x65\x66\x67\x68\x69".
244            "\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x83\x84\x85".
245            "\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96\x97\x98".
246            "\x99\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xB2".
247            "\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xC2\xC3\xC4\xC5".
248            "\xC6\xC7\xC8\xC9\xCA\xD2\xD3\xD4\xD5\xD6\xD7\xD8".
249            "\xD9\xDA\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA".
250            "\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA".
251            # Define huffman table (section B.2.4.1)
252            "\xFF\xC4".     # Marker
253            "\x00\x1F".     # Length (31 bytes)
254            "\x01".         # DC chrominance, table 1
255            "\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00".
256            "\x00\x00\x00\x00".
257            "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B".
258            #/* Define huffman table (section B.2.4.1) */
259            "\xFF\xC4".     # Marker
260            "\x00\xB5".     # Length (181 bytes)
261            "\x11".         # AC chrominance, table 1
262            "\x00\x02\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04".
263            "\x00\x01\x02\x77".
264            "\x00\x01\x02\x03\x11\x04\x05\x21".
265            "\x31\x06\x12\x41\x51\x07\x61\x71\x13\x22\x32\x81".
266            "\x08\x14\x42\x91\xA1\xB1\xC1\x09\x23\x33\x52\xF0".
267            "\x15\x62\x72\xD1\x0A\x16\x24\x34\xE1\x25\xF1\x17".
268            "\x18\x19\x1A\x26\x27\x28\x29\x2A\x35\x36\x37\x38".
269            "\x39\x3A\x43\x44\x45\x46\x47\x48\x49\x4A\x53\x54".
270            "\x55\x56\x57\x58\x59\x5A\x63\x64\x65\x66\x67\x68".
271            "\x69\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x82\x83".
272            "\x84\x85\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96".
273            "\x97\x98\x99\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9".
274            "\xAA\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xC2\xC3".
275            "\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2\xD3\xD4\xD5\xD6".
276            "\xD7\xD8\xD9\xDA\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9".
277            "\xEA\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA".
278            # Start of Scan marker
279            "\xFF\xDA".
280            pack("nC10",
281                  12,                     # length                  12,                     # length
282                  3,                      # number of components                  3,                      # number of components
283                  1,0,            # components DC+AC table numbers                  1,0x00,         # Scan 1: use DC/AC huff tables 0/0
284                  2,17,                  2,0x11,         # Scan 2: use DC/AC huff tables 1/1
285                  3,17,                  3,0x11,         # Scan 3: use DC/AC huff tables 1/1
286                  0,63,           # Ss, Se                  0,0x3f,         # Ss, Se
287                  0,165,          # Ah, Ai                  0,                      # Ah, Ai (not used)
288          );          );
 #------------------------------------------------------------------  
289    
290            if ( $dump ) {
291                    print "## created JPEG header...\n";
292                    hex_dump( $header, 0 );
293            }
294    
295          warn "## created JPEG header...", dump( $header );          my $frame = join('', @subframes ) . $data;
296          hex_dump( $header, 0 );          @subframes = ();
297    
298          print $fh $header . $data || die "can't write frame into $path: $!";          if ( ! $no_jpeg_header ) {
299                    print $fh $header, $frame, "\xFF\xD9" || die "can't write jpeg $path: $!";
300            } else {
301                    print $fh $frame || die "can't write raw jpeg $path: $!";
302            }
303          close $fh || die "can't close $path: $!";          close $fh || die "can't close $path: $!";
304          print ">> created $path ", -s $path, " bytes\n";          print ">> created $frame_nr ", $no_jpeg_header ? 'raw' : '', " jpeg $path ", -s $path, " bytes\n";
305  }  }
306    
307  my ( $riff, $amv ) = x(12, 'Z4x4Z4');  my ( $riff, $amv ) = x(12, 'Z4x4Z4');
# Line 247  while ( ! defined($d->{eof}) ) { Line 345  while ( ! defined($d->{eof}) ) {
345                          my $len = next_part( '00dc' );                          my $len = next_part( '00dc' );
346                          last unless $len;                          last unless $len;
347                          printf "<< %s 00dc - frame %d jpeg %d 0x%x bytes\n", $name, $frame, $len, $len;                          printf "<< %s 00dc - frame %d jpeg %d 0x%x bytes\n", $name, $frame, $len, $len;
348                          mkjpg( sprintf("$dump_dir/%03d.jpg", $frame ), x($len) );                          mkjpg( x($len) );
349    
350                          $len = next_part( '01wb', 0, 1 );                          $len = next_part( '01wb', 0, 1 );
351                          printf "<< %s 01wb - frame %d audio %d 0x%x bytes\n", $name, $frame, $len, $len;                          printf "<< %s 01wb - frame %d audio %d 0x%x bytes\n", $name, $frame, $len, $len;
# Line 257  while ( ! defined($d->{eof}) ) { Line 355  while ( ! defined($d->{eof}) ) {
355                  die "unknown $list $name";                  die "unknown $list $name";
356          }          }
357  }  }
358    
359    my $cmd = "ffmpeg -i $dump_dir/%04d.jpg -r 16 -f $dump_avi";
360    system($cmd) == 0 || die "can't convert frames to avi using $cmd: $!";
361    

Legend:
Removed from v.8  
changed lines
  Added in v.21

  ViewVC Help
Powered by ViewVC 1.1.26