Mercurial > libavcodec.hg
annotate pcx.c @ 12483:0159a19bfff7 libavcodec
aacdec: Rework channel mapping compatibility hacks.
For a PCE based configuration map the channels solely based on tags.
For an indexed configuration map the channels solely based on position.
This works with all known exotic samples including al17, elem_id0, bad_concat,
and lfe_is_sce.
author | alexc |
---|---|
date | Fri, 10 Sep 2010 18:01:48 +0000 |
parents | ffb3668ff7af |
children |
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 | |
12372
914f484bb476
Remove use of the deprecated function avcodec_check_dimensions(), use
stefano
parents:
11962
diff
changeset
|
25 #include "libavcore/imgutils.h" |
6073 | 26 #include "avcodec.h" |
27 #include "bytestream.h" | |
9428 | 28 #include "get_bits.h" |
6073 | 29 |
30 typedef struct PCXContext { | |
31 AVFrame picture; | |
32 } PCXContext; | |
33 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6244
diff
changeset
|
34 static av_cold int pcx_init(AVCodecContext *avctx) { |
6073 | 35 PCXContext *s = avctx->priv_data; |
36 | |
37 avcodec_get_frame_defaults(&s->picture); | |
38 avctx->coded_frame= &s->picture; | |
39 | |
40 return 0; | |
41 } | |
42 | |
43 /** | |
44 * @return advanced src pointer | |
45 */ | |
6793 | 46 static const uint8_t *pcx_rle_decode(const uint8_t *src, uint8_t *dst, |
10351 | 47 unsigned int bytes_per_scanline, int compressed) { |
6073 | 48 unsigned int i = 0; |
49 unsigned char run, value; | |
50 | |
10351 | 51 if (compressed) { |
52 while (i<bytes_per_scanline) { | |
53 run = 1; | |
6073 | 54 value = *src++; |
10351 | 55 if (value >= 0xc0) { |
56 run = value & 0x3f; | |
57 value = *src++; | |
58 } | |
59 while (i<bytes_per_scanline && run--) | |
60 dst[i++] = value; | |
6073 | 61 } |
10351 | 62 } else { |
63 memcpy(dst, src, bytes_per_scanline); | |
64 src += bytes_per_scanline; | |
6073 | 65 } |
66 | |
67 return src; | |
68 } | |
69 | |
6244 | 70 static void pcx_palette(const uint8_t **src, uint32_t *dst, unsigned int pallen) { |
6073 | 71 unsigned int i; |
72 | |
73 for (i=0; i<pallen; i++) | |
74 *dst++ = bytestream_get_be24(src); | |
10455 | 75 if (pallen < 256) |
10456 | 76 memset(dst, 0, (256 - pallen) * sizeof(*dst)); |
6073 | 77 } |
78 | |
79 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
|
80 AVPacket *avpkt) { |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
7040
diff
changeset
|
81 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
7040
diff
changeset
|
82 int buf_size = avpkt->size; |
6073 | 83 PCXContext * const s = avctx->priv_data; |
84 AVFrame *picture = data; | |
6075 | 85 AVFrame * const p = &s->picture; |
10351 | 86 int compressed, xmin, ymin, xmax, ymax; |
6073 | 87 unsigned int w, h, bits_per_pixel, bytes_per_line, nplanes, stride, y, x, |
88 bytes_per_scanline; | |
6244 | 89 uint8_t *ptr; |
90 uint8_t const *bufstart = buf; | |
11962 | 91 uint8_t *scanline; |
92 int ret = -1; | |
6073 | 93 |
10351 | 94 if (buf[0] != 0x0a || buf[1] > 5) { |
6073 | 95 av_log(avctx, AV_LOG_ERROR, "this is not PCX encoded data\n"); |
96 return -1; | |
97 } | |
98 | |
10351 | 99 compressed = buf[2]; |
6073 | 100 xmin = AV_RL16(buf+ 4); |
101 ymin = AV_RL16(buf+ 6); | |
102 xmax = AV_RL16(buf+ 8); | |
103 ymax = AV_RL16(buf+10); | |
104 | |
105 if (xmax < xmin || ymax < ymin) { | |
106 av_log(avctx, AV_LOG_ERROR, "invalid image dimensions\n"); | |
107 return -1; | |
108 } | |
109 | |
110 w = xmax - xmin + 1; | |
111 h = ymax - ymin + 1; | |
112 | |
113 bits_per_pixel = buf[3]; | |
114 bytes_per_line = AV_RL16(buf+66); | |
115 nplanes = buf[65]; | |
116 bytes_per_scanline = nplanes * bytes_per_line; | |
117 | |
118 if (bytes_per_scanline < w * bits_per_pixel * nplanes / 8) { | |
119 av_log(avctx, AV_LOG_ERROR, "PCX data is corrupted\n"); | |
120 return -1; | |
121 } | |
122 | |
123 switch ((nplanes<<8) + bits_per_pixel) { | |
124 case 0x0308: | |
125 avctx->pix_fmt = PIX_FMT_RGB24; | |
126 break; | |
127 case 0x0108: | |
128 case 0x0104: | |
129 case 0x0102: | |
130 case 0x0101: | |
131 case 0x0401: | |
132 case 0x0301: | |
133 case 0x0201: | |
134 avctx->pix_fmt = PIX_FMT_PAL8; | |
135 break; | |
136 default: | |
137 av_log(avctx, AV_LOG_ERROR, "invalid PCX file\n"); | |
138 return -1; | |
139 } | |
140 | |
141 buf += 128; | |
142 | |
143 if (p->data[0]) | |
144 avctx->release_buffer(avctx, p); | |
145 | |
12462
ffb3668ff7af
Use new imgutils.h API names, fix deprecation warnings.
stefano
parents:
12372
diff
changeset
|
146 if (av_image_check_size(w, h, 0, avctx)) |
6073 | 147 return -1; |
148 if (w != avctx->width || h != avctx->height) | |
149 avcodec_set_dimensions(avctx, w, h); | |
150 if (avctx->get_buffer(avctx, p) < 0) { | |
151 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
152 return -1; | |
153 } | |
154 | |
155 p->pict_type = FF_I_TYPE; | |
156 | |
157 ptr = p->data[0]; | |
158 stride = p->linesize[0]; | |
159 | |
11962 | 160 scanline = av_malloc(bytes_per_scanline); |
161 if (!scanline) | |
162 return AVERROR(ENOMEM); | |
163 | |
6073 | 164 if (nplanes == 3 && bits_per_pixel == 8) { |
165 for (y=0; y<h; y++) { | |
10351 | 166 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline, compressed); |
6073 | 167 |
168 for (x=0; x<w; x++) { | |
169 ptr[3*x ] = scanline[x ]; | |
170 ptr[3*x+1] = scanline[x+ bytes_per_line ]; | |
171 ptr[3*x+2] = scanline[x+(bytes_per_line<<1)]; | |
172 } | |
173 | |
174 ptr += stride; | |
175 } | |
176 | |
177 } else if (nplanes == 1 && bits_per_pixel == 8) { | |
6244 | 178 const uint8_t *palstart = bufstart + buf_size - 769; |
6073 | 179 |
180 for (y=0; y<h; y++, ptr+=stride) { | |
10351 | 181 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline, compressed); |
6073 | 182 memcpy(ptr, scanline, w); |
183 } | |
184 | |
185 if (buf != palstart) { | |
186 av_log(avctx, AV_LOG_WARNING, "image data possibly corrupted\n"); | |
187 buf = palstart; | |
188 } | |
189 if (*buf++ != 12) { | |
190 av_log(avctx, AV_LOG_ERROR, "expected palette after image data\n"); | |
11962 | 191 goto end; |
6073 | 192 } |
193 | |
194 } else if (nplanes == 1) { /* all packed formats, max. 16 colors */ | |
195 GetBitContext s; | |
196 | |
197 for (y=0; y<h; y++) { | |
198 init_get_bits(&s, scanline, bytes_per_scanline<<3); | |
199 | |
10351 | 200 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline, compressed); |
6073 | 201 |
202 for (x=0; x<w; x++) | |
203 ptr[x] = get_bits(&s, bits_per_pixel); | |
204 ptr += stride; | |
205 } | |
206 | |
207 } else { /* planar, 4, 8 or 16 colors */ | |
208 int i; | |
209 | |
210 for (y=0; y<h; y++) { | |
10351 | 211 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline, compressed); |
6073 | 212 |
213 for (x=0; x<w; x++) { | |
214 int m = 0x80 >> (x&7), v = 0; | |
215 for (i=nplanes - 1; i>=0; i--) { | |
216 v <<= 1; | |
217 v += !!(scanline[i*bytes_per_line + (x>>3)] & m); | |
218 } | |
219 ptr[x] = v; | |
220 } | |
221 ptr += stride; | |
222 } | |
223 } | |
224 | |
225 if (nplanes == 1 && bits_per_pixel == 8) { | |
226 pcx_palette(&buf, (uint32_t *) p->data[1], 256); | |
227 } else if (bits_per_pixel < 8) { | |
6244 | 228 const uint8_t *palette = bufstart+16; |
6073 | 229 pcx_palette(&palette, (uint32_t *) p->data[1], 16); |
230 } | |
231 | |
232 *picture = s->picture; | |
233 *data_size = sizeof(AVFrame); | |
234 | |
11962 | 235 ret = buf - bufstart; |
236 end: | |
237 av_free(scanline); | |
238 return ret; | |
6073 | 239 } |
240 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6244
diff
changeset
|
241 static av_cold int pcx_end(AVCodecContext *avctx) { |
6073 | 242 PCXContext *s = avctx->priv_data; |
243 | |
244 if(s->picture.data[0]) | |
245 avctx->release_buffer(avctx, &s->picture); | |
246 | |
247 return 0; | |
248 } | |
249 | |
250 AVCodec pcx_decoder = { | |
251 "pcx", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10456
diff
changeset
|
252 AVMEDIA_TYPE_VIDEO, |
6073 | 253 CODEC_ID_PCX, |
254 sizeof(PCXContext), | |
255 pcx_init, | |
256 NULL, | |
257 pcx_end, | |
258 pcx_decode_frame, | |
9802 | 259 CODEC_CAP_DR1, |
6722 | 260 NULL, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6793
diff
changeset
|
261 .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), |
6073 | 262 }; |