/[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

Annotation of /amv.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (hide annotations)
Sun Aug 19 11:45:39 2007 UTC (11 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 15739 byte(s)
unpack audio into .au file
1 dpavlin 3 #!/usr/bin/perl -w
2    
3     # amv.pl
4     #
5     # 07/19/07 19:21:39 CEST Dobrica Pavlinusic <dpavlin@rot13.org>
6 dpavlin 7 #
7     # Various useful links used to produce this:
8     # http://www.moviecodec.com/topics/15431p1.html
9     # http://en.wikipedia.org/wiki/RIFF_(File_format)
10 dpavlin 8 # http://www.obrador.com/essentialjpeg/HeaderInfo.htm
11     # http://lists.helixcommunity.org/pipermail/datatype-dev/2005-January/001886.html
12 dpavlin 24 # http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm
13 dpavlin 27 # http://wiki.multimedia.cx/index.php?title=IMA_ADPCM
14 dpavlin 3
15     use strict;
16    
17     use Data::Dump qw/dump/;
18     use Carp qw/confess/;
19 dpavlin 8 use File::Path;
20 dpavlin 15 use Getopt::Long;
21 dpavlin 3
22 dpavlin 25 my $dump_amv = 0;
23     my $dump_video = 0;
24     my $dump_jpeg = 0;
25     my $dump_audio = 0;
26 dpavlin 8 my $debug = 0;
27 dpavlin 24 my $verbose = 0;
28 dpavlin 15 my $dump_dir = '/tmp/dump/';
29 dpavlin 20 my $dump_avi = "dump.avi";
30 dpavlin 19 my $no_jpeg_header = 0;
31     my $jpeg_q = 100;
32 dpavlin 24 my $jpegtran;
33 dpavlin 8
34 dpavlin 15 GetOptions(
35 dpavlin 25 "dump-amv!" => \$dump_amv,
36     "dump-video!" => \$dump_video,
37     "dump-jpeg!" => \$dump_jpeg,
38     "dump-audio!" => \$dump_audio,
39 dpavlin 15 "debug!" => \$debug,
40     "dump-dir=s" => \$dump_dir,
41 dpavlin 19 "no-jpeg-headers!" => \$no_jpeg_header,
42 dpavlin 24 "jpegtran=s" => \$jpegtran,
43     "verbose!" => \$verbose,
44 dpavlin 15 );
45    
46 dpavlin 3 my $path = shift @ARGV || die "usage: $0 movie.amv\n";
47    
48 dpavlin 24 # by default, flip frames
49     #$jpegtran = '-flip vertical' unless defined($jpegtran);
50 dpavlin 15
51 dpavlin 11 rmtree $dump_dir if -e $dump_dir;
52     mkpath $dump_dir || die "can't create $dump_dir: $!";
53 dpavlin 8
54 dpavlin 3 open(my $fh, '<', $path) || die "can't open $path: $!";
55    
56 dpavlin 4 # offset in file
57     my $o = 0;
58    
59     # shared data hash
60     my $d;
61    
62 dpavlin 3 sub hex_dump {
63 dpavlin 8 my ( $bytes, $offset ) = @_;
64     return unless $bytes;
65    
66     my $old_o;
67     if (defined($offset)) {
68     $old_o = $o;
69     $o = $offset;
70     }
71    
72 dpavlin 3 my $ascii = $bytes;
73     $ascii =~ s/\W/./gs;
74 dpavlin 8 my $hex = uc( unpack('h*', $bytes) );
75 dpavlin 3 $hex =~ s/(..)/$1 /g;
76     # calculate number of characters for offset
77 dpavlin 4 #my $d = length( sprintf("%x",length($bytes)) );
78     my $d = 4;
79 dpavlin 6 my $prefix = '#.';
80 dpavlin 3 while ( $hex =~ s/^((?:\w\w\s){1,16})// ) {
81 dpavlin 6 printf "$prefix %0${d}x | %-48s| %s\n", $o, $1, substr( $ascii, 0, 16 );
82     $prefix = '##';
83 dpavlin 3 if ( length($ascii) >= 16 ) {
84     $ascii = substr( $ascii, 16 );
85 dpavlin 4 $o += 16;
86 dpavlin 3 } else {
87 dpavlin 4 $o += length($ascii);
88 dpavlin 3 last;
89     }
90     }
91 dpavlin 8
92     $o = $old_o if $old_o;
93 dpavlin 3 }
94    
95     sub x {
96     my ($len,$format) = @_;
97    
98     my $bytes;
99     read($fh, $bytes, $len);
100    
101     my $r_len = length($bytes);
102     confess "read $r_len bytes, expected $len" if $len != $r_len;
103    
104 dpavlin 25 if ( $dump_amv ) {
105     print "## raw $len bytes\n";
106     hex_dump( $bytes );
107     }
108 dpavlin 3
109 dpavlin 4 if ( $bytes eq 'AMV_END_' ) {
110 dpavlin 25 print "> end of file marker AMV_END_\n" if $dump_video;
111 dpavlin 4 $d->{eof}++;
112     return;
113     }
114    
115 dpavlin 3 if ( $format ) {
116     my @data = unpack($format, $bytes);
117 dpavlin 19 print "## unpacked = ",dump(@data),"\n" if $debug;
118 dpavlin 3 return @data;
119     } else {
120     return $bytes;
121     }
122     }
123    
124     sub next_part {
125     my ( $expected_part, $expected_len, $skip ) = @_;
126     my ( $part, $len ) = x(8,'A4V');
127 dpavlin 4 return unless $len;
128 dpavlin 3 confess "not $expected_part but $part" if $expected_part ne $part;
129     if ( $expected_len ) {
130     confess "expected $expected_len bytes for $part got $len" if $len != $expected_len;
131     }
132 dpavlin 24 printf "## next_part %s - %d 0x%x bytes\n", $part, $len, $len if $debug;
133 dpavlin 3 x($len) if $skip;
134     return $len;
135     }
136    
137 dpavlin 19 sub quality {
138     my @table = @_;
139     die "quantization matrice needs to have 64 bytes!" if $#table != 63;
140 dpavlin 3
141 dpavlin 19 my $in = join('', map { chr($_) } @table );
142     my $out;
143 dpavlin 8
144 dpavlin 19 foreach my $t ( @table ) {
145     $t = int( ( $t * $jpeg_q ) / 100 );
146     $t = 255 if $t > 255;
147     $out .= chr($t);
148     }
149    
150 dpavlin 25 if ( $dump_video ) {
151 dpavlin 19 print "## quantization table original\n";
152     hex_dump( $in );
153     print "## quantization table for $jpeg_q %\n";
154     hex_dump( $out );
155     }
156    
157     return $out;
158 dpavlin 8 }
159    
160 dpavlin 24 sub mp3_frame {
161     my $frame = join('',
162     # Frame sync (all bits set)
163     1 x 11 .
164     # MPEG Audio version ID
165     # 00 - MPEG Version 2.5 (unofficial)
166     # 01 - reserved
167     # 10 - MPEG Version 2 (ISO/IEC 13818-3)
168     # 11 - MPEG Version 1 (ISO/IEC 11172-3)
169     1,0,
170     # Layer description
171     # 00 - reserved
172     # 01 - Layer III
173     # 10 - Layer II
174     # 11 - Layer I
175     0,1,
176     # Protection bit
177     # 0 - Protected by CRC (16bit crc follows header)
178     # 1 - Not protected
179     0,
180     # Bitrate index
181     0,0,0,0,
182     # Sampling rate frequency index (22050)
183     0,0,
184     # Padding bit
185     # 0 - frame is not padded
186     # 1 - frame is padded with one extra slot
187     0,
188     # Private bit
189     0,
190     # Channel Mode
191     # 00 - Stereo
192     # 01 - Joint stereo (Stereo)
193     # 10 - Dual channel (2 mono channels)
194     # 11 - Single channel (Mono)
195     1,1,
196     # Mode extension (Only if Joint stereo)
197     0,0,
198     # Copyright
199     0,
200     # Original
201     0,
202     # Emphasis
203     # 00 - none
204     # 01 - 50/15 ms
205     # 10 - reserved
206     # 11 - CCIT J.17
207     0,0,
208     );
209    
210     die "frame must have 32 bits, not ", length($frame), " for $frame" if length($frame) != 32;
211    
212     my $bits = pack("b32", $frame);
213    
214     die "packed bits must be 4 bytes, not $bits" if length($bits) != 4;
215    
216     my $t = $frame;
217     $t =~ s/(.{8})/$1 /g;
218     warn "## mp3 frame frame = $t\n";
219    
220     return $bits;
221     }
222    
223 dpavlin 19 my @subframes;
224     my $frame_nr = 1;
225    
226     # how many subframes to join into single frame?
227     my $join_subframes = 0;
228    
229 dpavlin 8 sub mkjpg {
230 dpavlin 19 my ($data) = @_;
231 dpavlin 8
232     confess "no SOI marker in data" if substr($data,0,2) ne "\xFF\xD8";
233 dpavlin 19 confess "no EOI marker in data" if substr($data,-2,2) ne "\xFF\xD9";
234     $data = substr($data,2,-2);
235 dpavlin 8
236 dpavlin 19 if ( $#subframes < ( $join_subframes - 1 ) ) {
237     push @subframes, $data;
238 dpavlin 24 print "## saved $frame_nr/", $#subframes + 1, " subframe of ", length($data), " bytes\n" if $debug;
239 dpavlin 19 return;
240     }
241    
242 dpavlin 16 my $w = $d->{amvh}->{width} || die "no width?";
243     my $h = $d->{amvh}->{height} || confess "no height?";
244    
245 dpavlin 8 my $header =
246 dpavlin 19 # Start of Image (SOI) marker
247     "\xFF\xD8".
248     # JFIF marker
249     "\xFF\xE0".
250 dpavlin 8 pack("nZ5CCCnnCC",
251     16, # length
252 dpavlin 19 'JFIF', # identifier (JFIF)
253 dpavlin 8 1,1, # version
254     0, # units (none)
255     1,1, # X,Y density
256     0,0, # X,Y thumbnail
257     ).
258 dpavlin 19 "\xFF\xFE".
259     "\x00\x3CCREATOR: amv dumper (compat. IJG JPEG v62), quality = 100\n".
260     # quantization table (quaility=100%)
261     "\xFF\xDB".
262     "\x00\x43".
263     # 8 bit values, table 1
264     "\x00".
265     quality(
266     0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E,
267     0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
268     0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
269     0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33,
270     0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44,
271     0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57,
272     0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71,
273     0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63,
274     ).
275     "\xFF\xDB".
276     "\x00\x43".
277     # 8 bit values, table 1
278     "\x01".
279     quality(
280     0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2F, 0x1A,
281     0x1A, 0x2F, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
282     0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
283     0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
284     0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
285     0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
286     0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
287     0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
288     ).
289     # start of frame
290     "\xFF\xC0".
291 dpavlin 8 pack("ncnncc9",
292     17, # len
293     8, # sample precision in bits
294 dpavlin 16 $h,$w, # X,Y size
295 dpavlin 8 3, # number of components
296 dpavlin 19 1,0x22,0, # Component ID, H+V sampling factors, Quantization table number
297 dpavlin 11 2,0x11,1,
298     3,0x11,1,
299 dpavlin 8 ).
300 dpavlin 11 # Define huffman table (section B.2.4.1)
301 dpavlin 13 "\xFF\xC4". # Marker
302     "\x00\x1F". # Length (31 bytes)
303 dpavlin 14 "\x00". # DC luminance, table 0
304     "\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00".
305     "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B".
306 dpavlin 13 # Define huffman table (section B.2.4.1)
307     "\xFF\xC4". # Marker
308     "\x00\xB5". # Length (181 bytes)
309 dpavlin 14 "\x10". # AC luminance, table 0
310     "\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01\x7D".
311     "\x01\x02\x03\x00\x04\x11\x05\x12".
312 dpavlin 13 "\x21\x31\x41\x06\x13\x51\x61\x07\x22\x71\x14\x32".
313     "\x81\x91\xA1\x08\x23\x42\xB1\xC1\x15\x52\xD1\xF0".
314     "\x24\x33\x62\x72\x82\x09\x0A\x16\x17\x18\x19\x1A".
315     "\x25\x26\x27\x28\x29\x2A\x34\x35\x36\x37\x38\x39".
316     "\x3A\x43\x44\x45\x46\x47\x48\x49\x4A\x53\x54\x55".
317     "\x56\x57\x58\x59\x5A\x63\x64\x65\x66\x67\x68\x69".
318     "\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x83\x84\x85".
319     "\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96\x97\x98".
320     "\x99\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xB2".
321     "\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xC2\xC3\xC4\xC5".
322     "\xC6\xC7\xC8\xC9\xCA\xD2\xD3\xD4\xD5\xD6\xD7\xD8".
323     "\xD9\xDA\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA".
324     "\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA".
325 dpavlin 19 # Define huffman table (section B.2.4.1)
326     "\xFF\xC4". # Marker
327     "\x00\x1F". # Length (31 bytes)
328     "\x01". # DC chrominance, table 1
329     "\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00".
330     "\x00\x00\x00\x00".
331     "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B".
332 dpavlin 13 #/* Define huffman table (section B.2.4.1) */
333 dpavlin 14 "\xFF\xC4". # Marker
334     "\x00\xB5". # Length (181 bytes)
335     "\x11". # AC chrominance, table 1
336 dpavlin 13 "\x00\x02\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04".
337 dpavlin 14 "\x00\x01\x02\x77".
338     "\x00\x01\x02\x03\x11\x04\x05\x21".
339 dpavlin 13 "\x31\x06\x12\x41\x51\x07\x61\x71\x13\x22\x32\x81".
340     "\x08\x14\x42\x91\xA1\xB1\xC1\x09\x23\x33\x52\xF0".
341     "\x15\x62\x72\xD1\x0A\x16\x24\x34\xE1\x25\xF1\x17".
342     "\x18\x19\x1A\x26\x27\x28\x29\x2A\x35\x36\x37\x38".
343     "\x39\x3A\x43\x44\x45\x46\x47\x48\x49\x4A\x53\x54".
344     "\x55\x56\x57\x58\x59\x5A\x63\x64\x65\x66\x67\x68".
345     "\x69\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x82\x83".
346     "\x84\x85\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96".
347     "\x97\x98\x99\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9".
348     "\xAA\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xC2\xC3".
349     "\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2\xD3\xD4\xD5\xD6".
350     "\xD7\xD8\xD9\xDA\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9".
351     "\xEA\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA".
352 dpavlin 19 # Start of Scan marker
353     "\xFF\xDA".
354     pack("nC10",
355     12, # length
356     3, # number of components
357     1,0x00, # Scan 1: use DC/AC huff tables 0/0
358     2,0x11, # Scan 2: use DC/AC huff tables 1/1
359     3,0x11, # Scan 3: use DC/AC huff tables 1/1
360     0,0x3f, # Ss, Se
361     0, # Ah, Ai (not used)
362     );
363 dpavlin 8
364 dpavlin 25 if ( $dump_jpeg ) {
365 dpavlin 19 print "## created JPEG header...\n";
366 dpavlin 11 hex_dump( $header, 0 );
367     }
368 dpavlin 8
369 dpavlin 19 my $frame = join('', @subframes ) . $data;
370     @subframes = ();
371    
372 dpavlin 24 my $path = sprintf("$dump_dir/%04d.jpg", $frame_nr );
373 dpavlin 23
374     my $fh;
375     if ( $jpegtran ) {
376     open($fh, '|-', "jpegtran $jpegtran > $path") || die "can't create $path: $!";
377     } else {
378     open($fh, '>', $path) || die "can't create $path: $!";
379     }
380    
381 dpavlin 19 if ( ! $no_jpeg_header ) {
382 dpavlin 23 print $fh $header . $frame . "\xFF\xD9" || die "can't write jpeg $path: $!";
383 dpavlin 19 } else {
384     print $fh $frame || die "can't write raw jpeg $path: $!";
385     }
386 dpavlin 8 close $fh || die "can't close $path: $!";
387 dpavlin 24 print ">> created $frame_nr ", $no_jpeg_header ? 'raw' : '', " jpeg $path ", -s $path, " bytes\n" if $verbose;
388 dpavlin 8 }
389    
390 dpavlin 28 #
391     # IMA ADPCM decoder
392     #
393 dpavlin 8
394 dpavlin 28 my @index_adjust = ( -1, -1, -1, -1, 2, 4, 6, 8 );
395 dpavlin 24
396 dpavlin 28 my @step_size = (
397     7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
398     19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
399     50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
400     130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
401     337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
402     876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
403     2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
404     5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
405     15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
406 dpavlin 24 );
407    
408 dpavlin 28 my $pred_val = 0;
409     my $step_idx = 0;
410    
411     # This code is "borrowed" from the ALSA library
412     # http://www.alsa-project.org
413    
414     sub adpcm_decode_sample {
415     my $code = shift;
416    
417     my $pred_diff; # Predicted difference to next sample
418     my $step; # holds previous step_size value
419    
420     # Separate sign and magnitude
421     my $sign = $code & 0x8;
422     $code &= 0x7;
423    
424     # Computes pred_diff = (code + 0.5) * step / 4,
425     # but see comment in adpcm_coder.
426    
427     $step = $step_size[$step_idx] || die "no step_size[$step_idx]";
428    
429     # Compute difference and new predicted value
430     $pred_diff = $step >> 3;
431     my $i = 0x4;
432     while( $i ) {
433     if ($code & $i) {
434     $pred_diff += $step;
435     }
436     $i >>= 1;
437     $step >>= 1;
438     }
439     $pred_val += $sign ? -$pred_diff : $pred_diff;
440    
441     # Clamp output value
442     if ($pred_val > 32767) {
443     $pred_val = 32767;
444     } elsif ($pred_val < -32768) {
445     $pred_val = -32768;
446     }
447    
448     # Find new step_size index value
449     $step_idx += $index_adjust[$code];
450    
451     if ($step_idx < 0) {
452     $step_idx = 0;
453     } elsif ($step_idx > 88) {
454     $step_idx = 88;
455     }
456     return $pred_val;
457     }
458    
459     open(my $au_fh, '>', 'out.au') || die "can't open out.au: $!";
460     print $au_fh pack 'a4N5', (
461     # magic
462     '.snd',
463     # data offset
464     24,
465     # data size
466     -1,
467     # encoding - 16-bit linear PCM
468     3,
469     # sample rate
470     22050,
471     #channels
472     1,
473 dpavlin 24 );
474    
475 dpavlin 28 sub audio_frame {
476     my $data = shift || die "no data?";
477 dpavlin 24
478 dpavlin 28 my ( $origin, $index, $bytes ) = unpack 'ssL', substr($data,0,8);
479    
480     warn "audio_frame origin $origin index $index bytes $bytes\n";
481     hex_dump( substr($data,0,8) );
482    
483     $pred_val = $origin;
484     $step_idx = $index;
485    
486     foreach my $b ( map { ord($_) } split(//, substr($data,8)) ) {
487     print $au_fh pack 'n', adpcm_decode_sample( $b >> 4 );
488     print $au_fh pack 'n', adpcm_decode_sample( $b & 15 );
489     }
490     }
491    
492    
493     sub x_audio_frame {
494     my $data = shift || die "no data?";
495    
496     my $apath = sprintf("$dump_dir/%04d.wav", $frame_nr );
497     open(my $audio_fh, '>', $apath) || die "can't open audio file $apath: $!";
498    
499     print $audio_fh pack 'a4Va4a4VvvVVv4', (
500     # header 'RIFF', size
501     'RIFF',-1,
502     # type: 'WAVE'
503     'WAVE',
504     'fmt ',0x14,
505     # format: DVI (IMA) ADPCM Wave Type
506     0x11,
507     # channels
508     1,
509     # samples/sec
510     22050,
511     # avg. bytes/sec (for esimation)
512     11567,
513     # block align (size of block)
514     0x800,
515     # bits per sample (mono data)
516     4,
517     # cbSize (ADPCM with 7 soefficient pairs)
518     2,
519     # nSamplesPerBlock
520     # (((nBlockAlign - (7 * nChannels)) * 8) / (wBitsPerSample * nChannels)) + 2
521     0x03f9,
522     );
523    
524     print $audio_fh pack 'a4VVa4V', (
525     # time length of the data in samples
526     'fact',4,
527     220500,
528     #
529     'data',-1,
530     );
531    
532     my $riff_header_len = tell($audio_fh);
533    
534     print $audio_fh $data;
535    
536     my $size = tell($audio_fh);
537     warn "## wav file $apath size: $size\n";
538    
539     seek( $audio_fh, 4, 0 );
540     print $audio_fh pack("V", $size - 8);
541     seek( $audio_fh, $riff_header_len - 4, 0 );
542     print $audio_fh pack("V", $size - $riff_header_len);
543    
544     close($audio_fh) || die "can't close audio file $apath: $!";
545     }
546    
547     #
548     # read AMV file
549     #
550    
551     my ( $riff, $amv ) = x(12, 'Z4x4Z4');
552     die "$path not RIFF but $riff" if $riff ne 'RIFF';
553     die "$path not AMV but $amv" if $amv ne 'AMV ';
554    
555 dpavlin 4 while ( ! defined($d->{eof}) ) {
556 dpavlin 3 my ( $list, $name ) = x(12,'A4x4A4');
557     die "not LIST but $list" if $list ne 'LIST';
558 dpavlin 24 print "< $list * $name\n" if $verbose;
559 dpavlin 3
560     if ( $name eq 'hdrl' ) {
561    
562     my $len = next_part( 'amvh', hex(38) );
563    
564     my @names = ( qw/ms_per_frame width height fps ss mm hh/ );
565     my $h;
566     map {
567     my $v = $_;
568     my $n = shift @names || die "no more names?";
569     $h->{$n} = $v;
570     } x($len, 'Vx28VVVx8CCv');
571    
572     printf "## %s %d*%d %s fps (%d ms/frame) %02d:%02d:%02d\n",
573 dpavlin 8 $path,
574 dpavlin 3 $h->{width}, $h->{height}, $h->{fps}, $h->{ms_per_frame},
575     $h->{hh}, $h->{mm}, $h->{ss};
576    
577     $d->{amvh} = $h;
578    
579     } elsif ( $name eq 'strl' ) {
580    
581     next_part( 'strh', 0, 1 );
582     next_part( 'strf', 0, 1 );
583    
584 dpavlin 4 } elsif ( $name eq 'movi' ) {
585    
586     while (1) {
587     my $frame = $d->{movi}++;
588    
589 dpavlin 8 my $len = next_part( '00dc' );
590 dpavlin 4 last unless $len;
591 dpavlin 24 printf "<< %s 00dc - part %d jpeg %d 0x%x bytes\n", $name, $frame, $len, $len if $verbose;
592 dpavlin 19 mkjpg( x($len) );
593 dpavlin 4
594 dpavlin 24 $len = next_part( '01wb' );
595     printf "<< %s 01wb - part %d audio %d 0x%x bytes\n", $name, $frame, $len, $len if $verbose;
596    
597     my $audio_frame = x( $len );
598    
599 dpavlin 25 if ( $dump_audio ) {
600     printf "#### dumping audio frame %d 0x%x bytes\n", length($audio_frame), length($audio_frame);
601     hex_dump( $audio_frame );
602     }
603    
604 dpavlin 24 # remove 8 bytes of something
605 dpavlin 28 # $audio_frame = substr( $audio_frame, 8 );
606 dpavlin 24
607     if ( length($audio_frame) % 2 == 0 ) {
608     print "#### even sized frame!";
609     # $audio_frame = substr( $audio_frame, 0, -1 );
610     }
611    
612     # print $audio_fh mp3_frame;
613 dpavlin 28 audio_frame( $audio_frame );
614 dpavlin 24
615     $frame_nr++;
616 dpavlin 4 };
617    
618 dpavlin 3 } else {
619     die "unknown $list $name";
620     }
621     }
622 dpavlin 20
623 dpavlin 23 my $cmd = "ffmpeg -i $dump_dir/%04d.jpg -r 16 -y $dump_avi";
624 dpavlin 20 system($cmd) == 0 || die "can't convert frames to avi using $cmd: $!";
625    
626 dpavlin 28 print ">>>> created $frame_nr frames $dump_avi ", -s $dump_avi, "\n";

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26