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

Contents of /amv.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (show 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 #!/usr/bin/perl -w
2
3 # amv.pl
4 #
5 # 07/19/07 19:21:39 CEST Dobrica Pavlinusic <dpavlin@rot13.org>
6 #
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 # http://www.obrador.com/essentialjpeg/HeaderInfo.htm
11 # http://lists.helixcommunity.org/pipermail/datatype-dev/2005-January/001886.html
12 # http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm
13 # http://wiki.multimedia.cx/index.php?title=IMA_ADPCM
14
15 use strict;
16
17 use Data::Dump qw/dump/;
18 use Carp qw/confess/;
19 use File::Path;
20 use Getopt::Long;
21
22 my $dump_amv = 0;
23 my $dump_video = 0;
24 my $dump_jpeg = 0;
25 my $dump_audio = 0;
26 my $debug = 0;
27 my $verbose = 0;
28 my $dump_dir = '/tmp/dump/';
29 my $dump_avi = "dump.avi";
30 my $no_jpeg_header = 0;
31 my $jpeg_q = 100;
32 my $jpegtran;
33
34 GetOptions(
35 "dump-amv!" => \$dump_amv,
36 "dump-video!" => \$dump_video,
37 "dump-jpeg!" => \$dump_jpeg,
38 "dump-audio!" => \$dump_audio,
39 "debug!" => \$debug,
40 "dump-dir=s" => \$dump_dir,
41 "no-jpeg-headers!" => \$no_jpeg_header,
42 "jpegtran=s" => \$jpegtran,
43 "verbose!" => \$verbose,
44 );
45
46 my $path = shift @ARGV || die "usage: $0 movie.amv\n";
47
48 # by default, flip frames
49 #$jpegtran = '-flip vertical' unless defined($jpegtran);
50
51 rmtree $dump_dir if -e $dump_dir;
52 mkpath $dump_dir || die "can't create $dump_dir: $!";
53
54 open(my $fh, '<', $path) || die "can't open $path: $!";
55
56 # offset in file
57 my $o = 0;
58
59 # shared data hash
60 my $d;
61
62 sub hex_dump {
63 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 my $ascii = $bytes;
73 $ascii =~ s/\W/./gs;
74 my $hex = uc( unpack('h*', $bytes) );
75 $hex =~ s/(..)/$1 /g;
76 # calculate number of characters for offset
77 #my $d = length( sprintf("%x",length($bytes)) );
78 my $d = 4;
79 my $prefix = '#.';
80 while ( $hex =~ s/^((?:\w\w\s){1,16})// ) {
81 printf "$prefix %0${d}x | %-48s| %s\n", $o, $1, substr( $ascii, 0, 16 );
82 $prefix = '##';
83 if ( length($ascii) >= 16 ) {
84 $ascii = substr( $ascii, 16 );
85 $o += 16;
86 } else {
87 $o += length($ascii);
88 last;
89 }
90 }
91
92 $o = $old_o if $old_o;
93 }
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 if ( $dump_amv ) {
105 print "## raw $len bytes\n";
106 hex_dump( $bytes );
107 }
108
109 if ( $bytes eq 'AMV_END_' ) {
110 print "> end of file marker AMV_END_\n" if $dump_video;
111 $d->{eof}++;
112 return;
113 }
114
115 if ( $format ) {
116 my @data = unpack($format, $bytes);
117 print "## unpacked = ",dump(@data),"\n" if $debug;
118 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 return unless $len;
128 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 printf "## next_part %s - %d 0x%x bytes\n", $part, $len, $len if $debug;
133 x($len) if $skip;
134 return $len;
135 }
136
137 sub quality {
138 my @table = @_;
139 die "quantization matrice needs to have 64 bytes!" if $#table != 63;
140
141 my $in = join('', map { chr($_) } @table );
142 my $out;
143
144 foreach my $t ( @table ) {
145 $t = int( ( $t * $jpeg_q ) / 100 );
146 $t = 255 if $t > 255;
147 $out .= chr($t);
148 }
149
150 if ( $dump_video ) {
151 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 }
159
160 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 my @subframes;
224 my $frame_nr = 1;
225
226 # how many subframes to join into single frame?
227 my $join_subframes = 0;
228
229 sub mkjpg {
230 my ($data) = @_;
231
232 confess "no SOI marker in data" if substr($data,0,2) ne "\xFF\xD8";
233 confess "no EOI marker in data" if substr($data,-2,2) ne "\xFF\xD9";
234 $data = substr($data,2,-2);
235
236 if ( $#subframes < ( $join_subframes - 1 ) ) {
237 push @subframes, $data;
238 print "## saved $frame_nr/", $#subframes + 1, " subframe of ", length($data), " bytes\n" if $debug;
239 return;
240 }
241
242 my $w = $d->{amvh}->{width} || die "no width?";
243 my $h = $d->{amvh}->{height} || confess "no height?";
244
245 my $header =
246 # Start of Image (SOI) marker
247 "\xFF\xD8".
248 # JFIF marker
249 "\xFF\xE0".
250 pack("nZ5CCCnnCC",
251 16, # length
252 'JFIF', # identifier (JFIF)
253 1,1, # version
254 0, # units (none)
255 1,1, # X,Y density
256 0,0, # X,Y thumbnail
257 ).
258 "\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 pack("ncnncc9",
292 17, # len
293 8, # sample precision in bits
294 $h,$w, # X,Y size
295 3, # number of components
296 1,0x22,0, # Component ID, H+V sampling factors, Quantization table number
297 2,0x11,1,
298 3,0x11,1,
299 ).
300 # Define huffman table (section B.2.4.1)
301 "\xFF\xC4". # Marker
302 "\x00\x1F". # Length (31 bytes)
303 "\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 # Define huffman table (section B.2.4.1)
307 "\xFF\xC4". # Marker
308 "\x00\xB5". # Length (181 bytes)
309 "\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 "\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 # 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 #/* Define huffman table (section B.2.4.1) */
333 "\xFF\xC4". # Marker
334 "\x00\xB5". # Length (181 bytes)
335 "\x11". # AC chrominance, table 1
336 "\x00\x02\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04".
337 "\x00\x01\x02\x77".
338 "\x00\x01\x02\x03\x11\x04\x05\x21".
339 "\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 # 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
364 if ( $dump_jpeg ) {
365 print "## created JPEG header...\n";
366 hex_dump( $header, 0 );
367 }
368
369 my $frame = join('', @subframes ) . $data;
370 @subframes = ();
371
372 my $path = sprintf("$dump_dir/%04d.jpg", $frame_nr );
373
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 if ( ! $no_jpeg_header ) {
382 print $fh $header . $frame . "\xFF\xD9" || die "can't write jpeg $path: $!";
383 } else {
384 print $fh $frame || die "can't write raw jpeg $path: $!";
385 }
386 close $fh || die "can't close $path: $!";
387 print ">> created $frame_nr ", $no_jpeg_header ? 'raw' : '', " jpeg $path ", -s $path, " bytes\n" if $verbose;
388 }
389
390 #
391 # IMA ADPCM decoder
392 #
393
394 my @index_adjust = ( -1, -1, -1, -1, 2, 4, 6, 8 );
395
396 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 );
407
408 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 );
474
475 sub audio_frame {
476 my $data = shift || die "no data?";
477
478 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 while ( ! defined($d->{eof}) ) {
556 my ( $list, $name ) = x(12,'A4x4A4');
557 die "not LIST but $list" if $list ne 'LIST';
558 print "< $list * $name\n" if $verbose;
559
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 $path,
574 $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 } elsif ( $name eq 'movi' ) {
585
586 while (1) {
587 my $frame = $d->{movi}++;
588
589 my $len = next_part( '00dc' );
590 last unless $len;
591 printf "<< %s 00dc - part %d jpeg %d 0x%x bytes\n", $name, $frame, $len, $len if $verbose;
592 mkjpg( x($len) );
593
594 $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 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 # remove 8 bytes of something
605 # $audio_frame = substr( $audio_frame, 8 );
606
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 audio_frame( $audio_frame );
614
615 $frame_nr++;
616 };
617
618 } else {
619 die "unknown $list $name";
620 }
621 }
622
623 my $cmd = "ffmpeg -i $dump_dir/%04d.jpg -r 16 -y $dump_avi";
624 system($cmd) == 0 || die "can't convert frames to avi using $cmd: $!";
625
626 print ">>>> created $frame_nr frames $dump_avi ", -s $dump_avi, "\n";

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26