Mercurial > libavcodec.hg
annotate bmp.c @ 6920:d02af7474bff libavcodec
Prevent 128*1<<trellis from becoming 0 and creating 0 sized arrays.
fixes CID84 RUN2
CID85 RUN2
CID86 RUN2
CID87 RUN2
CID88 RUN2
CID89 RUN2
CID90 RUN2
CID91 RUN2
CID92 RUN2
CID93 RUN2
CID94 RUN2
CID95 RUN2
CID96 RUN2
CID97 RUN2
CID98 RUN2
CID99 RUN2
CID100 RUN2
CID101 RUN2
CID102 RUN2
CID103 RUN2
CID104 RUN2
CID105 RUN2
CID106 RUN2
author | michael |
---|---|
date | Wed, 28 May 2008 11:59:41 +0000 |
parents | 6eeb19edcee3 |
children | e943e1409077 |
rev | line source |
---|---|
2949 | 1 /* |
4415
f792b146869b
Segregate code common to BMP decoder and future encoder
diego
parents:
4394
diff
changeset
|
2 * BMP image format decoder |
2949 | 3 * Copyright (c) 2005 Mans Rullgard |
4 * | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
2949 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
2949 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
2949 | 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 | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2967
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
2949 | 20 */ |
21 | |
22 #include "avcodec.h" | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
23 #include "bytestream.h" |
4415
f792b146869b
Segregate code common to BMP decoder and future encoder
diego
parents:
4394
diff
changeset
|
24 #include "bmp.h" |
2949 | 25 |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6265
diff
changeset
|
26 static av_cold int bmp_decode_init(AVCodecContext *avctx){ |
2949 | 27 BMPContext *s = avctx->priv_data; |
28 | |
29 avcodec_get_frame_defaults((AVFrame*)&s->picture); | |
30 avctx->coded_frame = (AVFrame*)&s->picture; | |
31 | |
32 return 0; | |
33 } | |
34 | |
2967 | 35 static int bmp_decode_frame(AVCodecContext *avctx, |
2949 | 36 void *data, int *data_size, |
6265 | 37 const uint8_t *buf, int buf_size) |
2949 | 38 { |
39 BMPContext *s = avctx->priv_data; | |
40 AVFrame *picture = data; | |
41 AVFrame *p = &s->picture; | |
42 unsigned int fsize, hsize; | |
43 int width, height; | |
44 unsigned int depth; | |
4393 | 45 BiCompression comp; |
2949 | 46 unsigned int ihsize; |
47 int i, j, n, linesize; | |
48 uint32_t rgb[3]; | |
49 uint8_t *ptr; | |
50 int dsize; | |
6265 | 51 const uint8_t *buf0 = buf; |
2949 | 52 |
53 if(buf_size < 14){ | |
54 av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size); | |
55 return -1; | |
56 } | |
57 | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
58 if(bytestream_get_byte(&buf) != 'B' || |
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
59 bytestream_get_byte(&buf) != 'M') { |
2949 | 60 av_log(avctx, AV_LOG_ERROR, "bad magic number\n"); |
61 return -1; | |
62 } | |
63 | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
64 fsize = bytestream_get_le32(&buf); |
2949 | 65 if(buf_size < fsize){ |
66 av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n", | |
67 buf_size, fsize); | |
68 return -1; | |
69 } | |
70 | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
71 buf += 2; /* reserved1 */ |
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
72 buf += 2; /* reserved2 */ |
2949 | 73 |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
74 hsize = bytestream_get_le32(&buf); /* header size */ |
2949 | 75 if(fsize <= hsize){ |
76 av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n", | |
77 fsize, hsize); | |
78 return -1; | |
79 } | |
80 | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
81 ihsize = bytestream_get_le32(&buf); /* more header size */ |
2949 | 82 if(ihsize + 14 > hsize){ |
83 av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize); | |
84 return -1; | |
85 } | |
86 | |
6594 | 87 if (ihsize == 40) { |
6595 | 88 width = bytestream_get_le32(&buf); |
89 height = bytestream_get_le32(&buf); | |
6594 | 90 } else if (ihsize == 12) { |
91 width = bytestream_get_le16(&buf); | |
92 height = bytestream_get_le16(&buf); | |
93 } else { | |
94 av_log(avctx, AV_LOG_ERROR, "unsupported BMP file, patch welcome"); | |
95 return -1; | |
96 } | |
2949 | 97 |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
98 if(bytestream_get_le16(&buf) != 1){ /* planes */ |
2949 | 99 av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n"); |
100 return -1; | |
101 } | |
102 | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
103 depth = bytestream_get_le16(&buf); |
2949 | 104 |
6594 | 105 if(ihsize == 40) |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
106 comp = bytestream_get_le32(&buf); |
2949 | 107 else |
108 comp = BMP_RGB; | |
109 | |
110 if(comp != BMP_RGB && comp != BMP_BITFIELDS){ | |
111 av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp); | |
112 return -1; | |
113 } | |
114 | |
115 if(comp == BMP_BITFIELDS){ | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
116 buf += 20; |
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
117 rgb[0] = bytestream_get_le32(&buf); |
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
118 rgb[1] = bytestream_get_le32(&buf); |
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
119 rgb[2] = bytestream_get_le32(&buf); |
2949 | 120 } |
121 | |
122 avctx->width = width; | |
123 avctx->height = height > 0? height: -height; | |
124 | |
125 avctx->pix_fmt = PIX_FMT_NONE; | |
126 | |
127 switch(depth){ | |
128 case 32: | |
129 if(comp == BMP_BITFIELDS){ | |
130 rgb[0] = (rgb[0] >> 15) & 3; | |
131 rgb[1] = (rgb[1] >> 15) & 3; | |
132 rgb[2] = (rgb[2] >> 15) & 3; | |
133 | |
134 if(rgb[0] + rgb[1] + rgb[2] != 3 || | |
135 rgb[0] == rgb[1] || rgb[0] == rgb[2] || rgb[1] == rgb[2]){ | |
136 break; | |
137 } | |
138 } else { | |
139 rgb[0] = 2; | |
140 rgb[1] = 1; | |
141 rgb[2] = 0; | |
142 } | |
143 | |
144 avctx->pix_fmt = PIX_FMT_BGR24; | |
145 break; | |
146 case 24: | |
147 avctx->pix_fmt = PIX_FMT_BGR24; | |
148 break; | |
149 case 16: | |
150 if(comp == BMP_RGB) | |
151 avctx->pix_fmt = PIX_FMT_RGB555; | |
152 break; | |
153 default: | |
154 av_log(avctx, AV_LOG_ERROR, "depth %d not supported\n", depth); | |
155 return -1; | |
156 } | |
157 | |
158 if(avctx->pix_fmt == PIX_FMT_NONE){ | |
159 av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n"); | |
160 return -1; | |
161 } | |
162 | |
4432
a848b652f0ac
Fix segfault in bmp decoder. Patch by Michel Bardiaux mbardiaux mediaxim dot be.
takis
parents:
4415
diff
changeset
|
163 if(p->data[0]) |
a848b652f0ac
Fix segfault in bmp decoder. Patch by Michel Bardiaux mbardiaux mediaxim dot be.
takis
parents:
4415
diff
changeset
|
164 avctx->release_buffer(avctx, p); |
a848b652f0ac
Fix segfault in bmp decoder. Patch by Michel Bardiaux mbardiaux mediaxim dot be.
takis
parents:
4415
diff
changeset
|
165 |
2949 | 166 p->reference = 0; |
167 if(avctx->get_buffer(avctx, p) < 0){ | |
168 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
169 return -1; | |
170 } | |
171 p->pict_type = FF_I_TYPE; | |
172 p->key_frame = 1; | |
173 | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
174 buf = buf0 + hsize; |
2949 | 175 dsize = buf_size - hsize; |
176 | |
4109 | 177 /* Line size in file multiple of 4 */ |
178 n = (avctx->width * (depth / 8) + 3) & ~3; | |
2949 | 179 |
180 if(n * avctx->height > dsize){ | |
181 av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n", | |
182 dsize, n * avctx->height); | |
183 return -1; | |
184 } | |
185 | |
186 if(height > 0){ | |
187 ptr = p->data[0] + (avctx->height - 1) * p->linesize[0]; | |
188 linesize = -p->linesize[0]; | |
189 } else { | |
190 ptr = p->data[0]; | |
191 linesize = p->linesize[0]; | |
192 } | |
193 | |
194 switch(depth){ | |
195 case 24: | |
196 for(i = 0; i < avctx->height; i++){ | |
4445 | 197 memcpy(ptr, buf, avctx->width*(depth>>3)); |
2949 | 198 buf += n; |
199 ptr += linesize; | |
200 } | |
201 break; | |
202 case 16: | |
203 for(i = 0; i < avctx->height; i++){ | |
6265 | 204 const uint16_t *src = (const uint16_t *) buf; |
2949 | 205 uint16_t *dst = (uint16_t *) ptr; |
206 | |
207 for(j = 0; j < avctx->width; j++) | |
208 *dst++ = le2me_16(*src++); | |
209 | |
210 buf += n; | |
211 ptr += linesize; | |
212 } | |
213 break; | |
214 case 32: | |
215 for(i = 0; i < avctx->height; i++){ | |
6265 | 216 const uint8_t *src = buf; |
2949 | 217 uint8_t *dst = ptr; |
218 | |
219 for(j = 0; j < avctx->width; j++){ | |
220 dst[0] = src[rgb[2]]; | |
221 dst[1] = src[rgb[1]]; | |
222 dst[2] = src[rgb[0]]; | |
223 dst += 3; | |
224 src += 4; | |
225 } | |
226 | |
227 buf += n; | |
228 ptr += linesize; | |
229 } | |
230 break; | |
231 default: | |
232 av_log(avctx, AV_LOG_ERROR, "BMP decoder is broken\n"); | |
233 return -1; | |
234 } | |
235 | |
236 *picture = s->picture; | |
237 *data_size = sizeof(AVPicture); | |
238 | |
239 return buf_size; | |
240 } | |
241 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6265
diff
changeset
|
242 static av_cold int bmp_decode_end(AVCodecContext *avctx) |
4455
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
243 { |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
244 BMPContext* c = avctx->priv_data; |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
245 |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
246 if (c->picture.data[0]) |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
247 avctx->release_buffer(avctx, &c->picture); |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
248 |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
249 return 0; |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
250 } |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
251 |
2949 | 252 AVCodec bmp_decoder = { |
253 "bmp", | |
254 CODEC_TYPE_VIDEO, | |
255 CODEC_ID_BMP, | |
256 sizeof(BMPContext), | |
257 bmp_decode_init, | |
258 NULL, | |
4455
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
259 bmp_decode_end, |
6722 | 260 bmp_decode_frame, |
261 .long_name = "BMP image", | |
2949 | 262 }; |