/[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 5 by dpavlin, Thu Jul 19 20:53:33 2007 UTC revision 11 by dpavlin, Fri Jul 20 16:07:46 2007 UTC
# Line 3  Line 3 
3  # amv.pl  # amv.pl
4  #  #
5  # 07/19/07 19:21:39 CEST Dobrica Pavlinusic <dpavlin@rot13.org>  # 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    
13  use strict;  use strict;
14    
15  use Data::Dump qw/dump/;  use Data::Dump qw/dump/;
16  use Carp qw/confess/;  use Carp qw/confess/;
17    use File::Path;
18    
19    my $dump = 0;
20    my $debug = 0;
21    
22  my $path = shift @ARGV || die "usage: $0 movie.amv\n";  my $path = shift @ARGV || die "usage: $0 movie.amv\n";
23    
24    my $dump_dir = '/tmp/dump/';
25    rmtree $dump_dir if -e $dump_dir;
26    mkpath $dump_dir || die "can't create $dump_dir: $!";
27    
28  open(my $fh, '<', $path) || die "can't open $path: $!";  open(my $fh, '<', $path) || die "can't open $path: $!";
29    
30  # offset in file  # offset in file
# Line 20  my $o = 0; Line 34  my $o = 0;
34  my $d;  my $d;
35    
36  sub hex_dump {  sub hex_dump {
37          my $bytes = shift || return;          return unless $dump;
38    
39            my ( $bytes, $offset ) = @_;
40            return unless $bytes;
41    
42            my $old_o;
43            if (defined($offset)) {
44                    $old_o = $o;
45                    $o = $offset;
46            }
47    
48          my $ascii = $bytes;          my $ascii = $bytes;
49          $ascii =~ s/\W/./gs;          $ascii =~ s/\W/./gs;
50          my $hex = unpack('h*', $bytes);          my $hex = uc( unpack('h*', $bytes) );
51          $hex =~ s/(..)/$1 /g;          $hex =~ s/(..)/$1 /g;
52          # calculate number of characters for offset          # calculate number of characters for offset
53          #my $d = length( sprintf("%x",length($bytes)) );          #my $d = length( sprintf("%x",length($bytes)) );
54          my $d = 4;          my $d = 4;
55            my $prefix = '#.';
56          while ( $hex =~ s/^((?:\w\w\s){1,16})// ) {          while ( $hex =~ s/^((?:\w\w\s){1,16})// ) {
57                  printf "## %0${d}x | %-48s| %s\n", $o, $1, substr( $ascii, 0, 16 );                  printf "$prefix %0${d}x | %-48s| %s\n", $o, $1, substr( $ascii, 0, 16 );
58                    $prefix = '##';
59                  if ( length($ascii) >= 16 ) {                  if ( length($ascii) >= 16 ) {
60                          $ascii = substr( $ascii, 16 );                          $ascii = substr( $ascii, 16 );
61                          $o += 16;                          $o += 16;
# Line 39  sub hex_dump { Line 64  sub hex_dump {
64                          last;                          last;
65                  }                  }
66          }          }
67    
68            $o = $old_o if $old_o;
69  }  }
70    
71  sub x {  sub x {
# Line 60  sub x { Line 87  sub x {
87    
88          if ( $format ) {          if ( $format ) {
89                  my @data = unpack($format, $bytes);                  my @data = unpack($format, $bytes);
90                  warn "## unpacked = ",dump(@data),"\n";                  warn "## unpacked = ",dump(@data),"\n" if $debug;
91                  return @data;                  return @data;
92          } else {          } else {
93                  return $bytes;                  return $bytes;
# Line 75  sub next_part { Line 102  sub next_part {
102          if ( $expected_len ) {          if ( $expected_len ) {
103                  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;
104          }          }
105          printf ">> %s - %d 0x%x bytes\n", $part, $len, $len;          printf "<< %s - %d 0x%x bytes\n", $part, $len, $len;
106          x($len) if $skip;          x($len) if $skip;
107          return $len;          return $len;
108  }  }
109    
110  my ( $riff, $amv ) = x(12, 'Z8Z4');  sub huffman {
111  die "not RIFF but $riff" if $riff ne 'RIFF';  
112  die "not AMV but $amv" if $amv ne 'AMV ';  # JPEG DHT Segment for YCrCb omitted from MJPG data
113    return
114    "\xFF\xC4\x01\xA2" .
115    "\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00" .
116    "\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x01" .
117    "\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00" .
118    "\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x10\x00" .
119    "\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01\x7D" .
120    "\x01\x02\x03\x00\x04\x11\x05\x12\x21\x31\x41\x06\x13\x51\x61" .
121    "\x07\x22\x71\x14\x32\x81\x91\xA1\x08\x23\x42\xB1\xC1\x15\x52" .
122    "\xD1\xF0\x24\x33\x62\x72\x82\x09\x0A\x16\x17\x18\x19\x1A\x25" .
123    "\x26\x27\x28\x29\x2A\x34\x35\x36\x37\x38\x39\x3A\x43\x44\x45" .
124    "\x46\x47\x48\x49\x4A\x53\x54\x55\x56\x57\x58\x59\x5A\x63\x64" .
125    "\x65\x66\x67\x68\x69\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x83" .
126    "\x84\x85\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96\x97\x98\x99" .
127    "\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xB2\xB3\xB4\xB5\xB6" .
128    "\xB7\xB8\xB9\xBA\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2\xD3" .
129    "\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8" .
130    "\xE9\xEA\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\x11\x00\x02" .
131    "\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04\x00\x01\x02\x77\x00" .
132    "\x01\x02\x03\x11\x04\x05\x21\x31\x06\x12\x41\x51\x07\x61\x71" .
133    "\x13\x22\x32\x81\x08\x14\x42\x91\xA1\xB1\xC1\x09\x23\x33\x52" .
134    "\xF0\x15\x62\x72\xD1\x0A\x16\x24\x34\xE1\x25\xF1\x17\x18\x19" .
135    "\x1A\x26\x27\x28\x29\x2A\x35\x36\x37\x38\x39\x3A\x43\x44\x45" .
136    "\x46\x47\x48\x49\x4A\x53\x54\x55\x56\x57\x58\x59\x5A\x63\x64" .
137    "\x65\x66\x67\x68\x69\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x82" .
138    "\x83\x84\x85\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96\x97\x98" .
139    "\x99\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xB2\xB3\xB4\xB5" .
140    "\xB6\xB7\xB8\xB9\xBA\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2" .
141    "\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xE2\xE3\xE4\xE5\xE6\xE7\xE8" .
142    "\xE9\xEA\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA";
143    
144    }
145    
146    sub mkjpg {
147            my ($path,$data) = @_;
148            open(my $fh, '>', $path) || die "can't create $path: $!";
149    
150            confess "no SOI marker in data" if substr($data,0,2) ne "\xFF\xD8";
151            $data = substr($data,2);
152    
153            my $header =
154                    "\xFF\xD8".     # Start of Image (SOI) marker
155    #------------------------------------------------------------------
156                    "\xFF\xE0".     # JFIF marker
157            pack("nZ5CCCnnCC",
158                    16,                     # length
159                    'JFIF',         # identifier
160                    1,1,            # version
161                    0,                      # units (none)
162                    1,1,            # X,Y density
163                    0,0,            # X,Y thumbnail
164            ).
165    #------------------------------------------------------------------
166            "\xFF\xC0".     # Start of frame
167            pack("ncnncc9",
168                    17,                     # len
169                    8,                      # sample precision in bits
170                    120,160,        # X,Y size
171                    3,                      # number of components
172                    1,0x21,0,       # Component ID, H+V sampling factors, Quantization table number
173                    2,0x11,1,
174                    3,0x11,1,
175            ).
176    #------------------------------------------------------------------
177            "\xFF\xDB".             # Define Quantization table marker
178            "\x00\x84".             # len
179            "\x00".                 # 8 bit values, (byte) table 0
180            "\x10\x0B\x0C\x0E\x0C".
181            "\x0A\x10\x0E\x0D\x0E".
182            "\x12\x11\x10\x13\x18".
183            "\x28\x1A\x18\x16\x16".
184            "\x18\x31\x23\x25\x1D".
185            "\x28\x3A\x33\x3D\x3C".
186            "\x39\x33\x38\x37\x40".
187            "\x48\x5C\x4E\x40\x44".
188            "\x57\x45\x37\x38\x50".
189            "\x6D\x51\x57\x5F\x62".
190            "\x67\x68\x67\x3E\x4D".
191            "\x71\x79\x70\x64\x78".
192            "\x5C\x65\x67\x63".
193            "\x01".         # 8 bit values, (byte) table 1
194            "\x11\x12\x12\x18\x15".
195            "\x18\x2F\x1A\x1A\x2F".
196            "\x63\x42\x38\x42\x63".
197            "\x63\x63\x63\x63\x63".
198            "\x63\x63\x63\x63\x63".
199            "\x63\x63\x63\x63\x63".
200            "\x63\x63\x63\x63\x63".
201            "\x63\x63\x63\x63\x63".
202            "\x63\x63\x63\x63\x63".
203            "\x63\x63\x63\x63\x63".
204            "\x63\x63\x63\x63\x63".
205            "\x63\x63\x63\x63\x63".
206            "\x63\x63\x63\x63".
207    #------------------------------------------------------------------
208    #       huffman("\x00").        # 0 DC
209    #       huffman("\x01").        # 1 DC
210    #       huffman("\x10").        # 0 AC
211    #       huffman("\x11").        # 1 AC
212    #------------------------------------------------------------------
213            # Define huffman table (section B.2.4.1)
214            "\xFF\xC4".             # Marker
215            "\x00\x1F".             # Length (31 bytes)
216            "\x00".                 # DC, (byte) table 0
217            "\x00\x01\x05\x01\x01".
218            "\x01\x01\x01\x01\x00".
219            "\x00\x00\x00\x00\x00".
220            "\x00\x00\x01\x02\x03".
221            "\x04\x05\x06\x07\x08".
222            "\x09\x0A\x0B".
223            # Define huffman table (section B.2.4.1)
224            "\xFF\xC4".             # Marker
225            "\x00\xB5".             # Length (181 bytes)
226            "\x10".                 # AC, (byte) table 0
227            "\x00\x02\x01\x03\x03".
228            "\x02\x04\x03\x05\x05".
229            "\x04\x04\x00\x00\x01".
230            "\x7D\x01\x02\x03\x00".
231            "\x04\x11\x05\x12\x21".
232            "\x31\x41\x06\x13\x51".
233            "\x61\x07\x22\x71\x14".
234            "\x32\x81\x91\xA1\x08".
235            "\x23\x42\xB1\xC1\x15".
236            "\x52\xD1\xF0\x24\x33".
237            "\x62\x72\x82\x09\x0A".
238            "\x16\x17\x18\x19\x1A".
239            "\x25\x26\x27\x28\x29".
240            "\x2A\x34\x35\x36\x37".
241            "\x38\x39\x3A\x43\x44".
242            "\x45\x46\x47\x48\x49".
243            "\x4A\x53\x54\x55\x56".
244            "\x57\x58\x59\x5A\x63".
245            "\x64\x65\x66\x67\x68".
246            "\x69\x6A\x73\x74\x75".
247            "\x76\x77\x78\x79\x7A".
248            "\x83\x84\x85\x86\x87".
249            "\x88\x89\x8A\x92\x93".
250            "\x94\x95\x96\x97\x98".
251            "\x99\x9A\xA2\xA3\xA4".
252            "\xA5\xA6\xA7\xA8\xA9".
253            "\xAA\xB2\xB3\xB4\xB5".
254            "\xB6\xB7\xB8\xB9\xBA".
255            "\xC2\xC3\xC4\xC5\xC6".
256            "\xC7\xC8\xC9\xCA\xD2".
257            "\xD3\xD4\xD5\xD6\xD7".
258            "\xD8\xD9\xDA\xE1\xE2".
259            "\xE3\xE4\xE5\xE6\xE7".
260            "\xE8\xE9\xEA\xF1\xF2".
261            "\xF3\xF4\xF5\xF6\xF7".
262            "\xF8\xF9\xFA".
263            # Define huffman table (section B.2.4.1)
264            "\xFF\xC4".             # Marker
265            "\x00\x1F".             # Length (31 bytes)
266            "\x01".                 # DC, (byte) table 1
267            "\x00\x03\x01\x01\x01".
268            "\x01\x01\x01\x01\x01".
269            "\x01\x00\x00\x00\x00".
270            "\x00\x00\x01\x02\x03".
271            "\x04\x05\x06\x07\x08".
272            "\x09\x0A\x0B".
273            # Define huffman table (section B.2.4.1)
274            "\xFF\xC4".             # Marker
275            "\x00\xB5".             # Length (181 bytes)
276            "\x11".                 # AC, (byte) table 1
277            "\x00\x02\x01\x02\x04".
278            "\x04\x03\x04\x07\x05".
279            "\x04\x04\x00\x01\x02".
280            "\x77\x00\x01\x02\x03".
281            "\x11\x04\x05\x21\x31".
282            "\x06\x12\x41\x51\x07".
283            "\x61\x71\x13\x22\x32".
284            "\x81\x08\x14\x42\x91".
285            "\xA1\xB1\xC1\x09\x23".
286            "\x33\x52\xF0\x15\x62".
287            "\x72\xD1\x0A\x16\x24".
288            "\x34\xE1\x25\xF1\x17".
289            "\x18\x19\x1A\x26\x27".
290            "\x28\x29\x2A\x35\x36".
291            "\x37\x38\x39\x3A\x43".
292            "\x44\x45\x46\x47\x48".
293            "\x49\x4A\x53\x54\x55".
294            "\x56\x57\x58\x59\x5A".
295            "\x63\x64\x65\x66\x67".
296            "\x68\x69\x6A\x73\x74".
297            "\x75\x76\x77\x78\x79".
298            "\x7A\x82\x83\x84\x85".
299            "\x86\x87\x88\x89\x8A".
300            "\x92\x93\x94\x95\x96".
301            "\x97\x98\x99\x9A\xA2".
302            "\xA3\xA4\xA5\xA6\xA7".
303            "\xA8\xA9\xAA\xB2\xB3".
304            "\xB4\xB5\xB6\xB7\xB8".
305            "\xB9\xBA\xC2\xC3\xC4".
306            "\xC5\xC6\xC7\xC8\xC9".
307            "\xCA\xD2\xD3\xD4\xD5".
308            "\xD6\xD7\xD8\xD9\xDA".
309            "\xE2\xE3\xE4\xE5\xE6".
310            "\xE7\xE8\xE9\xEA\xF2".
311            "\xF3\xF4\xF5\xF6\xF7".
312            "\xF8\xF9\xFA".
313    #------------------------------------------------------------------
314                    "\xFF\xDA".     # Start of Scan marker
315            pack("nC11",
316                    12,                     # length
317                    3,                      # number of components
318                    1,0x00,         # Scan 1: use DC/AC huff tables 0/0
319                    2,0x11,         # Scan 2: use DC/AC huff tables 1/1
320                    3,0x11,         # Scan 3: use DC/AC huff tables 1/1
321                    0,0x3f,         # Ss, Se
322                    0,                      # Ah, Ai (not used)
323            );
324    #------------------------------------------------------------------
325    
326    
327            if ( $dump ) {
328                    warn "## created JPEG header...\n";
329                    hex_dump( $header, 0 );
330            }
331    
332            print $fh $header || die "can't write header into $path: $!";
333            print $fh $data || die "can't write frame into $path: $!";
334            close $fh || die "can't close $path: $!";
335            print ">> created $path ", -s $path, " bytes\n";
336    }
337    
338    my ( $riff, $amv ) = x(12, 'Z4x4Z4');
339    die "$path not RIFF but $riff" if $riff ne 'RIFF';
340    die "$path not AMV but $amv" if $amv ne 'AMV ';
341    
342  while ( ! defined($d->{eof}) ) {  while ( ! defined($d->{eof}) ) {
343          my ( $list, $name ) = x(12,'A4x4A4');          my ( $list, $name ) = x(12,'A4x4A4');
344          die "not LIST but $list" if $list ne 'LIST';          die "not LIST but $list" if $list ne 'LIST';
345          print "> $list .. $name\n";          print "< $list * $name\n";
346    
347          if ( $name eq 'hdrl' ) {          if ( $name eq 'hdrl' ) {
348    
# Line 102  while ( ! defined($d->{eof}) ) { Line 357  while ( ! defined($d->{eof}) ) {
357                  } x($len, 'Vx28VVVx8CCv');                  } x($len, 'Vx28VVVx8CCv');
358    
359                  printf "## %s %d*%d %s fps (%d ms/frame) %02d:%02d:%02d\n",                  printf "## %s %d*%d %s fps (%d ms/frame) %02d:%02d:%02d\n",
360                          $h->{path},                          $path,
361                          $h->{width}, $h->{height}, $h->{fps}, $h->{ms_per_frame},                          $h->{width}, $h->{height}, $h->{fps}, $h->{ms_per_frame},
362                          $h->{hh}, $h->{mm}, $h->{ss};                          $h->{hh}, $h->{mm}, $h->{ss};
363    
# Line 118  while ( ! defined($d->{eof}) ) { Line 373  while ( ! defined($d->{eof}) ) {
373                  while (1) {                  while (1) {
374                          my $frame = $d->{movi}++;                          my $frame = $d->{movi}++;
375                                    
376                          my $len = next_part( '00dc', 0, 1 );                          my $len = next_part( '00dc' );
377                          last unless $len;                          last unless $len;
378                          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;
379                            mkjpg( sprintf("$dump_dir/%03d.jpg", $frame ), x($len) );
380    
381                          my $len = next_part( '01wb', 0, 1 );                          $len = next_part( '01wb', 0, 1 );
382                          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;
383                  };                  };
384    
385          } else {          } else {

Legend:
Removed from v.5  
changed lines
  Added in v.11

  ViewVC Help
Powered by ViewVC 1.1.26