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