Mercurial > libavcodec.hg
annotate bmp.c @ 5876:731ee5ad6bde libavcodec
Correct assignment of interlaced_frame; was being set on output frames,
in display order, based on decoding information in decoding order. Now
set properly, immediately upon completion of decode.
Based on original patch from Reinhard Nissl, rnisssl % gmx , de
Original Thread: [FFmpeg-devel] H.264 + PAFF: BBC HD recording shows
extreme interlacing artefacts, Thu, 01 Nov 2007 22:43:09
author | heydowns |
---|---|
date | Mon, 05 Nov 2007 18:16:42 +0000 |
parents | de0e893ef264 |
children | abe584ca935c |
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 |
26 static int bmp_decode_init(AVCodecContext *avctx){ | |
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, |
37 uint8_t *buf, int buf_size) | |
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; | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
51 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 | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
87 width = bytestream_get_le32(&buf); |
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
88 height = bytestream_get_le32(&buf); |
2949 | 89 |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
90 if(bytestream_get_le16(&buf) != 1){ /* planes */ |
2949 | 91 av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n"); |
92 return -1; | |
93 } | |
94 | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
95 depth = bytestream_get_le16(&buf); |
2949 | 96 |
97 if(ihsize > 16) | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
98 comp = bytestream_get_le32(&buf); |
2949 | 99 else |
100 comp = BMP_RGB; | |
101 | |
102 if(comp != BMP_RGB && comp != BMP_BITFIELDS){ | |
103 av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp); | |
104 return -1; | |
105 } | |
106 | |
107 if(comp == BMP_BITFIELDS){ | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
108 buf += 20; |
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
109 rgb[0] = bytestream_get_le32(&buf); |
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
110 rgb[1] = bytestream_get_le32(&buf); |
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
111 rgb[2] = bytestream_get_le32(&buf); |
2949 | 112 } |
113 | |
114 avctx->width = width; | |
115 avctx->height = height > 0? height: -height; | |
116 | |
117 avctx->pix_fmt = PIX_FMT_NONE; | |
118 | |
119 switch(depth){ | |
120 case 32: | |
121 if(comp == BMP_BITFIELDS){ | |
122 rgb[0] = (rgb[0] >> 15) & 3; | |
123 rgb[1] = (rgb[1] >> 15) & 3; | |
124 rgb[2] = (rgb[2] >> 15) & 3; | |
125 | |
126 if(rgb[0] + rgb[1] + rgb[2] != 3 || | |
127 rgb[0] == rgb[1] || rgb[0] == rgb[2] || rgb[1] == rgb[2]){ | |
128 break; | |
129 } | |
130 } else { | |
131 rgb[0] = 2; | |
132 rgb[1] = 1; | |
133 rgb[2] = 0; | |
134 } | |
135 | |
136 avctx->pix_fmt = PIX_FMT_BGR24; | |
137 break; | |
138 case 24: | |
139 avctx->pix_fmt = PIX_FMT_BGR24; | |
140 break; | |
141 case 16: | |
142 if(comp == BMP_RGB) | |
143 avctx->pix_fmt = PIX_FMT_RGB555; | |
144 break; | |
145 default: | |
146 av_log(avctx, AV_LOG_ERROR, "depth %d not supported\n", depth); | |
147 return -1; | |
148 } | |
149 | |
150 if(avctx->pix_fmt == PIX_FMT_NONE){ | |
151 av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n"); | |
152 return -1; | |
153 } | |
154 | |
4432
a848b652f0ac
Fix segfault in bmp decoder. Patch by Michel Bardiaux mbardiaux mediaxim dot be.
takis
parents:
4415
diff
changeset
|
155 if(p->data[0]) |
a848b652f0ac
Fix segfault in bmp decoder. Patch by Michel Bardiaux mbardiaux mediaxim dot be.
takis
parents:
4415
diff
changeset
|
156 avctx->release_buffer(avctx, p); |
a848b652f0ac
Fix segfault in bmp decoder. Patch by Michel Bardiaux mbardiaux mediaxim dot be.
takis
parents:
4415
diff
changeset
|
157 |
2949 | 158 p->reference = 0; |
159 if(avctx->get_buffer(avctx, p) < 0){ | |
160 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
161 return -1; | |
162 } | |
163 p->pict_type = FF_I_TYPE; | |
164 p->key_frame = 1; | |
165 | |
4439
3af19e140d67
Make BMP decoder use bytestream. Patch by Michel Bardiaux
takis
parents:
4432
diff
changeset
|
166 buf = buf0 + hsize; |
2949 | 167 dsize = buf_size - hsize; |
168 | |
4109 | 169 /* Line size in file multiple of 4 */ |
170 n = (avctx->width * (depth / 8) + 3) & ~3; | |
2949 | 171 |
172 if(n * avctx->height > dsize){ | |
173 av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n", | |
174 dsize, n * avctx->height); | |
175 return -1; | |
176 } | |
177 | |
178 if(height > 0){ | |
179 ptr = p->data[0] + (avctx->height - 1) * p->linesize[0]; | |
180 linesize = -p->linesize[0]; | |
181 } else { | |
182 ptr = p->data[0]; | |
183 linesize = p->linesize[0]; | |
184 } | |
185 | |
186 switch(depth){ | |
187 case 24: | |
188 for(i = 0; i < avctx->height; i++){ | |
4445 | 189 memcpy(ptr, buf, avctx->width*(depth>>3)); |
2949 | 190 buf += n; |
191 ptr += linesize; | |
192 } | |
193 break; | |
194 case 16: | |
195 for(i = 0; i < avctx->height; i++){ | |
196 uint16_t *src = (uint16_t *) buf; | |
197 uint16_t *dst = (uint16_t *) ptr; | |
198 | |
199 for(j = 0; j < avctx->width; j++) | |
200 *dst++ = le2me_16(*src++); | |
201 | |
202 buf += n; | |
203 ptr += linesize; | |
204 } | |
205 break; | |
206 case 32: | |
207 for(i = 0; i < avctx->height; i++){ | |
208 uint8_t *src = buf; | |
209 uint8_t *dst = ptr; | |
210 | |
211 for(j = 0; j < avctx->width; j++){ | |
212 dst[0] = src[rgb[2]]; | |
213 dst[1] = src[rgb[1]]; | |
214 dst[2] = src[rgb[0]]; | |
215 dst += 3; | |
216 src += 4; | |
217 } | |
218 | |
219 buf += n; | |
220 ptr += linesize; | |
221 } | |
222 break; | |
223 default: | |
224 av_log(avctx, AV_LOG_ERROR, "BMP decoder is broken\n"); | |
225 return -1; | |
226 } | |
227 | |
228 *picture = s->picture; | |
229 *data_size = sizeof(AVPicture); | |
230 | |
231 return buf_size; | |
232 } | |
233 | |
4455
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
234 static int bmp_decode_end(AVCodecContext *avctx) |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
235 { |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
236 BMPContext* c = avctx->priv_data; |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
237 |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
238 if (c->picture.data[0]) |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
239 avctx->release_buffer(avctx, &c->picture); |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
240 |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
241 return 0; |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
242 } |
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
243 |
2949 | 244 AVCodec bmp_decoder = { |
245 "bmp", | |
246 CODEC_TYPE_VIDEO, | |
247 CODEC_ID_BMP, | |
248 sizeof(BMPContext), | |
249 bmp_decode_init, | |
250 NULL, | |
4455
8ecfb7ecbb53
Add decode_end method to bmp decoder. Patch by Michel Bardiaux,
takis
parents:
4445
diff
changeset
|
251 bmp_decode_end, |
2949 | 252 bmp_decode_frame |
253 }; |