Revision 19
Legend:
- Added
- Removed
- Modified
-
amv.pl
20 20 my $dump = 0; 21 21 my $debug = 0; 22 22 my $dump_dir = '/tmp/dump/'; 23 my $no_jpeg_header = 0; 24 my $jpeg_q = 100; 23 25 24 26 GetOptions( 25 27 "dump!" => \$dump, 26 28 "debug!" => \$debug, 27 29 "dump-dir=s" => \$dump_dir, 30 "no-jpeg-headers!" => \$no_jpeg_header, 28 31 ); 29 32 30 33 my $path = shift @ARGV || die "usage: $0 movie.amv\n"; … … 88 91 hex_dump( $bytes ); 89 92 90 93 if ( $bytes eq 'AMV_END_' ) { 91 warn "> end of file marker AMV_END_\n"; 94 print "> end of file marker AMV_END_\n" if $dump; 92 95 $d->{eof}++; 93 96 return; 94 97 } 95 98 96 99 if ( $format ) { 97 100 my @data = unpack($format, $bytes); 98 warn "## unpacked = ",dump(@data),"\n" if $debug; 101 print "## unpacked = ",dump(@data),"\n" if $debug; 99 102 return @data; 100 103 } else { 101 104 return $bytes; … … 115 118 return $len; 116 119 } 117 120 118 sub huffman { 121 sub quality { 122 my @table = @_; 123 die "quantization matrice needs to have 64 bytes!" if $#table != 63; 119 124 120 # JPEG DHT Segment for YCrCb omitted from MJPG data 121 return 122 "\xFF\xC4\x01\xA2" . 123 "\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00" . 124 "\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x01" . 125 "\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00" . 126 "\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x10\x00" . 127 "\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01\x7D" . 128 "\x01\x02\x03\x00\x04\x11\x05\x12\x21\x31\x41\x06\x13\x51\x61" . 129 "\x07\x22\x71\x14\x32\x81\x91\xA1\x08\x23\x42\xB1\xC1\x15\x52" . 130 "\xD1\xF0\x24\x33\x62\x72\x82\x09\x0A\x16\x17\x18\x19\x1A\x25" . 131 "\x26\x27\x28\x29\x2A\x34\x35\x36\x37\x38\x39\x3A\x43\x44\x45" . 132 "\x46\x47\x48\x49\x4A\x53\x54\x55\x56\x57\x58\x59\x5A\x63\x64" . 133 "\x65\x66\x67\x68\x69\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x83" . 134 "\x84\x85\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96\x97\x98\x99" . 135 "\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xB2\xB3\xB4\xB5\xB6" . 136 "\xB7\xB8\xB9\xBA\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2\xD3" . 137 "\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8" . 138 "\xE9\xEA\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\x11\x00\x02" . 139 "\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04\x00\x01\x02\x77\x00" . 140 "\x01\x02\x03\x11\x04\x05\x21\x31\x06\x12\x41\x51\x07\x61\x71" . 141 "\x13\x22\x32\x81\x08\x14\x42\x91\xA1\xB1\xC1\x09\x23\x33\x52" . 142 "\xF0\x15\x62\x72\xD1\x0A\x16\x24\x34\xE1\x25\xF1\x17\x18\x19" . 143 "\x1A\x26\x27\x28\x29\x2A\x35\x36\x37\x38\x39\x3A\x43\x44\x45" . 144 "\x46\x47\x48\x49\x4A\x53\x54\x55\x56\x57\x58\x59\x5A\x63\x64" . 145 "\x65\x66\x67\x68\x69\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x82" . 146 "\x83\x84\x85\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96\x97\x98" . 147 "\x99\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xB2\xB3\xB4\xB5" . 148 "\xB6\xB7\xB8\xB9\xBA\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2" . 149 "\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xE2\xE3\xE4\xE5\xE6\xE7\xE8" . 150 "\xE9\xEA\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA"; 125 my $in = join('', map { chr($_) } @table ); 126 my $out; 151 127 128 foreach my $t ( @table ) { 129 $t = int( ( $t * $jpeg_q ) / 100 ); 130 $t = 255 if $t > 255; 131 $out .= chr($t); 132 } 133 134 if ( $dump ) { 135 print "## quantization table original\n"; 136 hex_dump( $in ); 137 print "## quantization table for $jpeg_q %\n"; 138 hex_dump( $out ); 139 } 140 141 return $out; 152 142 } 153 143 144 my @subframes; 145 my $frame_nr = 1; 146 147 # how many subframes to join into single frame? 148 my $join_subframes = 0; 149 154 150 sub mkjpg { 155 my ($path,$data) = @_; 156 open(my $fh, '>', $path) || die "can't create $path: $!"; 151 my ($data) = @_; 157 152 158 153 confess "no SOI marker in data" if substr($data,0,2) ne "\xFF\xD8"; 159 $data = substr($data,2); 154 confess "no EOI marker in data" if substr($data,-2,2) ne "\xFF\xD9"; 155 $data = substr($data,2,-2); 160 156 157 if ( $#subframes < ( $join_subframes - 1 ) ) { 158 push @subframes, $data; 159 print "## saved $frame_nr/", $#subframes + 1, " subframe of ", length($data), " bytes\n"; 160 return; 161 } 162 163 my $path = sprintf("$dump_dir/%04d.jpg", $frame_nr++ ); 164 165 open(my $fh, '>', $path) || die "can't create $path: $!"; 166 161 167 my $w = $d->{amvh}->{width} || die "no width?"; 162 168 my $h = $d->{amvh}->{height} || confess "no height?"; 163 169 164 170 my $header = 165 "\xFF\xD8". # Start of Image (SOI) marker 166 #------------------------------------------------------------------ 167 "\xFF\xE0". # JFIF marker 171 # Start of Image (SOI) marker 172 "\xFF\xD8". 173 # JFIF marker 174 "\xFF\xE0". 168 175 pack("nZ5CCCnnCC", 169 176 16, # length 170 'JFIF', # identifier 177 'JFIF', # identifier (JFIF) 171 178 1,1, # version 172 179 0, # units (none) 173 180 1,1, # X,Y density 174 181 0,0, # X,Y thumbnail 175 182 ). 176 #------------------------------------------------------------------ 177 "\xFF\xC0". # Start of frame 183 "\xFF\xFE". 184 "\x00\x3CCREATOR: amv dumper (compat. IJG JPEG v62), quality = 100\n". 185 # quantization table (quaility=100%) 186 "\xFF\xDB". 187 "\x00\x43". 188 # 8 bit values, table 1 189 "\x00". 190 quality( 191 0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E, 192 0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 193 0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 194 0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33, 195 0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 196 0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 197 0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 198 0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 199 ). 200 "\xFF\xDB". 201 "\x00\x43". 202 # 8 bit values, table 1 203 "\x01". 204 quality( 205 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2F, 0x1A, 206 0x1A, 0x2F, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, 207 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 208 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 209 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 210 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 211 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 212 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 213 ). 214 # start of frame 215 "\xFF\xC0". 178 216 pack("ncnncc9", 179 217 17, # len 180 218 8, # sample precision in bits 181 219 $h,$w, # X,Y size 182 220 3, # number of components 183 1,0x21,0, # Component ID, H+V sampling factors, Quantization table number 221 1,0x22,0, # Component ID, H+V sampling factors, Quantization table number 184 222 2,0x11,1, 185 223 3,0x11,1, 186 224 ). 187 #------------------------------------------------------------------ 188 "\xFF\xDB". # Define Quantization table marker 189 "\x00\x84". # len 190 "\x00". # 8 bit values, (byte) table 0 191 "\x10\x0B\x0C\x0E\x0C". 192 "\x0A\x10\x0E\x0D\x0E". 193 "\x12\x11\x10\x13\x18". 194 "\x28\x1A\x18\x16\x16". 195 "\x18\x31\x23\x25\x1D". 196 "\x28\x3A\x33\x3D\x3C". 197 "\x39\x33\x38\x37\x40". 198 "\x48\x5C\x4E\x40\x44". 199 "\x57\x45\x37\x38\x50". 200 "\x6D\x51\x57\x5F\x62". 201 "\x67\x68\x67\x3E\x4D". 202 "\x71\x79\x70\x64\x78". 203 "\x5C\x65\x67\x63". 204 "\x01". # 8 bit values, (byte) table 1 205 "\x11\x12\x12\x18\x15". 206 "\x18\x2F\x1A\x1A\x2F". 207 "\x63\x42\x38\x42\x63". 208 "\x63\x63\x63\x63\x63". 209 "\x63\x63\x63\x63\x63". 210 "\x63\x63\x63\x63\x63". 211 "\x63\x63\x63\x63\x63". 212 "\x63\x63\x63\x63\x63". 213 "\x63\x63\x63\x63\x63". 214 "\x63\x63\x63\x63\x63". 215 "\x63\x63\x63\x63\x63". 216 "\x63\x63\x63\x63\x63". 217 "\x63\x63\x63\x63". 218 #------------------------------------------------------------------ 219 # huffman("\x00"). # 0 DC 220 # huffman("\x01"). # 1 DC 221 # huffman("\x10"). # 0 AC 222 # huffman("\x11"). # 1 AC 223 #------------------------------------------------------------------ 224 225 # Define huffman table (section B.2.4.1) 225 "\xFF\xC4". # Marker 226 "\x00\x1F". # Length (31 bytes) 227 "\x00". # DC, (byte) table 0 228 "\x00\x01\x05\x01\x01". 229 "\x01\x01\x01\x01\x00". 230 "\x00\x00\x00\x00\x00". 231 "\x00\x00\x01\x02\x03". 232 "\x04\x05\x06\x07\x08". 233 "\x09\x0A\x0B". 234 # Define huffman table (section B.2.4.1) 235 "\xFF\xC4". # Marker 236 "\x00\xB5". # Length (181 bytes) 237 "\x10". # AC, (byte) table 0 238 "\x00\x02\x01\x03\x03". 239 "\x02\x04\x03\x05\x05". 240 "\x04\x04\x00\x00\x01". 241 "\x7D\x01\x02\x03\x00". 242 "\x04\x11\x05\x12\x21". 243 "\x31\x41\x06\x13\x51". 244 "\x61\x07\x22\x71\x14". 245 "\x32\x81\x91\xA1\x08". 246 "\x23\x42\xB1\xC1\x15". 247 "\x52\xD1\xF0\x24\x33". 248 "\x62\x72\x82\x09\x0A". 249 "\x16\x17\x18\x19\x1A". 250 "\x25\x26\x27\x28\x29". 251 "\x2A\x34\x35\x36\x37". 252 "\x38\x39\x3A\x43\x44". 253 "\x45\x46\x47\x48\x49". 254 "\x4A\x53\x54\x55\x56". 255 "\x57\x58\x59\x5A\x63". 256 "\x64\x65\x66\x67\x68". 257 "\x69\x6A\x73\x74\x75". 258 "\x76\x77\x78\x79\x7A". 259 "\x83\x84\x85\x86\x87". 260 "\x88\x89\x8A\x92\x93". 261 "\x94\x95\x96\x97\x98". 262 "\x99\x9A\xA2\xA3\xA4". 263 "\xA5\xA6\xA7\xA8\xA9". 264 "\xAA\xB2\xB3\xB4\xB5". 265 "\xB6\xB7\xB8\xB9\xBA". 266 "\xC2\xC3\xC4\xC5\xC6". 267 "\xC7\xC8\xC9\xCA\xD2". 268 "\xD3\xD4\xD5\xD6\xD7". 269 "\xD8\xD9\xDA\xE1\xE2". 270 "\xE3\xE4\xE5\xE6\xE7". 271 "\xE8\xE9\xEA\xF1\xF2". 272 "\xF3\xF4\xF5\xF6\xF7". 273 "\xF8\xF9\xFA". 274 # Define huffman table (section B.2.4.1) 275 "\xFF\xC4". # Marker 276 "\x00\x1F". # Length (31 bytes) 277 "\x01". # DC, (byte) table 1 278 "\x00\x03\x01\x01\x01". 279 "\x01\x01\x01\x01\x01". 280 "\x01\x00\x00\x00\x00". 281 "\x00\x00\x01\x02\x03". 282 "\x04\x05\x06\x07\x08". 283 "\x09\x0A\x0B". 284 # Define huffman table (section B.2.4.1) 285 "\xFF\xC4". # Marker 286 "\x00\xB5". # Length (181 bytes) 287 "\x11". # AC, (byte) table 1 288 "\x00\x02\x01\x02\x04". 289 "\x04\x03\x04\x07\x05". 290 "\x04\x04\x00\x01\x02". 291 "\x77\x00\x01\x02\x03". 292 "\x11\x04\x05\x21\x31". 293 "\x06\x12\x41\x51\x07". 294 "\x61\x71\x13\x22\x32". 295 "\x81\x08\x14\x42\x91". 296 "\xA1\xB1\xC1\x09\x23". 297 "\x33\x52\xF0\x15\x62". 298 "\x72\xD1\x0A\x16\x24". 299 "\x34\xE1\x25\xF1\x17". 300 "\x18\x19\x1A\x26\x27". 301 "\x28\x29\x2A\x35\x36". 302 "\x37\x38\x39\x3A\x43". 303 "\x44\x45\x46\x47\x48". 304 "\x49\x4A\x53\x54\x55". 305 "\x56\x57\x58\x59\x5A". 306 "\x63\x64\x65\x66\x67". 307 "\x68\x69\x6A\x73\x74". 308 "\x75\x76\x77\x78\x79". 309 "\x7A\x82\x83\x84\x85". 310 "\x86\x87\x88\x89\x8A". 311 "\x92\x93\x94\x95\x96". 312 "\x97\x98\x99\x9A\xA2". 313 "\xA3\xA4\xA5\xA6\xA7". 314 "\xA8\xA9\xAA\xB2\xB3". 315 "\xB4\xB5\xB6\xB7\xB8". 316 "\xB9\xBA\xC2\xC3\xC4". 317 "\xC5\xC6\xC7\xC8\xC9". 318 "\xCA\xD2\xD3\xD4\xD5". 319 "\xD6\xD7\xD8\xD9\xDA". 320 "\xE2\xE3\xE4\xE5\xE6". 321 "\xE7\xE8\xE9\xEA\xF2". 322 "\xF3\xF4\xF5\xF6\xF7". 323 "\xF8\xF9\xFA". 324 #------------------------------------------------------------------ 325 "\xFF\xDA". # Start of Scan marker 326 pack("nC11", 327 12, # length 328 3, # number of components 329 1,0x00, # Scan 1: use DC/AC huff tables 0/0 330 2,0x11, # Scan 2: use DC/AC huff tables 1/1 331 3,0x11, # Scan 3: use DC/AC huff tables 1/1 332 0,0x3f, # Ss, Se 333 0, # Ah, Ai (not used) 334 ); 335 #------------------------------------------------------------------ 336 337 $header = 338 # SOI 339 "\xFF\xD8". 340 # JFIF 341 "\xFF\xE0". 342 "\x00\x0e\x41\x56\x49\x31\x00\x00\x00\x00\x00\x00\x00\x00". 343 "\xff\xDD\x00\x04\x00\x00". 344 # quantization table 345 "\xFF\xDB". 346 "\x00\x43\x00\x21\x16\x18". 347 "\x1D\x18\x14\x21\x1D\x1B\x1D\x25". 348 "\x23\x21\x27\x31\x53\x36\x31\x2D". 349 "\x2D\x31\x65\x48\x4c\x3c\x53\x78". 350 "\x6a\x7e\x7c\x76\x6a\x74\x72\x85". 351 "\x95\xbf\xa2\x85\x8d\xb4\x8f\x72". 352 "\x74\xa6\xe2\xa8\xb4\xc5\xcb\xd6". 353 "\xd8\xd6\x80\xa0\xeb\xfb\xe8\xd0". 354 "\xf9\xbf\xd2\xd6\xcd". 355 # quantization table 356 "\xff\xdb". 357 "\x00\x43\x01\x23\x25\x25\x31\x2b\x31". 358 "\x61\x36\x36\x61\xcd\x89\x74\x89". 359 "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd". 360 "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd". 361 "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd". 362 "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd". 363 "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd". 364 "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd". 365 "\xcd\xcd". 366 # Define huffman table (section B.2.4.1) 367 226 "\xFF\xC4". # Marker 368 227 "\x00\x1F". # Length (31 bytes) 369 228 "\x00". # DC luminance, table 0 … … 371 230 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B". 372 231 # Define huffman table (section B.2.4.1) 373 232 "\xFF\xC4". # Marker 374 "\x00\x1F". # Length (31 bytes) 375 "\x01". # DC chrominance, table 1 376 "\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00". 377 "\x00\x00\x00\x00". 378 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B". 379 # Define huffman table (section B.2.4.1) 380 "\xFF\xC4". # Marker 381 233 "\x00\xB5". # Length (181 bytes) 382 234 "\x10". # AC luminance, table 0 383 235 "\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01\x7D". … … 395 247 "\xC6\xC7\xC8\xC9\xCA\xD2\xD3\xD4\xD5\xD6\xD7\xD8". 396 248 "\xD9\xDA\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA". 397 249 "\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA". 250 # Define huffman table (section B.2.4.1) 251 "\xFF\xC4". # Marker 252 "\x00\x1F". # Length (31 bytes) 253 "\x01". # DC chrominance, table 1 254 "\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00". 255 "\x00\x00\x00\x00". 256 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B". 398 257 #/* Define huffman table (section B.2.4.1) */ 399 258 "\xFF\xC4". # Marker 400 259 "\x00\xB5". # Length (181 bytes) … … 415 274 "\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2\xD3\xD4\xD5\xD6". 416 275 "\xD7\xD8\xD9\xDA\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9". 417 276 "\xEA\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA". 418 # start of frame 419 "\xff\xc0". 420 "\x00\x11\x08". 421 pack("nn", $h, $w). 422 "\x03\x01\x21\x00\x02\x11\x01\x03\x11\x01". 423 # 424 "\xff\xda". 425 "\x00\x0c\x03\x01\x00\x02\x11\x03\x11". 426 "\x00\x3f\x00"; 277 # Start of Scan marker 278 "\xFF\xDA". 279 pack("nC10", 280 12, # length 281 3, # number of components 282 1,0x00, # Scan 1: use DC/AC huff tables 0/0 283 2,0x11, # Scan 2: use DC/AC huff tables 1/1 284 3,0x11, # Scan 3: use DC/AC huff tables 1/1 285 0,0x3f, # Ss, Se 286 0, # Ah, Ai (not used) 287 ); 427 288 428 289 if ( $dump ) { 429 warn "## created JPEG header...\n"; 290 print "## created JPEG header...\n"; 430 291 hex_dump( $header, 0 ); 431 292 } 432 293 433 print $fh $header || die "can't write header into $path: $!"; 434 print $fh $data || die "can't write frame into $path: $!"; 294 my $frame = join('', @subframes ) . $data; 295 @subframes = (); 296 297 if ( ! $no_jpeg_header ) { 298 print $fh $header, $frame, "\xFF\xD9" || die "can't write jpeg $path: $!"; 299 } else { 300 print $fh $frame || die "can't write raw jpeg $path: $!"; 301 } 435 302 close $fh || die "can't close $path: $!"; 436 print ">> created $path ", -s $path, " bytes\n"; 303 print ">> created $frame_nr ", $no_jpeg_header ? 'raw' : '', " jpeg $path ", -s $path, " bytes\n"; 437 304 } 438 305 439 306 my ( $riff, $amv ) = x(12, 'Z4x4Z4'); … … 477 344 my $len = next_part( '00dc' ); 478 345 last unless $len; 479 346 printf "<< %s 00dc - frame %d jpeg %d 0x%x bytes\n", $name, $frame, $len, $len; 480 mkjpg( sprintf("$dump_dir/%03d.jpg", $frame ), x($len) ); 347 mkjpg( x($len) ); 481 348 482 349 $len = next_part( '01wb', 0, 1 ); 483 350 printf "<< %s 01wb - frame %d audio %d 0x%x bytes\n", $name, $frame, $len, $len;