Mercurial > libavcodec.hg
annotate pcx.c @ 11034:fd5921186064 libavcodec
Make the fast loop filter path work with unavailable left MBs.
This prevents the issue with having to switch between slow and
fast code paths in each row.
0.5% faster loopfilter for cathedral
author | michael |
---|---|
date | Thu, 28 Jan 2010 02:15:25 +0000 |
parents | 2422415a296c |
children | 8a4984c5cacc |
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, |
10351 | 46 unsigned int bytes_per_scanline, int compressed) { |
6073 | 47 unsigned int i = 0; |
48 unsigned char run, value; | |
49 | |
10351 | 50 if (compressed) { |
51 while (i<bytes_per_scanline) { | |
52 run = 1; | |
6073 | 53 value = *src++; |
10351 | 54 if (value >= 0xc0) { |
55 run = value & 0x3f; | |
56 value = *src++; | |
57 } | |
58 while (i<bytes_per_scanline && run--) | |
59 dst[i++] = value; | |
6073 | 60 } |
10351 | 61 } else { |
62 memcpy(dst, src, bytes_per_scanline); | |
63 src += bytes_per_scanline; | |
6073 | 64 } |
65 | |
66 return src; | |
67 } | |
68 | |
6244 | 69 static void pcx_palette(const uint8_t **src, uint32_t *dst, unsigned int pallen) { |
6073 | 70 unsigned int i; |
71 | |
72 for (i=0; i<pallen; i++) | |
73 *dst++ = bytestream_get_be24(src); | |
10455 | 74 if (pallen < 256) |
10456 | 75 memset(dst, 0, (256 - pallen) * sizeof(*dst)); |
6073 | 76 } |
77 | |
78 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
|
79 AVPacket *avpkt) { |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
7040
diff
changeset
|
80 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
7040
diff
changeset
|
81 int buf_size = avpkt->size; |
6073 | 82 PCXContext * const s = avctx->priv_data; |
83 AVFrame *picture = data; | |
6075 | 84 AVFrame * const p = &s->picture; |
10351 | 85 int compressed, xmin, ymin, xmax, ymax; |
6073 | 86 unsigned int w, h, bits_per_pixel, bytes_per_line, nplanes, stride, y, x, |
87 bytes_per_scanline; | |
6244 | 88 uint8_t *ptr; |
89 uint8_t const *bufstart = buf; | |
6073 | 90 |
10351 | 91 if (buf[0] != 0x0a || buf[1] > 5) { |
6073 | 92 av_log(avctx, AV_LOG_ERROR, "this is not PCX encoded data\n"); |
93 return -1; | |
94 } | |
95 | |
10351 | 96 compressed = buf[2]; |
6073 | 97 xmin = AV_RL16(buf+ 4); |
98 ymin = AV_RL16(buf+ 6); | |
99 xmax = AV_RL16(buf+ 8); | |
100 ymax = AV_RL16(buf+10); | |
101 | |
102 if (xmax < xmin || ymax < ymin) { | |
103 av_log(avctx, AV_LOG_ERROR, "invalid image dimensions\n"); | |
104 return -1; | |
105 } | |
106 | |
107 w = xmax - xmin + 1; | |
108 h = ymax - ymin + 1; | |
109 | |
110 bits_per_pixel = buf[3]; | |
111 bytes_per_line = AV_RL16(buf+66); | |
112 nplanes = buf[65]; | |
113 bytes_per_scanline = nplanes * bytes_per_line; | |
114 | |
115 if (bytes_per_scanline < w * bits_per_pixel * nplanes / 8) { | |
116 av_log(avctx, AV_LOG_ERROR, "PCX data is corrupted\n"); | |
117 return -1; | |
118 } | |
119 | |
120 switch ((nplanes<<8) + bits_per_pixel) { | |
121 case 0x0308: | |
122 avctx->pix_fmt = PIX_FMT_RGB24; | |
123 break; | |
124 case 0x0108: | |
125 case 0x0104: | |
126 case 0x0102: | |
127 case 0x0101: | |
128 case 0x0401: | |
129 case 0x0301: | |
130 case 0x0201: | |
131 avctx->pix_fmt = PIX_FMT_PAL8; | |
132 break; | |
133 default: | |
134 av_log(avctx, AV_LOG_ERROR, "invalid PCX file\n"); | |
135 return -1; | |
136 } | |
137 | |
138 buf += 128; | |
139 | |
140 if (p->data[0]) | |
141 avctx->release_buffer(avctx, p); | |
142 | |
143 if (avcodec_check_dimensions(avctx, w, h)) | |
144 return -1; | |
145 if (w != avctx->width || h != avctx->height) | |
146 avcodec_set_dimensions(avctx, w, h); | |
147 if (avctx->get_buffer(avctx, p) < 0) { | |
148 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
149 return -1; | |
150 } | |
151 | |
152 p->pict_type = FF_I_TYPE; | |
153 | |
154 ptr = p->data[0]; | |
155 stride = p->linesize[0]; | |
156 | |
157 if (nplanes == 3 && bits_per_pixel == 8) { | |
158 uint8_t scanline[bytes_per_scanline]; | |
159 | |
160 for (y=0; y<h; y++) { | |
10351 | 161 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline, compressed); |
6073 | 162 |
163 for (x=0; x<w; x++) { | |
164 ptr[3*x ] = scanline[x ]; | |
165 ptr[3*x+1] = scanline[x+ bytes_per_line ]; | |
166 ptr[3*x+2] = scanline[x+(bytes_per_line<<1)]; | |
167 } | |
168 | |
169 ptr += stride; | |
170 } | |
171 | |
172 } else if (nplanes == 1 && bits_per_pixel == 8) { | |
173 uint8_t scanline[bytes_per_scanline]; | |
6244 | 174 const uint8_t *palstart = bufstart + buf_size - 769; |
6073 | 175 |
176 for (y=0; y<h; y++, ptr+=stride) { | |
10351 | 177 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline, compressed); |
6073 | 178 memcpy(ptr, scanline, w); |
179 } | |
180 | |
181 if (buf != palstart) { | |
182 av_log(avctx, AV_LOG_WARNING, "image data possibly corrupted\n"); | |
183 buf = palstart; | |
184 } | |
185 if (*buf++ != 12) { | |
186 av_log(avctx, AV_LOG_ERROR, "expected palette after image data\n"); | |
187 return -1; | |
188 } | |
189 | |
190 } else if (nplanes == 1) { /* all packed formats, max. 16 colors */ | |
191 uint8_t scanline[bytes_per_scanline]; | |
192 GetBitContext s; | |
193 | |
194 for (y=0; y<h; y++) { | |
195 init_get_bits(&s, scanline, bytes_per_scanline<<3); | |
196 | |
10351 | 197 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline, compressed); |
6073 | 198 |
199 for (x=0; x<w; x++) | |
200 ptr[x] = get_bits(&s, bits_per_pixel); | |
201 ptr += stride; | |
202 } | |
203 | |
204 } else { /* planar, 4, 8 or 16 colors */ | |
205 uint8_t scanline[bytes_per_scanline]; | |
206 int i; | |
207 | |
208 for (y=0; y<h; y++) { | |
10351 | 209 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline, compressed); |
6073 | 210 |
211 for (x=0; x<w; x++) { | |
212 int m = 0x80 >> (x&7), v = 0; | |
213 for (i=nplanes - 1; i>=0; i--) { | |
214 v <<= 1; | |
215 v += !!(scanline[i*bytes_per_line + (x>>3)] & m); | |
216 } | |
217 ptr[x] = v; | |
218 } | |
219 ptr += stride; | |
220 } | |
221 } | |
222 | |
223 if (nplanes == 1 && bits_per_pixel == 8) { | |
224 pcx_palette(&buf, (uint32_t *) p->data[1], 256); | |
225 } else if (bits_per_pixel < 8) { | |
6244 | 226 const uint8_t *palette = bufstart+16; |
6073 | 227 pcx_palette(&palette, (uint32_t *) p->data[1], 16); |
228 } | |
229 | |
230 *picture = s->picture; | |
231 *data_size = sizeof(AVFrame); | |
232 | |
233 return buf - bufstart; | |
234 } | |
235 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6244
diff
changeset
|
236 static av_cold int pcx_end(AVCodecContext *avctx) { |
6073 | 237 PCXContext *s = avctx->priv_data; |
238 | |
239 if(s->picture.data[0]) | |
240 avctx->release_buffer(avctx, &s->picture); | |
241 | |
242 return 0; | |
243 } | |
244 | |
245 AVCodec pcx_decoder = { | |
246 "pcx", | |
247 CODEC_TYPE_VIDEO, | |
248 CODEC_ID_PCX, | |
249 sizeof(PCXContext), | |
250 pcx_init, | |
251 NULL, | |
252 pcx_end, | |
253 pcx_decode_frame, | |
9802 | 254 CODEC_CAP_DR1, |
6722 | 255 NULL, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6793
diff
changeset
|
256 .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), |
6073 | 257 }; |