/[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 13 by dpavlin, Fri Jul 20 16:55:33 2007 UTC revision 28 by dpavlin, Sun Aug 19 11:45:39 2007 UTC
# Line 9  Line 9 
9  # http://en.wikipedia.org/wiki/RIFF_(File_format)  # http://en.wikipedia.org/wiki/RIFF_(File_format)
10  # http://www.obrador.com/essentialjpeg/HeaderInfo.htm  # http://www.obrador.com/essentialjpeg/HeaderInfo.htm
11  # http://lists.helixcommunity.org/pipermail/datatype-dev/2005-January/001886.html  # 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;  use strict;
16    
17  use Data::Dump qw/dump/;  use Data::Dump qw/dump/;
18  use Carp qw/confess/;  use Carp qw/confess/;
19  use File::Path;  use File::Path;
20    use Getopt::Long;
21    
22  my $dump = 0;  my $dump_amv = 0;
23    my $dump_video = 0;
24    my $dump_jpeg = 0;
25    my $dump_audio = 0;
26  my $debug = 0;  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";  my $path = shift @ARGV || die "usage: $0 movie.amv\n";
47    
48  my $dump_dir = '/tmp/dump/';  # by default, flip frames
49    #$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    
# Line 34  my $o = 0; Line 60  my $o = 0;
60  my $d;  my $d;
61    
62  sub hex_dump {  sub hex_dump {
         return unless $dump;  
   
63          my ( $bytes, $offset ) = @_;          my ( $bytes, $offset ) = @_;
64          return unless $bytes;          return unless $bytes;
65    
# Line 77  sub x { Line 101  sub x {
101          my $r_len = length($bytes);          my $r_len = length($bytes);
102          confess "read $r_len bytes, expected $len" if $len != $r_len;          confess "read $r_len bytes, expected $len" if $len != $r_len;
103    
104          hex_dump( $bytes );          if ( $dump_amv ) {
105                    print "## raw $len bytes\n";
106                    hex_dump( $bytes );
107            }
108    
109          if ( $bytes eq 'AMV_END_' ) {          if ( $bytes eq 'AMV_END_' ) {
110                  warn "> end of file marker AMV_END_\n";                  print "> end of file marker AMV_END_\n" if $dump_video;
111                  $d->{eof}++;                  $d->{eof}++;
112                  return;                  return;
113          }          }
114    
115          if ( $format ) {          if ( $format ) {
116                  my @data = unpack($format, $bytes);                  my @data = unpack($format, $bytes);
117                  warn "## unpacked = ",dump(@data),"\n" if $debug;                  print "## unpacked = ",dump(@data),"\n" if $debug;
118                  return @data;                  return @data;
119          } else {          } else {
120                  return $bytes;                  return $bytes;
# Line 102  sub next_part { Line 129  sub next_part {
129          if ( $expected_len ) {          if ( $expected_len ) {
130                  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;
131          }          }
132          printf "<< %s - %d 0x%x bytes\n", $part, $len, $len;          printf "## next_part %s - %d 0x%x bytes\n", $part, $len, $len if $debug;
133          x($len) if $skip;          x($len) if $skip;
134          return $len;          return $len;
135  }  }
136    
137  sub huffman {  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  # JPEG DHT Segment for YCrCb omitted from MJPG data          if ( $dump_video ) {
151  return                  print "## quantization table original\n";
152  "\xFF\xC4\x01\xA2" .                  hex_dump( $in );
153  "\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00" .                  print "## quantization table for $jpeg_q %\n";
154  "\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x01" .                  hex_dump( $out );
155  "\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";  
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 {  sub mkjpg {
230          my ($path,$data) = @_;          my ($data) = @_;
         open(my $fh, '>', $path) || die "can't create $path: $!";  
231    
232          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";
233          $data = substr($data,2);          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 =          my $header =
246                  "\xFF\xD8".     # Start of Image (SOI) marker          # Start of Image (SOI) marker
247  #------------------------------------------------------------------          "\xFF\xD8".
248                  "\xFF\xE0".     # JFIF marker          # JFIF marker
249            "\xFF\xE0".
250          pack("nZ5CCCnnCC",          pack("nZ5CCCnnCC",
251                  16,                     # length                  16,                     # length
252                  'JFIF',         # identifier                  'JFIF',         # identifier (JFIF)
253                  1,1,            # version                  1,1,            # version
254                  0,                      # units (none)                  0,                      # units (none)
255                  1,1,            # X,Y density                  1,1,            # X,Y density
256                  0,0,            # X,Y thumbnail                  0,0,            # X,Y thumbnail
257          ).          ).
258  #------------------------------------------------------------------          "\xFF\xFE".
259          "\xFF\xC0".     # Start of frame          "\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",          pack("ncnncc9",
292                  17,                     # len                  17,                     # len
293                  8,                      # sample precision in bits                  8,                      # sample precision in bits
294                  120,160,        # X,Y size                  $h,$w,          # X,Y size
295                  3,                      # number of components                  3,                      # number of components
296                  1,0x21,0,       # Component ID, H+V sampling factors, Quantization table number                  1,0x22,0,       # Component ID, H+V sampling factors, Quantization table number
297                  2,0x11,1,                  2,0x11,1,
298                  3,0x11,1,                  3,0x11,1,
299          ).          ).
 #------------------------------------------------------------------  
         "\xFF\xDB".             # Define Quantization table marker  
         "\x00\x84".             # len  
         "\x00".                 # 8 bit values, (byte) table 0  
         "\x10\x0B\x0C\x0E\x0C".  
         "\x0A\x10\x0E\x0D\x0E".  
         "\x12\x11\x10\x13\x18".  
         "\x28\x1A\x18\x16\x16".  
         "\x18\x31\x23\x25\x1D".  
         "\x28\x3A\x33\x3D\x3C".  
         "\x39\x33\x38\x37\x40".  
         "\x48\x5C\x4E\x40\x44".  
         "\x57\x45\x37\x38\x50".  
         "\x6D\x51\x57\x5F\x62".  
         "\x67\x68\x67\x3E\x4D".  
         "\x71\x79\x70\x64\x78".  
         "\x5C\x65\x67\x63".  
         "\x01".         # 8 bit values, (byte) table 1  
         "\x11\x12\x12\x18\x15".  
         "\x18\x2F\x1A\x1A\x2F".  
         "\x63\x42\x38\x42\x63".  
         "\x63\x63\x63\x63\x63".  
         "\x63\x63\x63\x63\x63".  
         "\x63\x63\x63\x63\x63".  
         "\x63\x63\x63\x63\x63".  
         "\x63\x63\x63\x63\x63".  
         "\x63\x63\x63\x63\x63".  
         "\x63\x63\x63\x63\x63".  
         "\x63\x63\x63\x63\x63".  
         "\x63\x63\x63\x63\x63".  
         "\x63\x63\x63\x63".  
 #------------------------------------------------------------------  
 #       huffman("\x00").        # 0 DC  
 #       huffman("\x01").        # 1 DC  
 #       huffman("\x10").        # 0 AC  
 #       huffman("\x11").        # 1 AC  
 #------------------------------------------------------------------  
         # Define huffman table (section B.2.4.1)  
         "\xFF\xC4".             # Marker  
         "\x00\x1F".             # Length (31 bytes)  
         "\x00".                 # DC, (byte) table 0  
         "\x00\x01\x05\x01\x01".  
         "\x01\x01\x01\x01\x00".  
         "\x00\x00\x00\x00\x00".  
         "\x00\x00\x01\x02\x03".  
         "\x04\x05\x06\x07\x08".  
         "\x09\x0A\x0B".  
         # Define huffman table (section B.2.4.1)  
         "\xFF\xC4".             # Marker  
         "\x00\xB5".             # Length (181 bytes)  
         "\x10".                 # AC, (byte) table 0  
         "\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".  
         # Define huffman table (section B.2.4.1)  
         "\xFF\xC4".             # Marker  
         "\x00\x1F".             # Length (31 bytes)  
         "\x01".                 # DC, (byte) table 1  
         "\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".  
         # Define huffman table (section B.2.4.1)  
         "\xFF\xC4".             # Marker  
         "\x00\xB5".             # Length (181 bytes)  
         "\x11".                 # AC, (byte) table 1  
         "\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".  
 #------------------------------------------------------------------  
                 "\xFF\xDA".     # Start of Scan marker  
         pack("nC11",  
                 12,                     # length  
                 3,                      # number of components  
                 1,0x00,         # Scan 1: use DC/AC huff tables 0/0  
                 2,0x11,         # Scan 2: use DC/AC huff tables 1/1  
                 3,0x11,         # Scan 3: use DC/AC huff tables 1/1  
                 0,0x3f,         # Ss, Se  
                 0,                      # Ah, Ai (not used)  
         );  
 #------------------------------------------------------------------  
   
         my $header =  
         # SOI  
         "\xFF\xD8".  
         # JFIF  
         "\xFF\xE0".  
         "\x00\x0e\x41\x56\x49\x31\x00\x00\x00\x00\x00\x00\x00\x00".  
         "\xff\xDD\x00\x04\x00\x00".  
         # quantization table  
         "\xFF\xDB".  
         "\x00\x43\x00\x21\x16\x18".  
         "\x1D\x18\x14\x21\x1D\x1B\x1D\x25".  
         "\x23\x21\x27\x31\x53\x36\x31\x2D".  
         "\x2D\x31\x65\x48\x4c\x3c\x53\x78".  
         "\x6a\x7e\x7c\x76\x6a\x74\x72\x85".  
         "\x95\xbf\xa2\x85\x8d\xb4\x8f\x72".  
         "\x74\xa6\xe2\xa8\xb4\xc5\xcb\xd6".  
         "\xd8\xd6\x80\xa0\xeb\xfb\xe8\xd0".  
         "\xf9\xbf\xd2\xd6\xcd".  
         # quantization table  
         "\xff\xdb".  
         "\x00\x43\x01\x23\x25\x25\x31\x2b\x31".  
         "\x61\x36\x36\x61\xcd\x89\x74\x89".  
         "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd".  
         "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd".  
         "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd".  
         "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd".  
         "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd".  
         "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd".  
         "\xcd\xcd".  
300          # Define huffman table (section B.2.4.1)          # Define huffman table (section B.2.4.1)
301          "\xFF\xC4".     # Marker          "\xFF\xC4".     # Marker
302          "\x00\x1F".     # Length (31 bytes)          "\x00\x1F".     # Length (31 bytes)
303          "\x00".         # DC, table 0          "\x00".         # DC luminance, table 0
304          "\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00".          "\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00".
305          "\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07".          "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B".
         "\x08\x09\x0A\x0B".  
306          # Define huffman table (section B.2.4.1)          # Define huffman table (section B.2.4.1)
307          "\xFF\xC4".     # Marker          "\xFF\xC4".     # Marker
308          "\x00\xB5".     # Length (181 bytes)          "\x00\xB5".     # Length (181 bytes)
309          "\x10".         # AC, table 0          "\x10".         # AC luminance, table 0
310          "\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04".          "\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01\x7D".
311          "\x00\x00\x01\x7D\x01\x02\x03\x00\x04\x11\x05\x12".          "\x01\x02\x03\x00\x04\x11\x05\x12".
312          "\x21\x31\x41\x06\x13\x51\x61\x07\x22\x71\x14\x32".          "\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".          "\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".          "\x24\x33\x62\x72\x82\x09\x0A\x16\x17\x18\x19\x1A".
# Line 379  sub mkjpg { Line 323  sub mkjpg {
323          "\xD9\xDA\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA".          "\xD9\xDA\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA".
324          "\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA".          "\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA".
325          # Define huffman table (section B.2.4.1)          # Define huffman table (section B.2.4.1)
326          "\xFF\xC4".     #       /* Marker */          "\xFF\xC4".     # Marker
327          "\x00\x1F".     #       /* Length (31 bytes) */          "\x00\x1F".     # Length (31 bytes)
328          "\x01".         #/* DC". table 1 */          "\x01".         # DC chrominance, table 1
329          "\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00".          "\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00".
330          "\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07".          "\x00\x00\x00\x00".
331          "\x08\x09\x0A\x0B".          "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B".
332          #/* Define huffman table (section B.2.4.1) */          #/* Define huffman table (section B.2.4.1) */
333          "\xFF\xC4".     #       /* Marker */          "\xFF\xC4".     # Marker
334          "\x00\xB5".     #       /* Length (181 bytes) */          "\x00\xB5".     # Length (181 bytes)
335          "\x11".         #/* AC". table 1 */          "\x11".         # AC chrominance, table 1
336          "\x00\x02\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04".          "\x00\x02\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04".
337          "\x00\x01\x02\x77\x00\x01\x02\x03\x11\x04\x05\x21".          "\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".          "\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".          "\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".          "\x15\x62\x72\xD1\x0A\x16\x24\x34\xE1\x25\xF1\x17".
# Line 404  sub mkjpg { Line 349  sub mkjpg {
349          "\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2\xD3\xD4\xD5\xD6".          "\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".          "\xD7\xD8\xD9\xDA\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9".
351          "\xEA\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA".          "\xEA\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA".
352          # start of frame          # Start of Scan marker
353          "\xff\xc0".          "\xFF\xDA".
354          "\x00\x11\x08".          pack("nC10",
355          pack("nn", 120, 160).                  12,                     # length
356          "\x03\x01\x21\x00\x02\x11\x01\x03\x11\x01".                  3,                      # number of components
357          #                  1,0x00,         # Scan 1: use DC/AC huff tables 0/0
358          "\xff\xda".                  2,0x11,         # Scan 2: use DC/AC huff tables 1/1
359          "\x00\x0c\x03\x01\x00\x02\x11\x03\x11".                  3,0x11,         # Scan 3: use DC/AC huff tables 1/1
360          "\x00\x3f\x00";                  0,0x3f,         # Ss, Se
361                    0,                      # Ah, Ai (not used)
362            );
363    
364          if ( $dump ) {          if ( $dump_jpeg ) {
365                  warn "## created JPEG header...\n";                  print "## created JPEG header...\n";
366                  hex_dump( $header, 0 );                  hex_dump( $header, 0 );
367          }          }
368    
369          print $fh $header || die "can't write header into $path: $!";          my $frame = join('', @subframes ) . $data;
370          print $fh $data || die "can't write frame into $path: $!";          @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: $!";          close $fh || die "can't close $path: $!";
387          print ">> created $path ", -s $path, " bytes\n";          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');  my ( $riff, $amv ) = x(12, 'Z4x4Z4');
552  die "$path not RIFF but $riff" if $riff ne 'RIFF';  die "$path not RIFF but $riff" if $riff ne 'RIFF';
553  die "$path not AMV but $amv" if $amv ne 'AMV ';  die "$path not AMV but $amv" if $amv ne 'AMV ';
# Line 432  die "$path not AMV but $amv" if $amv ne Line 555  die "$path not AMV but $amv" if $amv ne
555  while ( ! defined($d->{eof}) ) {  while ( ! defined($d->{eof}) ) {
556          my ( $list, $name ) = x(12,'A4x4A4');          my ( $list, $name ) = x(12,'A4x4A4');
557          die "not LIST but $list" if $list ne 'LIST';          die "not LIST but $list" if $list ne 'LIST';
558          print "< $list * $name\n";          print "< $list * $name\n" if $verbose;
559    
560          if ( $name eq 'hdrl' ) {          if ( $name eq 'hdrl' ) {
561    
# Line 465  while ( ! defined($d->{eof}) ) { Line 588  while ( ! defined($d->{eof}) ) {
588                                    
589                          my $len = next_part( '00dc' );                          my $len = next_part( '00dc' );
590                          last unless $len;                          last unless $len;
591                          printf "<< %s 00dc - frame %d jpeg %d 0x%x bytes\n", $name, $frame, $len, $len;                          printf "<< %s 00dc - part %d jpeg %d 0x%x bytes\n", $name, $frame, $len, $len if $verbose;
592                          mkjpg( sprintf("$dump_dir/%03d.jpg", $frame ), x($len) );                          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                          $len = next_part( '01wb', 0, 1 );                          if ( $dump_audio ) {
600                          printf "<< %s 01wb - frame %d audio %d 0x%x bytes\n", $name, $frame, $len, $len;                                  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 {          } else {
619                  die "unknown $list $name";                  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";

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

  ViewVC Help
Powered by ViewVC 1.1.26