Mercurial > libavcodec.hg
annotate faxcompr.c @ 9896:bbefbca72722 libavcodec
Drop code that attempts to decode frames that are prefixed by junk.
Too often it ends up decoding random data into noise without detecting
it (for example after seeking of some MP3 data with oddly often occurring
startcode emulation).
Fixes issue1154.
| author | michael |
|---|---|
| date | Tue, 30 Jun 2009 03:57:27 +0000 |
| parents | 0dce4fe6e6f3 |
| children | cc02e912d20e |
| rev | line source |
|---|---|
| 8466 | 1 /* |
| 2 * CCITT Fax Group 3 and 4 decompression | |
| 3 * Copyright (c) 2008 Konstantin Shishkov | |
| 4 * | |
| 5 * This file is part of FFmpeg. | |
| 6 * | |
| 7 * FFmpeg is free software; you can redistribute it and/or | |
| 8 * modify it under the terms of the GNU Lesser General Public | |
| 9 * License as published by the Free Software Foundation; either | |
| 10 * version 2.1 of the License, or (at your option) any later version. | |
| 11 * | |
| 12 * FFmpeg is distributed in the hope that it will be useful, | |
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 * Lesser General Public License for more details. | |
| 16 * | |
| 17 * You should have received a copy of the GNU Lesser General Public | |
| 18 * License along with FFmpeg; if not, write to the Free Software | |
| 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 */ | |
| 21 | |
| 22 /** | |
| 23 * CCITT Fax Group 3 and 4 decompression | |
|
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8693
diff
changeset
|
24 * @file libavcodec/faxcompr.c |
| 8466 | 25 * @author Konstantin Shishkov |
| 26 */ | |
| 27 #include "avcodec.h" | |
| 9428 | 28 #include "get_bits.h" |
|
9411
4cb7c65fc775
Split bitstream.h, put the bitstream writer stuff in the new file
stefano
parents:
8718
diff
changeset
|
29 #include "put_bits.h" |
| 8466 | 30 #include "faxcompr.h" |
| 31 | |
| 32 #define CCITT_SYMS 104 | |
| 33 | |
| 34 static const uint16_t ccitt_syms[CCITT_SYMS] = { | |
| 35 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, | |
| 36 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, | |
| 37 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, | |
| 38 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, | |
| 39 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, | |
| 40 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, | |
| 41 960, 1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, | |
| 42 1792, 1856, 1920, 1984, 2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496, 2560 | |
| 43 }; | |
| 44 | |
| 45 static const uint8_t ccitt_codes_bits[2][CCITT_SYMS] = | |
| 46 { | |
| 47 { | |
| 48 0x35, 0x07, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, 0x13, 0x14, 0x07, 0x08, 0x08, | |
| 49 0x03, 0x34, 0x35, 0x2A, 0x2B, 0x27, 0x0C, 0x08, 0x17, 0x03, 0x04, 0x28, 0x2B, | |
| 50 0x13, 0x24, 0x18, 0x02, 0x03, 0x1A, 0x1B, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, | |
| 51 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x04, 0x05, 0x0A, 0x0B, 0x52, 0x53, 0x54, | |
| 52 0x55, 0x24, 0x25, 0x58, 0x59, 0x5A, 0x5B, 0x4A, 0x4B, 0x32, 0x33, 0x34, 0x1B, | |
| 53 0x12, 0x17, 0x37, 0x36, 0x37, 0x64, 0x65, 0x68, 0x67, 0xCC, 0xCD, 0xD2, 0xD3, | |
| 54 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0x98, 0x99, 0x9A, 0x18, 0x9B, | |
| 55 0x08, 0x0C, 0x0D, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F | |
| 56 }, | |
| 57 { | |
| 58 0x37, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x03, 0x05, 0x04, 0x04, 0x05, 0x07, | |
| 59 0x04, 0x07, 0x18, 0x17, 0x18, 0x08, 0x67, 0x68, 0x6C, 0x37, 0x28, 0x17, 0x18, | |
| 60 0xCA, 0xCB, 0xCC, 0xCD, 0x68, 0x69, 0x6A, 0x6B, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, | |
| 61 0xD7, 0x6C, 0x6D, 0xDA, 0xDB, 0x54, 0x55, 0x56, 0x57, 0x64, 0x65, 0x52, 0x53, | |
| 62 0x24, 0x37, 0x38, 0x27, 0x28, 0x58, 0x59, 0x2B, 0x2C, 0x5A, 0x66, 0x67, 0x0F, | |
| 63 0xC8, 0xC9, 0x5B, 0x33, 0x34, 0x35, 0x6C, 0x6D, 0x4A, 0x4B, 0x4C, 0x4D, 0x72, | |
| 64 0x73, 0x74, 0x75, 0x76, 0x77, 0x52, 0x53, 0x54, 0x55, 0x5A, 0x5B, 0x64, 0x65, | |
| 65 0x08, 0x0C, 0x0D, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F | |
| 66 } | |
| 67 }; | |
| 68 | |
| 69 static const uint8_t ccitt_codes_lens[2][CCITT_SYMS] = | |
| 70 { | |
| 71 { | |
| 72 8, 6, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, | |
| 73 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | |
| 74 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | |
| 75 8, 8, 8, 8, 5, 5, 6, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, | |
| 76 9, 9, 9, 9, 9, 9, 9, 9, 9, 6, 9, 11, 11, 11, 12, 12, 12, 12, 12, 12, | |
| 77 12, 12, 12, 12 | |
| 78 }, | |
| 79 { | |
| 80 10, 3, 2, 2, 3, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 9, 10, 10, 10, 11, | |
| 81 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, | |
| 82 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, | |
| 83 12, 12, 12, 12, 10, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, | |
| 84 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 11, 11, 12, 12, 12, 12, 12, 12, | |
| 85 12, 12, 12, 12 | |
| 86 } | |
| 87 }; | |
| 88 | |
| 89 static const uint8_t ccitt_group3_2d_bits[11] = { | |
| 90 1, 1, 2, 2, 2, 1, 3, 3, 3, 1, 1 | |
| 91 }; | |
| 92 | |
| 93 static const uint8_t ccitt_group3_2d_lens[11] = { | |
| 94 4, 3, 7, 6, 3, 1, 3, 6, 7, 7, 9 | |
| 95 }; | |
| 96 | |
| 97 static VLC ccitt_vlc[2], ccitt_group3_2d_vlc; | |
| 98 | |
|
8693
18737839ed27
Add missing void keyword to parameterless function declarations.
diego
parents:
8490
diff
changeset
|
99 av_cold void ff_ccitt_unpack_init(void) |
| 8466 | 100 { |
| 101 static VLC_TYPE code_table1[528][2]; | |
| 102 static VLC_TYPE code_table2[648][2]; | |
| 103 int i; | |
| 104 static int initialized = 0; | |
| 105 | |
| 106 if(initialized) | |
| 107 return; | |
| 108 ccitt_vlc[0].table = code_table1; | |
| 109 ccitt_vlc[0].table_allocated = 528; | |
| 110 ccitt_vlc[1].table = code_table2; | |
| 111 ccitt_vlc[1].table_allocated = 648; | |
| 112 for(i = 0; i < 2; i++){ | |
| 113 init_vlc_sparse(&ccitt_vlc[i], 9, CCITT_SYMS, | |
| 114 ccitt_codes_lens[i], 1, 1, | |
| 115 ccitt_codes_bits[i], 1, 1, | |
| 116 ccitt_syms, 2, 2, | |
| 117 INIT_VLC_USE_NEW_STATIC); | |
| 118 } | |
| 119 INIT_VLC_STATIC(&ccitt_group3_2d_vlc, 9, 11, | |
| 120 ccitt_group3_2d_lens, 1, 1, | |
| 121 ccitt_group3_2d_bits, 1, 1, 512); | |
| 122 initialized = 1; | |
| 123 } | |
| 124 | |
| 125 | |
| 126 static int decode_group3_1d_line(AVCodecContext *avctx, GetBitContext *gb, | |
| 8486 | 127 unsigned int pix_left, int *runs, const int *runend) |
| 8466 | 128 { |
| 8486 | 129 int mode = 0; |
| 130 unsigned int run=0; | |
| 8466 | 131 unsigned int t; |
| 132 for(;;){ | |
| 133 t = get_vlc2(gb, ccitt_vlc[mode].table, 9, 2); | |
| 134 run += t; | |
| 135 if(t < 64){ | |
| 136 *runs++ = run; | |
|
8476
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
137 if(runs >= runend){ |
|
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
138 av_log(avctx, AV_LOG_ERROR, "Run overrun\n"); |
|
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
139 return -1; |
|
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
140 } |
| 8486 | 141 if(pix_left <= run){ |
| 142 if(pix_left == run) | |
| 8466 | 143 break; |
| 144 av_log(avctx, AV_LOG_ERROR, "Run went out of bounds\n"); | |
| 145 return -1; | |
| 146 } | |
| 8486 | 147 pix_left -= run; |
| 8466 | 148 run = 0; |
| 149 mode = !mode; | |
| 150 }else if((int)t == -1){ | |
| 151 av_log(avctx, AV_LOG_ERROR, "Incorrect code\n"); | |
| 152 return -1; | |
| 153 } | |
| 154 } | |
| 155 *runs++ = 0; | |
| 156 return 0; | |
| 157 } | |
| 158 | |
| 159 static int decode_group3_2d_line(AVCodecContext *avctx, GetBitContext *gb, | |
| 8487 | 160 unsigned int width, int *runs, const int *runend, const int *ref) |
| 8466 | 161 { |
| 8487 | 162 int mode = 0, saved_run = 0, t; |
| 8466 | 163 int run_off = *ref++; |
| 8487 | 164 unsigned int offs=0, run= 0; |
| 8466 | 165 |
|
8476
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
166 runend--; // for the last written 0 |
|
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
167 |
|
8481
f456c3aebe1c
Get rid of pix_left in the 2d code, it is simpler that way.
michael
parents:
8478
diff
changeset
|
168 while(offs < width){ |
| 8466 | 169 int cmode = get_vlc2(gb, ccitt_group3_2d_vlc.table, 9, 1); |
| 170 if(cmode == -1){ | |
| 171 av_log(avctx, AV_LOG_ERROR, "Incorrect mode VLC\n"); | |
| 172 return -1; | |
| 173 } | |
| 174 if(!cmode){//pass mode | |
| 175 run_off += *ref++; | |
| 176 run = run_off - offs; | |
| 8485 | 177 offs= run_off; |
| 8466 | 178 run_off += *ref++; |
|
8481
f456c3aebe1c
Get rid of pix_left in the 2d code, it is simpler that way.
michael
parents:
8478
diff
changeset
|
179 if(offs > width){ |
| 8466 | 180 av_log(avctx, AV_LOG_ERROR, "Run went out of bounds\n"); |
| 181 return -1; | |
| 182 } | |
| 183 saved_run += run; | |
| 184 }else if(cmode == 1){//horizontal mode | |
| 185 int k; | |
| 186 for(k = 0; k < 2; k++){ | |
| 187 run = 0; | |
| 188 for(;;){ | |
| 189 t = get_vlc2(gb, ccitt_vlc[mode].table, 9, 2); | |
| 190 if(t == -1){ | |
| 191 av_log(avctx, AV_LOG_ERROR, "Incorrect code\n"); | |
| 192 return -1; | |
| 193 } | |
| 194 run += t; | |
| 195 if(t < 64) | |
| 196 break; | |
| 197 } | |
| 198 *runs++ = run + saved_run; | |
|
8476
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
199 if(runs >= runend){ |
|
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
200 av_log(avctx, AV_LOG_ERROR, "Run overrun\n"); |
|
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
201 return -1; |
|
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
202 } |
| 8466 | 203 saved_run = 0; |
|
8481
f456c3aebe1c
Get rid of pix_left in the 2d code, it is simpler that way.
michael
parents:
8478
diff
changeset
|
204 offs += run; |
| 8487 | 205 if(offs > width || run > width){ |
| 8466 | 206 av_log(avctx, AV_LOG_ERROR, "Run went out of bounds\n"); |
| 207 return -1; | |
| 208 } | |
| 209 mode = !mode; | |
| 210 } | |
| 211 }else if(cmode == 9 || cmode == 10){ | |
| 212 av_log(avctx, AV_LOG_ERROR, "Special modes are not supported (yet)\n"); | |
| 213 return -1; | |
| 214 }else{//vertical mode | |
| 215 run = run_off - offs + (cmode - 5); | |
| 8490 | 216 run_off -= *--ref; |
|
8481
f456c3aebe1c
Get rid of pix_left in the 2d code, it is simpler that way.
michael
parents:
8478
diff
changeset
|
217 offs += run; |
| 8488 | 218 if(offs > width || run > width){ |
| 8466 | 219 av_log(avctx, AV_LOG_ERROR, "Run went out of bounds\n"); |
| 220 return -1; | |
| 221 } | |
| 222 *runs++ = run + saved_run; | |
|
8476
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
223 if(runs >= runend){ |
|
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
224 av_log(avctx, AV_LOG_ERROR, "Run overrun\n"); |
|
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
225 return -1; |
|
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
226 } |
| 8466 | 227 saved_run = 0; |
| 228 mode = !mode; | |
| 229 } | |
|
8483
c8113e1e91c0
Move sync line pointers code to the end of the loop, it is simpler that way.
michael
parents:
8482
diff
changeset
|
230 //sync line pointers |
|
c8113e1e91c0
Move sync line pointers code to the end of the loop, it is simpler that way.
michael
parents:
8482
diff
changeset
|
231 while(run_off <= offs){ |
|
c8113e1e91c0
Move sync line pointers code to the end of the loop, it is simpler that way.
michael
parents:
8482
diff
changeset
|
232 run_off += *ref++; |
|
c8113e1e91c0
Move sync line pointers code to the end of the loop, it is simpler that way.
michael
parents:
8482
diff
changeset
|
233 run_off += *ref++; |
|
c8113e1e91c0
Move sync line pointers code to the end of the loop, it is simpler that way.
michael
parents:
8482
diff
changeset
|
234 } |
| 8466 | 235 } |
| 236 *runs++ = saved_run; | |
| 237 *runs++ = 0; | |
| 238 return 0; | |
| 239 } | |
| 240 | |
| 241 static void put_line(uint8_t *dst, int size, int width, const int *runs) | |
| 242 { | |
| 243 PutBitContext pb; | |
| 8469 | 244 int run, mode = ~0, pix_left = width, run_idx = 0; |
| 8466 | 245 |
| 246 init_put_bits(&pb, dst, size*8); | |
| 247 while(pix_left > 0){ | |
| 248 run = runs[run_idx++]; | |
| 8469 | 249 mode = ~mode; |
| 8466 | 250 pix_left -= run; |
| 251 for(; run > 16; run -= 16) | |
| 8469 | 252 put_sbits(&pb, 16, mode); |
| 8470 | 253 if(run) |
| 8471 | 254 put_sbits(&pb, run, mode); |
| 8466 | 255 } |
| 256 } | |
| 257 | |
| 258 static int find_group3_syncmarker(GetBitContext *gb, int srcsize) | |
| 259 { | |
| 8467 | 260 unsigned int state = -1; |
| 261 srcsize -= get_bits_count(gb); | |
| 262 while(srcsize-- > 0){ | |
| 263 state+= state + get_bits1(gb); | |
| 8472 | 264 if((state & 0xFFF) == 1) |
| 8467 | 265 return 0; |
| 8466 | 266 } |
| 8467 | 267 return -1; |
| 8466 | 268 } |
| 269 | |
| 8474 | 270 int ff_ccitt_unpack(AVCodecContext *avctx, |
| 8466 | 271 const uint8_t *src, int srcsize, |
| 8474 | 272 uint8_t *dst, int height, int stride, enum TiffCompr compr) |
| 8466 | 273 { |
| 274 int j; | |
| 275 GetBitContext gb; | |
|
8476
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
276 int *runs, *ref, *runend; |
| 8466 | 277 int ret; |
|
8478
2f7c09bb6bfb
Factorize "avctx->width + 2" out to avoid someone mistakenly changing
michael
parents:
8477
diff
changeset
|
278 int runsize= avctx->width + 2; |
| 8466 | 279 |
|
8478
2f7c09bb6bfb
Factorize "avctx->width + 2" out to avoid someone mistakenly changing
michael
parents:
8477
diff
changeset
|
280 runs = av_malloc(runsize * sizeof(runs[0])); |
|
2f7c09bb6bfb
Factorize "avctx->width + 2" out to avoid someone mistakenly changing
michael
parents:
8477
diff
changeset
|
281 ref = av_malloc(runsize * sizeof(ref[0])); |
| 8466 | 282 ref[0] = avctx->width; |
| 283 ref[1] = 0; | |
| 284 ref[2] = 0; | |
| 285 init_get_bits(&gb, src, srcsize*8); | |
| 286 for(j = 0; j < height; j++){ | |
|
8478
2f7c09bb6bfb
Factorize "avctx->width + 2" out to avoid someone mistakenly changing
michael
parents:
8477
diff
changeset
|
287 runend = runs + runsize; |
| 8474 | 288 if(compr == TIFF_G4){ |
|
8476
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
289 ret = decode_group3_2d_line(avctx, &gb, avctx->width, runs, runend, ref); |
| 8466 | 290 if(ret < 0){ |
| 291 av_free(runs); | |
| 292 av_free(ref); | |
| 293 return -1; | |
| 294 } | |
| 295 }else{ | |
| 296 if(find_group3_syncmarker(&gb, srcsize*8) < 0) | |
| 297 break; | |
| 8474 | 298 if(compr==TIFF_CCITT_RLE || get_bits1(&gb)) |
|
8476
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
299 ret = decode_group3_1d_line(avctx, &gb, avctx->width, runs, runend); |
| 8466 | 300 else |
|
8476
0a0d7c4f2cf3
Close gaping sechole. That is, a series of run=0 allows arbitrary data to
michael
parents:
8475
diff
changeset
|
301 ret = decode_group3_2d_line(avctx, &gb, avctx->width, runs, runend, ref); |
| 8466 | 302 } |
| 303 if(ret < 0){ | |
| 304 put_line(dst, stride, avctx->width, ref); | |
| 305 }else{ | |
| 306 put_line(dst, stride, avctx->width, runs); | |
| 307 FFSWAP(int*, runs, ref); | |
| 308 } | |
| 309 dst += stride; | |
| 310 } | |
| 311 av_free(runs); | |
| 312 av_free(ref); | |
| 313 return 0; | |
| 314 } |
