Mercurial > libavcodec.hg
annotate bmp.c @ 3198:6b9f0c4fbdbe libavcodec
First part of a series of speed-enchancing patches.
This one sets up a snow.h and makes snow use the dsputil function pointer
framework to access the three functions that will be implemented in asm
in the other parts of the patchset.
Patch by Robert Edele < yartrebo AH earthlink POIS net>
Original thread:
Subject: [Ffmpeg-devel] [PATCH] Snow mmx+sse2 asm optimizations
Date: Sun, 05 Feb 2006 12:47:14 -0500
author | gpoirier |
---|---|
date | Thu, 16 Mar 2006 19:18:18 +0000 |
parents | 0b546eab515d |
children | c8c591fe26f8 |
rev | line source |
---|---|
2949 | 1 /* |
2 * BMP image format | |
3 * Copyright (c) 2005 Mans Rullgard | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2967
diff
changeset
|
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
2949 | 18 */ |
19 | |
20 #include "avcodec.h" | |
21 #include "bitstream.h" | |
22 #include "bswap.h" | |
23 | |
24 typedef struct BMPContext { | |
25 AVFrame picture; | |
26 } BMPContext; | |
27 | |
28 #define BMP_RGB 0 | |
29 #define BMP_RLE8 1 | |
30 #define BMP_RLE4 2 | |
31 #define BMP_BITFIELDS 3 | |
32 | |
33 #define read16(bits) bswap_16(get_bits(bits, 16)) | |
34 #define read32(bits) bswap_32(get_bits_long(bits, 32)) | |
35 | |
36 static int bmp_decode_init(AVCodecContext *avctx){ | |
37 BMPContext *s = avctx->priv_data; | |
38 | |
39 avcodec_get_frame_defaults((AVFrame*)&s->picture); | |
40 avctx->coded_frame = (AVFrame*)&s->picture; | |
41 | |
42 return 0; | |
43 } | |
44 | |
2967 | 45 static int bmp_decode_frame(AVCodecContext *avctx, |
2949 | 46 void *data, int *data_size, |
47 uint8_t *buf, int buf_size) | |
48 { | |
49 BMPContext *s = avctx->priv_data; | |
50 AVFrame *picture = data; | |
51 AVFrame *p = &s->picture; | |
52 GetBitContext bits; | |
53 unsigned int fsize, hsize; | |
54 int width, height; | |
55 unsigned int depth; | |
56 unsigned int comp; | |
57 unsigned int ihsize; | |
58 int i, j, n, linesize; | |
59 uint32_t rgb[3]; | |
60 uint8_t *ptr; | |
61 int dsize; | |
62 | |
63 if(buf_size < 14){ | |
64 av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size); | |
65 return -1; | |
66 } | |
67 | |
68 init_get_bits(&bits, buf, buf_size); | |
69 | |
70 if(get_bits(&bits, 16) != 0x424d){ /* 'BM' */ | |
71 av_log(avctx, AV_LOG_ERROR, "bad magic number\n"); | |
72 return -1; | |
73 } | |
74 | |
75 fsize = read32(&bits); | |
76 if(buf_size < fsize){ | |
77 av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n", | |
78 buf_size, fsize); | |
79 return -1; | |
80 } | |
81 | |
82 skip_bits(&bits, 16); /* reserved1 */ | |
83 skip_bits(&bits, 16); /* reserved2 */ | |
84 | |
85 hsize = read32(&bits); /* header size */ | |
86 if(fsize <= hsize){ | |
87 av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n", | |
88 fsize, hsize); | |
89 return -1; | |
90 } | |
91 | |
92 ihsize = read32(&bits); /* more header size */ | |
93 if(ihsize + 14 > hsize){ | |
94 av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize); | |
95 return -1; | |
96 } | |
97 | |
98 width = read32(&bits); | |
99 height = read32(&bits); | |
100 | |
101 if(read16(&bits) != 1){ /* planes */ | |
102 av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n"); | |
103 return -1; | |
104 } | |
105 | |
106 depth = read16(&bits); | |
107 | |
108 if(ihsize > 16) | |
109 comp = read32(&bits); | |
110 else | |
111 comp = BMP_RGB; | |
112 | |
113 if(comp != BMP_RGB && comp != BMP_BITFIELDS){ | |
114 av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp); | |
115 return -1; | |
116 } | |
117 | |
118 if(comp == BMP_BITFIELDS){ | |
119 skip_bits(&bits, 20 * 8); | |
120 rgb[0] = read32(&bits); | |
121 rgb[1] = read32(&bits); | |
122 rgb[2] = read32(&bits); | |
123 } | |
124 | |
125 avctx->codec_id = CODEC_ID_BMP; | |
126 avctx->width = width; | |
127 avctx->height = height > 0? height: -height; | |
128 | |
129 avctx->pix_fmt = PIX_FMT_NONE; | |
130 | |
131 switch(depth){ | |
132 case 32: | |
133 if(comp == BMP_BITFIELDS){ | |
134 rgb[0] = (rgb[0] >> 15) & 3; | |
135 rgb[1] = (rgb[1] >> 15) & 3; | |
136 rgb[2] = (rgb[2] >> 15) & 3; | |
137 | |
138 if(rgb[0] + rgb[1] + rgb[2] != 3 || | |
139 rgb[0] == rgb[1] || rgb[0] == rgb[2] || rgb[1] == rgb[2]){ | |
140 break; | |
141 } | |
142 } else { | |
143 rgb[0] = 2; | |
144 rgb[1] = 1; | |
145 rgb[2] = 0; | |
146 } | |
147 | |
148 avctx->pix_fmt = PIX_FMT_BGR24; | |
149 break; | |
150 case 24: | |
151 avctx->pix_fmt = PIX_FMT_BGR24; | |
152 break; | |
153 case 16: | |
154 if(comp == BMP_RGB) | |
155 avctx->pix_fmt = PIX_FMT_RGB555; | |
156 break; | |
157 default: | |
158 av_log(avctx, AV_LOG_ERROR, "depth %d not supported\n", depth); | |
159 return -1; | |
160 } | |
161 | |
162 if(avctx->pix_fmt == PIX_FMT_NONE){ | |
163 av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n"); | |
164 return -1; | |
165 } | |
166 | |
167 p->reference = 0; | |
168 if(avctx->get_buffer(avctx, p) < 0){ | |
169 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
170 return -1; | |
171 } | |
172 p->pict_type = FF_I_TYPE; | |
173 p->key_frame = 1; | |
174 | |
175 buf += hsize; | |
176 dsize = buf_size - hsize; | |
177 | |
178 n = avctx->width * (depth / 8); | |
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++){ | |
197 memcpy(ptr, buf, n); | |
198 buf += n; | |
199 ptr += linesize; | |
200 } | |
201 break; | |
202 case 16: | |
203 for(i = 0; i < avctx->height; i++){ | |
204 uint16_t *src = (uint16_t *) buf; | |
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++){ | |
216 uint8_t *src = buf; | |
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 | |
242 AVCodec bmp_decoder = { | |
243 "bmp", | |
244 CODEC_TYPE_VIDEO, | |
245 CODEC_ID_BMP, | |
246 sizeof(BMPContext), | |
247 bmp_decode_init, | |
248 NULL, | |
249 NULL, | |
250 bmp_decode_frame | |
251 }; |