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

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

  ViewVC Help
Powered by ViewVC 1.1.26