Mercurial > libavcodec.hg
annotate pcx.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 | aebbb6c631b6 |
| children | 997bdf43a4ed |
| rev | line source |
|---|---|
| 6073 | 1 /* |
| 2 * PC Paintbrush PCX (.pcx) image decoder | |
| 3 * Copyright (c) 2007, 2008 Ivo van Poorten | |
| 4 * | |
| 5 * This decoder does not support CGA palettes. I am unable to find samples | |
| 6 * and Netpbm cannot generate them. | |
| 7 * | |
| 8 * This file is part of FFmpeg. | |
| 9 * | |
| 10 * FFmpeg is free software; you can redistribute it and/or | |
| 11 * modify it under the terms of the GNU Lesser General Public | |
| 12 * License as published by the Free Software Foundation; either | |
| 13 * version 2.1 of the License, or (at your option) any later version. | |
| 14 * | |
| 15 * FFmpeg is distributed in the hope that it will be useful, | |
| 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 18 * Lesser General Public License for more details. | |
| 19 * | |
| 20 * You should have received a copy of the GNU Lesser General Public | |
| 21 * License along with FFmpeg; if not, write to the Free Software | |
| 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 23 */ | |
| 24 | |
| 25 #include "avcodec.h" | |
| 26 #include "bytestream.h" | |
| 9428 | 27 #include "get_bits.h" |
| 6073 | 28 |
| 29 typedef struct PCXContext { | |
| 30 AVFrame picture; | |
| 31 } PCXContext; | |
| 32 | |
|
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6244
diff
changeset
|
33 static av_cold int pcx_init(AVCodecContext *avctx) { |
| 6073 | 34 PCXContext *s = avctx->priv_data; |
| 35 | |
| 36 avcodec_get_frame_defaults(&s->picture); | |
| 37 avctx->coded_frame= &s->picture; | |
| 38 | |
| 39 return 0; | |
| 40 } | |
| 41 | |
| 42 /** | |
| 43 * @return advanced src pointer | |
| 44 */ | |
| 6793 | 45 static const uint8_t *pcx_rle_decode(const uint8_t *src, uint8_t *dst, |
| 6073 | 46 unsigned int bytes_per_scanline) { |
| 47 unsigned int i = 0; | |
| 48 unsigned char run, value; | |
| 49 | |
| 50 while (i<bytes_per_scanline) { | |
| 51 run = 1; | |
| 52 value = *src++; | |
| 53 if (value >= 0xc0) { | |
| 54 run = value & 0x3f; | |
| 55 value = *src++; | |
| 56 } | |
| 57 while (i<bytes_per_scanline && run--) | |
| 58 dst[i++] = value; | |
| 59 } | |
| 60 | |
| 61 return src; | |
| 62 } | |
| 63 | |
| 6244 | 64 static void pcx_palette(const uint8_t **src, uint32_t *dst, unsigned int pallen) { |
| 6073 | 65 unsigned int i; |
| 66 | |
| 67 for (i=0; i<pallen; i++) | |
| 68 *dst++ = bytestream_get_be24(src); | |
| 69 memset(dst, 0, (256 - pallen) * sizeof(*dst)); | |
| 70 } | |
| 71 | |
| 72 static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |
|
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
7040
diff
changeset
|
73 AVPacket *avpkt) { |
|
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
7040
diff
changeset
|
74 const uint8_t *buf = avpkt->data; |
|
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
7040
diff
changeset
|
75 int buf_size = avpkt->size; |
| 6073 | 76 PCXContext * const s = avctx->priv_data; |
| 77 AVFrame *picture = data; | |
| 6075 | 78 AVFrame * const p = &s->picture; |
| 6073 | 79 int xmin, ymin, xmax, ymax; |
| 80 unsigned int w, h, bits_per_pixel, bytes_per_line, nplanes, stride, y, x, | |
| 81 bytes_per_scanline; | |
| 6244 | 82 uint8_t *ptr; |
| 83 uint8_t const *bufstart = buf; | |
| 6073 | 84 |
| 85 if (buf[0] != 0x0a || buf[1] > 5 || buf[1] == 1 || buf[2] != 1) { | |
| 86 av_log(avctx, AV_LOG_ERROR, "this is not PCX encoded data\n"); | |
| 87 return -1; | |
| 88 } | |
| 89 | |
| 90 xmin = AV_RL16(buf+ 4); | |
| 91 ymin = AV_RL16(buf+ 6); | |
| 92 xmax = AV_RL16(buf+ 8); | |
| 93 ymax = AV_RL16(buf+10); | |
| 94 | |
| 95 if (xmax < xmin || ymax < ymin) { | |
| 96 av_log(avctx, AV_LOG_ERROR, "invalid image dimensions\n"); | |
| 97 return -1; | |
| 98 } | |
| 99 | |
| 100 w = xmax - xmin + 1; | |
| 101 h = ymax - ymin + 1; | |
| 102 | |
| 103 bits_per_pixel = buf[3]; | |
| 104 bytes_per_line = AV_RL16(buf+66); | |
| 105 nplanes = buf[65]; | |
| 106 bytes_per_scanline = nplanes * bytes_per_line; | |
| 107 | |
| 108 if (bytes_per_scanline < w * bits_per_pixel * nplanes / 8) { | |
| 109 av_log(avctx, AV_LOG_ERROR, "PCX data is corrupted\n"); | |
| 110 return -1; | |
| 111 } | |
| 112 | |
| 113 switch ((nplanes<<8) + bits_per_pixel) { | |
| 114 case 0x0308: | |
| 115 avctx->pix_fmt = PIX_FMT_RGB24; | |
| 116 break; | |
| 117 case 0x0108: | |
| 118 case 0x0104: | |
| 119 case 0x0102: | |
| 120 case 0x0101: | |
| 121 case 0x0401: | |
| 122 case 0x0301: | |
| 123 case 0x0201: | |
| 124 avctx->pix_fmt = PIX_FMT_PAL8; | |
| 125 break; | |
| 126 default: | |
| 127 av_log(avctx, AV_LOG_ERROR, "invalid PCX file\n"); | |
| 128 return -1; | |
| 129 } | |
| 130 | |
| 131 buf += 128; | |
| 132 | |
| 133 if (p->data[0]) | |
| 134 avctx->release_buffer(avctx, p); | |
| 135 | |
| 136 if (avcodec_check_dimensions(avctx, w, h)) | |
| 137 return -1; | |
| 138 if (w != avctx->width || h != avctx->height) | |
| 139 avcodec_set_dimensions(avctx, w, h); | |
| 140 if (avctx->get_buffer(avctx, p) < 0) { | |
| 141 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
| 142 return -1; | |
| 143 } | |
| 144 | |
| 145 p->pict_type = FF_I_TYPE; | |
| 146 | |
| 147 ptr = p->data[0]; | |
| 148 stride = p->linesize[0]; | |
| 149 | |
| 150 if (nplanes == 3 && bits_per_pixel == 8) { | |
| 151 uint8_t scanline[bytes_per_scanline]; | |
| 152 | |
| 153 for (y=0; y<h; y++) { | |
| 154 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline); | |
| 155 | |
| 156 for (x=0; x<w; x++) { | |
| 157 ptr[3*x ] = scanline[x ]; | |
| 158 ptr[3*x+1] = scanline[x+ bytes_per_line ]; | |
| 159 ptr[3*x+2] = scanline[x+(bytes_per_line<<1)]; | |
| 160 } | |
| 161 | |
| 162 ptr += stride; | |
| 163 } | |
| 164 | |
| 165 } else if (nplanes == 1 && bits_per_pixel == 8) { | |
| 166 uint8_t scanline[bytes_per_scanline]; | |
| 6244 | 167 const uint8_t *palstart = bufstart + buf_size - 769; |
| 6073 | 168 |
| 169 for (y=0; y<h; y++, ptr+=stride) { | |
| 170 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline); | |
| 171 memcpy(ptr, scanline, w); | |
| 172 } | |
| 173 | |
| 174 if (buf != palstart) { | |
| 175 av_log(avctx, AV_LOG_WARNING, "image data possibly corrupted\n"); | |
| 176 buf = palstart; | |
| 177 } | |
| 178 if (*buf++ != 12) { | |
| 179 av_log(avctx, AV_LOG_ERROR, "expected palette after image data\n"); | |
| 180 return -1; | |
| 181 } | |
| 182 | |
| 183 } else if (nplanes == 1) { /* all packed formats, max. 16 colors */ | |
| 184 uint8_t scanline[bytes_per_scanline]; | |
| 185 GetBitContext s; | |
| 186 | |
| 187 for (y=0; y<h; y++) { | |
| 188 init_get_bits(&s, scanline, bytes_per_scanline<<3); | |
| 189 | |
| 190 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline); | |
| 191 | |
| 192 for (x=0; x<w; x++) | |
| 193 ptr[x] = get_bits(&s, bits_per_pixel); | |
| 194 ptr += stride; | |
| 195 } | |
| 196 | |
| 197 } else { /* planar, 4, 8 or 16 colors */ | |
| 198 uint8_t scanline[bytes_per_scanline]; | |
| 199 int i; | |
| 200 | |
| 201 for (y=0; y<h; y++) { | |
| 202 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline); | |
| 203 | |
| 204 for (x=0; x<w; x++) { | |
| 205 int m = 0x80 >> (x&7), v = 0; | |
| 206 for (i=nplanes - 1; i>=0; i--) { | |
| 207 v <<= 1; | |
| 208 v += !!(scanline[i*bytes_per_line + (x>>3)] & m); | |
| 209 } | |
| 210 ptr[x] = v; | |
| 211 } | |
| 212 ptr += stride; | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 if (nplanes == 1 && bits_per_pixel == 8) { | |
| 217 pcx_palette(&buf, (uint32_t *) p->data[1], 256); | |
| 218 } else if (bits_per_pixel < 8) { | |
| 6244 | 219 const uint8_t *palette = bufstart+16; |
| 6073 | 220 pcx_palette(&palette, (uint32_t *) p->data[1], 16); |
| 221 } | |
| 222 | |
| 223 *picture = s->picture; | |
| 224 *data_size = sizeof(AVFrame); | |
| 225 | |
| 226 return buf - bufstart; | |
| 227 } | |
| 228 | |
|
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6244
diff
changeset
|
229 static av_cold int pcx_end(AVCodecContext *avctx) { |
| 6073 | 230 PCXContext *s = avctx->priv_data; |
| 231 | |
| 232 if(s->picture.data[0]) | |
| 233 avctx->release_buffer(avctx, &s->picture); | |
| 234 | |
| 235 return 0; | |
| 236 } | |
| 237 | |
| 238 AVCodec pcx_decoder = { | |
| 239 "pcx", | |
| 240 CODEC_TYPE_VIDEO, | |
| 241 CODEC_ID_PCX, | |
| 242 sizeof(PCXContext), | |
| 243 pcx_init, | |
| 244 NULL, | |
| 245 pcx_end, | |
| 246 pcx_decode_frame, | |
| 9802 | 247 CODEC_CAP_DR1, |
| 6722 | 248 NULL, |
|
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6793
diff
changeset
|
249 .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), |
| 6073 | 250 }; |
