flacdec: split frame header decoding and validation into a separate
[FFMpeg-mirror/lagarith.git] / libavcodec / pnmenc.c
blob69e6bed657b7624d4c464b9e293cfdd82637c788
1 /*
2 * PNM image format
3 * Copyright (c) 2002, 2003 Fabrice Bellard
5 * This file is part of FFmpeg.
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.
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.
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
21 #include "avcodec.h"
22 #include "bytestream.h"
23 #include "pnm.h"
26 static av_cold int common_init(AVCodecContext *avctx){
27 PNMContext *s = avctx->priv_data;
29 avcodec_get_frame_defaults((AVFrame*)&s->picture);
30 avctx->coded_frame= (AVFrame*)&s->picture;
32 return 0;
35 static int pnm_decode_frame(AVCodecContext *avctx,
36 void *data, int *data_size,
37 const uint8_t *buf, int buf_size)
39 PNMContext * const s = avctx->priv_data;
40 AVFrame *picture = data;
41 AVFrame * const p= (AVFrame*)&s->picture;
42 int i, n, linesize, h, upgrade = 0;
43 unsigned char *ptr;
45 s->bytestream_start=
46 s->bytestream= buf;
47 s->bytestream_end= buf + buf_size;
49 if(ff_pnm_decode_header(avctx, s) < 0)
50 return -1;
52 if(p->data[0])
53 avctx->release_buffer(avctx, p);
55 p->reference= 0;
56 if(avctx->get_buffer(avctx, p) < 0){
57 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
58 return -1;
60 p->pict_type= FF_I_TYPE;
61 p->key_frame= 1;
63 switch(avctx->pix_fmt) {
64 default:
65 return -1;
66 case PIX_FMT_RGB48BE:
67 n = avctx->width * 6;
68 goto do_read;
69 case PIX_FMT_RGB24:
70 n = avctx->width * 3;
71 goto do_read;
72 case PIX_FMT_GRAY8:
73 n = avctx->width;
74 if (s->maxval < 255)
75 upgrade = 1;
76 goto do_read;
77 case PIX_FMT_GRAY16BE:
78 case PIX_FMT_GRAY16LE:
79 n = avctx->width * 2;
80 if (s->maxval < 65535)
81 upgrade = 2;
82 goto do_read;
83 case PIX_FMT_MONOWHITE:
84 case PIX_FMT_MONOBLACK:
85 n = (avctx->width + 7) >> 3;
86 do_read:
87 ptr = p->data[0];
88 linesize = p->linesize[0];
89 if(s->bytestream + n*avctx->height > s->bytestream_end)
90 return -1;
91 for(i = 0; i < avctx->height; i++) {
92 if (!upgrade)
93 memcpy(ptr, s->bytestream, n);
94 else if (upgrade == 1) {
95 unsigned int j, f = (255*128 + s->maxval/2) / s->maxval;
96 for (j=0; j<n; j++)
97 ptr[j] = (s->bytestream[j] * f + 64) >> 7;
98 } else if (upgrade == 2) {
99 unsigned int j, v, f = (65535*32768 + s->maxval/2) / s->maxval;
100 for (j=0; j<n/2; j++) {
101 v = be2me_16(((uint16_t *)s->bytestream)[j]);
102 ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15;
105 s->bytestream += n;
106 ptr += linesize;
108 break;
109 case PIX_FMT_YUV420P:
111 unsigned char *ptr1, *ptr2;
113 n = avctx->width;
114 ptr = p->data[0];
115 linesize = p->linesize[0];
116 if(s->bytestream + n*avctx->height*3/2 > s->bytestream_end)
117 return -1;
118 for(i = 0; i < avctx->height; i++) {
119 memcpy(ptr, s->bytestream, n);
120 s->bytestream += n;
121 ptr += linesize;
123 ptr1 = p->data[1];
124 ptr2 = p->data[2];
125 n >>= 1;
126 h = avctx->height >> 1;
127 for(i = 0; i < h; i++) {
128 memcpy(ptr1, s->bytestream, n);
129 s->bytestream += n;
130 memcpy(ptr2, s->bytestream, n);
131 s->bytestream += n;
132 ptr1 += p->linesize[1];
133 ptr2 += p->linesize[2];
136 break;
137 case PIX_FMT_RGB32:
138 ptr = p->data[0];
139 linesize = p->linesize[0];
140 if(s->bytestream + avctx->width*avctx->height*4 > s->bytestream_end)
141 return -1;
142 for(i = 0; i < avctx->height; i++) {
143 int j, r, g, b, a;
145 for(j = 0;j < avctx->width; j++) {
146 r = *s->bytestream++;
147 g = *s->bytestream++;
148 b = *s->bytestream++;
149 a = *s->bytestream++;
150 ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
152 ptr += linesize;
154 break;
156 *picture= *(AVFrame*)&s->picture;
157 *data_size = sizeof(AVPicture);
159 return s->bytestream - s->bytestream_start;
162 static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
163 PNMContext *s = avctx->priv_data;
164 AVFrame *pict = data;
165 AVFrame * const p= (AVFrame*)&s->picture;
166 int i, h, h1, c, n, linesize;
167 uint8_t *ptr, *ptr1, *ptr2;
169 if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
170 av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
171 return -1;
174 *p = *pict;
175 p->pict_type= FF_I_TYPE;
176 p->key_frame= 1;
178 s->bytestream_start=
179 s->bytestream= outbuf;
180 s->bytestream_end= outbuf+buf_size;
182 h = avctx->height;
183 h1 = h;
184 switch(avctx->pix_fmt) {
185 case PIX_FMT_MONOWHITE:
186 c = '4';
187 n = (avctx->width + 7) >> 3;
188 break;
189 case PIX_FMT_GRAY8:
190 c = '5';
191 n = avctx->width;
192 break;
193 case PIX_FMT_GRAY16BE:
194 c = '5';
195 n = avctx->width * 2;
196 break;
197 case PIX_FMT_RGB24:
198 c = '6';
199 n = avctx->width * 3;
200 break;
201 case PIX_FMT_RGB48BE:
202 c = '6';
203 n = avctx->width * 6;
204 break;
205 case PIX_FMT_YUV420P:
206 c = '5';
207 n = avctx->width;
208 h1 = (h * 3) / 2;
209 break;
210 default:
211 return -1;
213 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
214 "P%c\n%d %d\n",
215 c, avctx->width, h1);
216 s->bytestream += strlen(s->bytestream);
217 if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
218 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
219 "%d\n", (avctx->pix_fmt != PIX_FMT_GRAY16BE && avctx->pix_fmt != PIX_FMT_RGB48BE) ? 255 : 65535);
220 s->bytestream += strlen(s->bytestream);
223 ptr = p->data[0];
224 linesize = p->linesize[0];
225 for(i=0;i<h;i++) {
226 memcpy(s->bytestream, ptr, n);
227 s->bytestream += n;
228 ptr += linesize;
231 if (avctx->pix_fmt == PIX_FMT_YUV420P) {
232 h >>= 1;
233 n >>= 1;
234 ptr1 = p->data[1];
235 ptr2 = p->data[2];
236 for(i=0;i<h;i++) {
237 memcpy(s->bytestream, ptr1, n);
238 s->bytestream += n;
239 memcpy(s->bytestream, ptr2, n);
240 s->bytestream += n;
241 ptr1 += p->linesize[1];
242 ptr2 += p->linesize[2];
245 return s->bytestream - s->bytestream_start;
248 static int pam_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
249 PNMContext *s = avctx->priv_data;
250 AVFrame *pict = data;
251 AVFrame * const p= (AVFrame*)&s->picture;
252 int i, h, w, n, linesize, depth, maxval;
253 const char *tuple_type;
254 uint8_t *ptr;
256 if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
257 av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
258 return -1;
261 *p = *pict;
262 p->pict_type= FF_I_TYPE;
263 p->key_frame= 1;
265 s->bytestream_start=
266 s->bytestream= outbuf;
267 s->bytestream_end= outbuf+buf_size;
269 h = avctx->height;
270 w = avctx->width;
271 switch(avctx->pix_fmt) {
272 case PIX_FMT_MONOWHITE:
273 n = (w + 7) >> 3;
274 depth = 1;
275 maxval = 1;
276 tuple_type = "BLACKANDWHITE";
277 break;
278 case PIX_FMT_GRAY8:
279 n = w;
280 depth = 1;
281 maxval = 255;
282 tuple_type = "GRAYSCALE";
283 break;
284 case PIX_FMT_RGB24:
285 n = w * 3;
286 depth = 3;
287 maxval = 255;
288 tuple_type = "RGB";
289 break;
290 case PIX_FMT_RGB32:
291 n = w * 4;
292 depth = 4;
293 maxval = 255;
294 tuple_type = "RGB_ALPHA";
295 break;
296 default:
297 return -1;
299 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
300 "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLETYPE %s\nENDHDR\n",
301 w, h, depth, maxval, tuple_type);
302 s->bytestream += strlen(s->bytestream);
304 ptr = p->data[0];
305 linesize = p->linesize[0];
307 if (avctx->pix_fmt == PIX_FMT_RGB32) {
308 int j;
309 unsigned int v;
311 for(i=0;i<h;i++) {
312 for(j=0;j<w;j++) {
313 v = ((uint32_t *)ptr)[j];
314 bytestream_put_be24(&s->bytestream, v);
315 *s->bytestream++ = v >> 24;
317 ptr += linesize;
319 } else {
320 for(i=0;i<h;i++) {
321 memcpy(s->bytestream, ptr, n);
322 s->bytestream += n;
323 ptr += linesize;
326 return s->bytestream - s->bytestream_start;
329 #if 0
330 static int pnm_probe(AVProbeData *pd)
332 const char *p = pd->buf;
333 if (pd->buf_size >= 8 &&
334 p[0] == 'P' &&
335 p[1] >= '4' && p[1] <= '6' &&
336 pnm_space(p[2]) )
337 return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
338 else
339 return 0;
342 static int pgmyuv_probe(AVProbeData *pd)
344 if (match_ext(pd->filename, "pgmyuv"))
345 return AVPROBE_SCORE_MAX;
346 else
347 return 0;
350 static int pam_probe(AVProbeData *pd)
352 const char *p = pd->buf;
353 if (pd->buf_size >= 8 &&
354 p[0] == 'P' &&
355 p[1] == '7' &&
356 p[2] == '\n')
357 return AVPROBE_SCORE_MAX;
358 else
359 return 0;
361 #endif
364 #if CONFIG_PGM_DECODER
365 AVCodec pgm_decoder = {
366 "pgm",
367 CODEC_TYPE_VIDEO,
368 CODEC_ID_PGM,
369 sizeof(PNMContext),
370 common_init,
371 NULL,
372 NULL,
373 pnm_decode_frame,
374 .pix_fmts= (enum PixelFormat[]){PIX_FMT_GRAY8, PIX_FMT_GRAY16BE, PIX_FMT_NONE},
375 .long_name= NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"),
377 #endif
379 #if CONFIG_PGM_ENCODER
380 AVCodec pgm_encoder = {
381 "pgm",
382 CODEC_TYPE_VIDEO,
383 CODEC_ID_PGM,
384 sizeof(PNMContext),
385 common_init,
386 pnm_encode_frame,
387 .pix_fmts= (enum PixelFormat[]){PIX_FMT_GRAY8, PIX_FMT_GRAY16BE, PIX_FMT_NONE},
388 .long_name= NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"),
390 #endif // CONFIG_PGM_ENCODER
392 #if CONFIG_PGMYUV_DECODER
393 AVCodec pgmyuv_decoder = {
394 "pgmyuv",
395 CODEC_TYPE_VIDEO,
396 CODEC_ID_PGMYUV,
397 sizeof(PNMContext),
398 common_init,
399 NULL,
400 NULL,
401 pnm_decode_frame,
402 .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
403 .long_name= NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"),
405 #endif
407 #if CONFIG_PGMYUV_ENCODER
408 AVCodec pgmyuv_encoder = {
409 "pgmyuv",
410 CODEC_TYPE_VIDEO,
411 CODEC_ID_PGMYUV,
412 sizeof(PNMContext),
413 common_init,
414 pnm_encode_frame,
415 .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
416 .long_name= NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"),
418 #endif // CONFIG_PGMYUV_ENCODER
420 #if CONFIG_PPM_DECODER
421 AVCodec ppm_decoder = {
422 "ppm",
423 CODEC_TYPE_VIDEO,
424 CODEC_ID_PPM,
425 sizeof(PNMContext),
426 common_init,
427 NULL,
428 NULL,
429 pnm_decode_frame,
430 .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB48BE, PIX_FMT_NONE},
431 .long_name= NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"),
433 #endif
435 #if CONFIG_PPM_ENCODER
436 AVCodec ppm_encoder = {
437 "ppm",
438 CODEC_TYPE_VIDEO,
439 CODEC_ID_PPM,
440 sizeof(PNMContext),
441 common_init,
442 pnm_encode_frame,
443 .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB48BE, PIX_FMT_NONE},
444 .long_name= NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"),
446 #endif // CONFIG_PPM_ENCODER
448 #if CONFIG_PBM_DECODER
449 AVCodec pbm_decoder = {
450 "pbm",
451 CODEC_TYPE_VIDEO,
452 CODEC_ID_PBM,
453 sizeof(PNMContext),
454 common_init,
455 NULL,
456 NULL,
457 pnm_decode_frame,
458 .pix_fmts= (enum PixelFormat[]){PIX_FMT_MONOWHITE, PIX_FMT_NONE},
459 .long_name= NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"),
461 #endif
463 #if CONFIG_PBM_ENCODER
464 AVCodec pbm_encoder = {
465 "pbm",
466 CODEC_TYPE_VIDEO,
467 CODEC_ID_PBM,
468 sizeof(PNMContext),
469 common_init,
470 pnm_encode_frame,
471 .pix_fmts= (enum PixelFormat[]){PIX_FMT_MONOWHITE, PIX_FMT_NONE},
472 .long_name= NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"),
474 #endif // CONFIG_PBM_ENCODER
476 #if CONFIG_PAM_DECODER
477 AVCodec pam_decoder = {
478 "pam",
479 CODEC_TYPE_VIDEO,
480 CODEC_ID_PAM,
481 sizeof(PNMContext),
482 common_init,
483 NULL,
484 NULL,
485 pnm_decode_frame,
486 .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB32, PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, PIX_FMT_NONE},
487 .long_name= NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"),
489 #endif
491 #if CONFIG_PAM_ENCODER
492 AVCodec pam_encoder = {
493 "pam",
494 CODEC_TYPE_VIDEO,
495 CODEC_ID_PAM,
496 sizeof(PNMContext),
497 common_init,
498 pam_encode_frame,
499 .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB32, PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, PIX_FMT_NONE},
500 .long_name= NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"),
502 #endif // CONFIG_PAM_ENCODER