Mercurial > libavcodec.hg
annotate pnmdec.c @ 12138:41f078d6869d libavcodec
Do not try to decode less than one frame of data in TrueSpeech decoder.
This should solve issue 2085.
author | kostya |
---|---|
date | Sun, 11 Jul 2010 14:50:20 +0000 |
parents | 8b28e74de2c0 |
children |
rev | line source |
---|---|
10465 | 1 /* |
2 * PNM image format | |
3 * Copyright (c) 2002, 2003 Fabrice Bellard | |
4 * | |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
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 | |
18 * License along with FFmpeg; if not, write to the Free Software | |
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 */ | |
21 | |
22 #include "avcodec.h" | |
23 #include "bytestream.h" | |
10612 | 24 #include "put_bits.h" |
10465 | 25 #include "pnm.h" |
26 | |
27 | |
28 static int pnm_decode_frame(AVCodecContext *avctx, void *data, | |
29 int *data_size, AVPacket *avpkt) | |
30 { | |
31 const uint8_t *buf = avpkt->data; | |
32 int buf_size = avpkt->size; | |
33 PNMContext * const s = avctx->priv_data; | |
34 AVFrame *picture = data; | |
35 AVFrame * const p = (AVFrame*)&s->picture; | |
10612 | 36 int i, j, n, linesize, h, upgrade = 0; |
10465 | 37 unsigned char *ptr; |
10612 | 38 int components, sample_len; |
10465 | 39 |
40 s->bytestream_start = | |
41 s->bytestream = buf; | |
42 s->bytestream_end = buf + buf_size; | |
43 | |
44 if (ff_pnm_decode_header(avctx, s) < 0) | |
45 return -1; | |
46 | |
47 if (p->data[0]) | |
48 avctx->release_buffer(avctx, p); | |
49 | |
50 p->reference = 0; | |
51 if (avctx->get_buffer(avctx, p) < 0) { | |
52 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
53 return -1; | |
54 } | |
55 p->pict_type = FF_I_TYPE; | |
56 p->key_frame = 1; | |
57 | |
58 switch (avctx->pix_fmt) { | |
59 default: | |
60 return -1; | |
61 case PIX_FMT_RGB48BE: | |
62 n = avctx->width * 6; | |
10612 | 63 components=3; |
64 sample_len=16; | |
10465 | 65 goto do_read; |
66 case PIX_FMT_RGB24: | |
67 n = avctx->width * 3; | |
10612 | 68 components=3; |
69 sample_len=8; | |
10465 | 70 goto do_read; |
71 case PIX_FMT_GRAY8: | |
72 n = avctx->width; | |
10612 | 73 components=1; |
74 sample_len=8; | |
10465 | 75 if (s->maxval < 255) |
76 upgrade = 1; | |
77 goto do_read; | |
78 case PIX_FMT_GRAY16BE: | |
79 case PIX_FMT_GRAY16LE: | |
80 n = avctx->width * 2; | |
10612 | 81 components=1; |
82 sample_len=16; | |
10465 | 83 if (s->maxval < 65535) |
84 upgrade = 2; | |
85 goto do_read; | |
86 case PIX_FMT_MONOWHITE: | |
87 case PIX_FMT_MONOBLACK: | |
88 n = (avctx->width + 7) >> 3; | |
10612 | 89 components=1; |
90 sample_len=1; | |
10465 | 91 do_read: |
92 ptr = p->data[0]; | |
93 linesize = p->linesize[0]; | |
94 if (s->bytestream + n * avctx->height > s->bytestream_end) | |
95 return -1; | |
10612 | 96 if(s->type < 4){ |
97 for (i=0; i<avctx->height; i++) { | |
98 PutBitContext pb; | |
99 init_put_bits(&pb, ptr, linesize); | |
100 for(j=0; j<avctx->width * components; j++){ | |
101 unsigned int c=0; | |
102 int v=0; | |
103 while(s->bytestream < s->bytestream_end && (*s->bytestream < '0' || *s->bytestream > '9' )) | |
104 s->bytestream++; | |
105 if(s->bytestream >= s->bytestream_end) | |
106 return -1; | |
107 do{ | |
108 v= 10*v + c; | |
109 c= (*s->bytestream++) - '0'; | |
110 }while(c <= 9); | |
111 put_bits(&pb, sample_len, (((1<<sample_len)-1)*v + (s->maxval>>1))/s->maxval); | |
112 } | |
113 flush_put_bits(&pb); | |
114 ptr+= linesize; | |
115 } | |
116 }else{ | |
10465 | 117 for (i = 0; i < avctx->height; i++) { |
118 if (!upgrade) | |
119 memcpy(ptr, s->bytestream, n); | |
120 else if (upgrade == 1) { | |
121 unsigned int j, f = (255 * 128 + s->maxval / 2) / s->maxval; | |
122 for (j = 0; j < n; j++) | |
123 ptr[j] = (s->bytestream[j] * f + 64) >> 7; | |
124 } else if (upgrade == 2) { | |
125 unsigned int j, v, f = (65535 * 32768 + s->maxval / 2) / s->maxval; | |
126 for (j = 0; j < n / 2; j++) { | |
12129 | 127 v = av_be2ne16(((uint16_t *)s->bytestream)[j]); |
10465 | 128 ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15; |
129 } | |
130 } | |
131 s->bytestream += n; | |
132 ptr += linesize; | |
133 } | |
10612 | 134 } |
10465 | 135 break; |
136 case PIX_FMT_YUV420P: | |
137 { | |
138 unsigned char *ptr1, *ptr2; | |
139 | |
140 n = avctx->width; | |
141 ptr = p->data[0]; | |
142 linesize = p->linesize[0]; | |
143 if (s->bytestream + n * avctx->height * 3 / 2 > s->bytestream_end) | |
144 return -1; | |
145 for (i = 0; i < avctx->height; i++) { | |
146 memcpy(ptr, s->bytestream, n); | |
147 s->bytestream += n; | |
148 ptr += linesize; | |
149 } | |
150 ptr1 = p->data[1]; | |
151 ptr2 = p->data[2]; | |
152 n >>= 1; | |
153 h = avctx->height >> 1; | |
154 for (i = 0; i < h; i++) { | |
155 memcpy(ptr1, s->bytestream, n); | |
156 s->bytestream += n; | |
157 memcpy(ptr2, s->bytestream, n); | |
158 s->bytestream += n; | |
159 ptr1 += p->linesize[1]; | |
160 ptr2 += p->linesize[2]; | |
161 } | |
162 } | |
163 break; | |
164 case PIX_FMT_RGB32: | |
165 ptr = p->data[0]; | |
166 linesize = p->linesize[0]; | |
167 if (s->bytestream + avctx->width * avctx->height * 4 > s->bytestream_end) | |
168 return -1; | |
169 for (i = 0; i < avctx->height; i++) { | |
170 int j, r, g, b, a; | |
171 | |
172 for (j = 0; j < avctx->width; j++) { | |
173 r = *s->bytestream++; | |
174 g = *s->bytestream++; | |
175 b = *s->bytestream++; | |
176 a = *s->bytestream++; | |
177 ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b; | |
178 } | |
179 ptr += linesize; | |
180 } | |
181 break; | |
182 } | |
183 *picture = *(AVFrame*)&s->picture; | |
184 *data_size = sizeof(AVPicture); | |
185 | |
186 return s->bytestream - s->bytestream_start; | |
187 } | |
188 | |
189 | |
190 #if CONFIG_PGM_DECODER | |
191 AVCodec pgm_decoder = { | |
192 "pgm", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10612
diff
changeset
|
193 AVMEDIA_TYPE_VIDEO, |
10465 | 194 CODEC_ID_PGM, |
195 sizeof(PNMContext), | |
196 ff_pnm_init, | |
197 NULL, | |
198 ff_pnm_end, | |
199 pnm_decode_frame, | |
200 CODEC_CAP_DR1, | |
201 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_GRAY8, PIX_FMT_GRAY16BE, PIX_FMT_NONE}, | |
12108
c35d7bc64882
Add new decoder property max_lowres and do not init decoder if requested value is higher.
cehoyos
parents:
11560
diff
changeset
|
202 .max_lowres = 5, |
10465 | 203 .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), |
204 }; | |
205 #endif | |
206 | |
207 #if CONFIG_PGMYUV_DECODER | |
208 AVCodec pgmyuv_decoder = { | |
209 "pgmyuv", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10612
diff
changeset
|
210 AVMEDIA_TYPE_VIDEO, |
10465 | 211 CODEC_ID_PGMYUV, |
212 sizeof(PNMContext), | |
213 ff_pnm_init, | |
214 NULL, | |
215 ff_pnm_end, | |
216 pnm_decode_frame, | |
217 CODEC_CAP_DR1, | |
218 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, | |
12108
c35d7bc64882
Add new decoder property max_lowres and do not init decoder if requested value is higher.
cehoyos
parents:
11560
diff
changeset
|
219 .max_lowres = 5, |
10465 | 220 .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), |
221 }; | |
222 #endif | |
223 | |
224 #if CONFIG_PPM_DECODER | |
225 AVCodec ppm_decoder = { | |
226 "ppm", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10612
diff
changeset
|
227 AVMEDIA_TYPE_VIDEO, |
10465 | 228 CODEC_ID_PPM, |
229 sizeof(PNMContext), | |
230 ff_pnm_init, | |
231 NULL, | |
232 ff_pnm_end, | |
233 pnm_decode_frame, | |
234 CODEC_CAP_DR1, | |
235 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB48BE, PIX_FMT_NONE}, | |
12108
c35d7bc64882
Add new decoder property max_lowres and do not init decoder if requested value is higher.
cehoyos
parents:
11560
diff
changeset
|
236 .max_lowres = 5, |
10465 | 237 .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), |
238 }; | |
239 #endif | |
240 | |
241 #if CONFIG_PBM_DECODER | |
242 AVCodec pbm_decoder = { | |
243 "pbm", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10612
diff
changeset
|
244 AVMEDIA_TYPE_VIDEO, |
10465 | 245 CODEC_ID_PBM, |
246 sizeof(PNMContext), | |
247 ff_pnm_init, | |
248 NULL, | |
249 ff_pnm_end, | |
250 pnm_decode_frame, | |
251 CODEC_CAP_DR1, | |
252 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_MONOWHITE, PIX_FMT_NONE}, | |
12108
c35d7bc64882
Add new decoder property max_lowres and do not init decoder if requested value is higher.
cehoyos
parents:
11560
diff
changeset
|
253 .max_lowres = 5, |
10465 | 254 .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), |
255 }; | |
256 #endif | |
257 | |
258 #if CONFIG_PAM_DECODER | |
259 AVCodec pam_decoder = { | |
260 "pam", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10612
diff
changeset
|
261 AVMEDIA_TYPE_VIDEO, |
10465 | 262 CODEC_ID_PAM, |
263 sizeof(PNMContext), | |
264 ff_pnm_init, | |
265 NULL, | |
266 ff_pnm_end, | |
267 pnm_decode_frame, | |
268 CODEC_CAP_DR1, | |
269 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB32, PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, PIX_FMT_NONE}, | |
12108
c35d7bc64882
Add new decoder property max_lowres and do not init decoder if requested value is higher.
cehoyos
parents:
11560
diff
changeset
|
270 .max_lowres = 5, |
10465 | 271 .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), |
272 }; | |
273 #endif |