]> git.sesse.net Git - ffmpeg/blob - libavcodec/pnmenc.c
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
[ffmpeg] / 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                         const uint8_t *buf, int buf_size)
38 {
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;
44
45     s->bytestream_start=
46     s->bytestream= buf;
47     s->bytestream_end= buf + buf_size;
48
49     if(ff_pnm_decode_header(avctx, s) < 0)
50         return -1;
51
52     if(p->data[0])
53         avctx->release_buffer(avctx, p);
54
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;
59     }
60     p->pict_type= FF_I_TYPE;
61     p->key_frame= 1;
62
63     switch(avctx->pix_fmt) {
64     default:
65         return -1;
66     case PIX_FMT_RGB24:
67         n = avctx->width * 3;
68         goto do_read;
69     case PIX_FMT_GRAY8:
70         n = avctx->width;
71         if (s->maxval < 255)
72             upgrade = 1;
73         goto do_read;
74     case PIX_FMT_GRAY16BE:
75     case PIX_FMT_GRAY16LE:
76         n = avctx->width * 2;
77         if (s->maxval < 65535)
78             upgrade = 2;
79         goto do_read;
80     case PIX_FMT_MONOWHITE:
81     case PIX_FMT_MONOBLACK:
82         n = (avctx->width + 7) >> 3;
83     do_read:
84         ptr = p->data[0];
85         linesize = p->linesize[0];
86         if(s->bytestream + n*avctx->height > s->bytestream_end)
87             return -1;
88         for(i = 0; i < avctx->height; i++) {
89             if (!upgrade)
90                 memcpy(ptr, s->bytestream, n);
91             else if (upgrade == 1) {
92                 unsigned int j, f = (255*128 + s->maxval/2) / s->maxval;
93                 for (j=0; j<n; j++)
94                     ptr[j] = (s->bytestream[j] * f + 64) >> 7;
95             } else if (upgrade == 2) {
96                 unsigned int j, v, f = (65535*32768 + s->maxval/2) / s->maxval;
97                 for (j=0; j<n/2; j++) {
98                     v = be2me_16(((uint16_t *)s->bytestream)[j]);
99                     ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15;
100                 }
101             }
102             s->bytestream += n;
103             ptr += linesize;
104         }
105         break;
106     case PIX_FMT_YUV420P:
107         {
108             unsigned char *ptr1, *ptr2;
109
110             n = avctx->width;
111             ptr = p->data[0];
112             linesize = p->linesize[0];
113             if(s->bytestream + n*avctx->height*3/2 > s->bytestream_end)
114                 return -1;
115             for(i = 0; i < avctx->height; i++) {
116                 memcpy(ptr, s->bytestream, n);
117                 s->bytestream += n;
118                 ptr += linesize;
119             }
120             ptr1 = p->data[1];
121             ptr2 = p->data[2];
122             n >>= 1;
123             h = avctx->height >> 1;
124             for(i = 0; i < h; i++) {
125                 memcpy(ptr1, s->bytestream, n);
126                 s->bytestream += n;
127                 memcpy(ptr2, s->bytestream, n);
128                 s->bytestream += n;
129                 ptr1 += p->linesize[1];
130                 ptr2 += p->linesize[2];
131             }
132         }
133         break;
134     case PIX_FMT_RGB32:
135         ptr = p->data[0];
136         linesize = p->linesize[0];
137         if(s->bytestream + avctx->width*avctx->height*4 > s->bytestream_end)
138             return -1;
139         for(i = 0; i < avctx->height; i++) {
140             int j, r, g, b, a;
141
142             for(j = 0;j < avctx->width; j++) {
143                 r = *s->bytestream++;
144                 g = *s->bytestream++;
145                 b = *s->bytestream++;
146                 a = *s->bytestream++;
147                 ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
148             }
149             ptr += linesize;
150         }
151         break;
152     }
153     *picture= *(AVFrame*)&s->picture;
154     *data_size = sizeof(AVPicture);
155
156     return s->bytestream - s->bytestream_start;
157 }
158
159 static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
160     PNMContext *s = avctx->priv_data;
161     AVFrame *pict = data;
162     AVFrame * const p= (AVFrame*)&s->picture;
163     int i, h, h1, c, n, linesize;
164     uint8_t *ptr, *ptr1, *ptr2;
165
166     if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
167         av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
168         return -1;
169     }
170
171     *p = *pict;
172     p->pict_type= FF_I_TYPE;
173     p->key_frame= 1;
174
175     s->bytestream_start=
176     s->bytestream= outbuf;
177     s->bytestream_end= outbuf+buf_size;
178
179     h = avctx->height;
180     h1 = h;
181     switch(avctx->pix_fmt) {
182     case PIX_FMT_MONOWHITE:
183         c = '4';
184         n = (avctx->width + 7) >> 3;
185         break;
186     case PIX_FMT_GRAY8:
187         c = '5';
188         n = avctx->width;
189         break;
190     case PIX_FMT_GRAY16BE:
191         c = '5';
192         n = avctx->width * 2;
193         break;
194     case PIX_FMT_RGB24:
195         c = '6';
196         n = avctx->width * 3;
197         break;
198     case PIX_FMT_YUV420P:
199         c = '5';
200         n = avctx->width;
201         h1 = (h * 3) / 2;
202         break;
203     default:
204         return -1;
205     }
206     snprintf(s->bytestream, s->bytestream_end - s->bytestream,
207              "P%c\n%d %d\n",
208              c, avctx->width, h1);
209     s->bytestream += strlen(s->bytestream);
210     if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
211         snprintf(s->bytestream, s->bytestream_end - s->bytestream,
212                  "%d\n", (avctx->pix_fmt != PIX_FMT_GRAY16BE) ? 255 : 65535);
213         s->bytestream += strlen(s->bytestream);
214     }
215
216     ptr = p->data[0];
217     linesize = p->linesize[0];
218     for(i=0;i<h;i++) {
219         memcpy(s->bytestream, ptr, n);
220         s->bytestream += n;
221         ptr += linesize;
222     }
223
224     if (avctx->pix_fmt == PIX_FMT_YUV420P) {
225         h >>= 1;
226         n >>= 1;
227         ptr1 = p->data[1];
228         ptr2 = p->data[2];
229         for(i=0;i<h;i++) {
230             memcpy(s->bytestream, ptr1, n);
231             s->bytestream += n;
232             memcpy(s->bytestream, ptr2, n);
233             s->bytestream += n;
234                 ptr1 += p->linesize[1];
235                 ptr2 += p->linesize[2];
236         }
237     }
238     return s->bytestream - s->bytestream_start;
239 }
240
241 static int pam_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
242     PNMContext *s = avctx->priv_data;
243     AVFrame *pict = data;
244     AVFrame * const p= (AVFrame*)&s->picture;
245     int i, h, w, n, linesize, depth, maxval;
246     const char *tuple_type;
247     uint8_t *ptr;
248
249     if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
250         av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
251         return -1;
252     }
253
254     *p = *pict;
255     p->pict_type= FF_I_TYPE;
256     p->key_frame= 1;
257
258     s->bytestream_start=
259     s->bytestream= outbuf;
260     s->bytestream_end= outbuf+buf_size;
261
262     h = avctx->height;
263     w = avctx->width;
264     switch(avctx->pix_fmt) {
265     case PIX_FMT_MONOWHITE:
266         n = (w + 7) >> 3;
267         depth = 1;
268         maxval = 1;
269         tuple_type = "BLACKANDWHITE";
270         break;
271     case PIX_FMT_GRAY8:
272         n = w;
273         depth = 1;
274         maxval = 255;
275         tuple_type = "GRAYSCALE";
276         break;
277     case PIX_FMT_RGB24:
278         n = w * 3;
279         depth = 3;
280         maxval = 255;
281         tuple_type = "RGB";
282         break;
283     case PIX_FMT_RGB32:
284         n = w * 4;
285         depth = 4;
286         maxval = 255;
287         tuple_type = "RGB_ALPHA";
288         break;
289     default:
290         return -1;
291     }
292     snprintf(s->bytestream, s->bytestream_end - s->bytestream,
293              "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLETYPE %s\nENDHDR\n",
294              w, h, depth, maxval, tuple_type);
295     s->bytestream += strlen(s->bytestream);
296
297     ptr = p->data[0];
298     linesize = p->linesize[0];
299
300     if (avctx->pix_fmt == PIX_FMT_RGB32) {
301         int j;
302         unsigned int v;
303
304         for(i=0;i<h;i++) {
305             for(j=0;j<w;j++) {
306                 v = ((uint32_t *)ptr)[j];
307                 bytestream_put_be24(&s->bytestream, v);
308                 *s->bytestream++ = v >> 24;
309             }
310             ptr += linesize;
311         }
312     } else {
313         for(i=0;i<h;i++) {
314             memcpy(s->bytestream, ptr, n);
315             s->bytestream += n;
316             ptr += linesize;
317         }
318     }
319     return s->bytestream - s->bytestream_start;
320 }
321
322 #if 0
323 static int pnm_probe(AVProbeData *pd)
324 {
325     const char *p = pd->buf;
326     if (pd->buf_size >= 8 &&
327         p[0] == 'P' &&
328         p[1] >= '4' && p[1] <= '6' &&
329         pnm_space(p[2]) )
330         return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
331     else
332         return 0;
333 }
334
335 static int pgmyuv_probe(AVProbeData *pd)
336 {
337     if (match_ext(pd->filename, "pgmyuv"))
338         return AVPROBE_SCORE_MAX;
339     else
340         return 0;
341 }
342
343 static int pam_probe(AVProbeData *pd)
344 {
345     const char *p = pd->buf;
346     if (pd->buf_size >= 8 &&
347         p[0] == 'P' &&
348         p[1] == '7' &&
349         p[2] == '\n')
350         return AVPROBE_SCORE_MAX;
351     else
352         return 0;
353 }
354 #endif
355
356
357 #ifdef CONFIG_PGM_ENCODER
358 AVCodec pgm_encoder = {
359     "pgm",
360     CODEC_TYPE_VIDEO,
361     CODEC_ID_PGM,
362     sizeof(PNMContext),
363     common_init,
364     pnm_encode_frame,
365     NULL, //encode_end,
366     pnm_decode_frame,
367     .pix_fmts= (enum PixelFormat[]){PIX_FMT_GRAY8, PIX_FMT_GRAY16BE, PIX_FMT_NONE},
368     .long_name= NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"),
369 };
370 #endif // CONFIG_PGM_ENCODER
371
372 #ifdef CONFIG_PGMYUV_ENCODER
373 AVCodec pgmyuv_encoder = {
374     "pgmyuv",
375     CODEC_TYPE_VIDEO,
376     CODEC_ID_PGMYUV,
377     sizeof(PNMContext),
378     common_init,
379     pnm_encode_frame,
380     NULL, //encode_end,
381     pnm_decode_frame,
382     .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
383     .long_name= NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"),
384 };
385 #endif // CONFIG_PGMYUV_ENCODER
386
387 #ifdef CONFIG_PPM_ENCODER
388 AVCodec ppm_encoder = {
389     "ppm",
390     CODEC_TYPE_VIDEO,
391     CODEC_ID_PPM,
392     sizeof(PNMContext),
393     common_init,
394     pnm_encode_frame,
395     NULL, //encode_end,
396     pnm_decode_frame,
397     .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_NONE},
398     .long_name= NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"),
399 };
400 #endif // CONFIG_PPM_ENCODER
401
402 #ifdef CONFIG_PBM_ENCODER
403 AVCodec pbm_encoder = {
404     "pbm",
405     CODEC_TYPE_VIDEO,
406     CODEC_ID_PBM,
407     sizeof(PNMContext),
408     common_init,
409     pnm_encode_frame,
410     NULL, //encode_end,
411     pnm_decode_frame,
412     .pix_fmts= (enum PixelFormat[]){PIX_FMT_MONOWHITE, PIX_FMT_NONE},
413     .long_name= NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"),
414 };
415 #endif // CONFIG_PBM_ENCODER
416
417 #ifdef CONFIG_PAM_ENCODER
418 AVCodec pam_encoder = {
419     "pam",
420     CODEC_TYPE_VIDEO,
421     CODEC_ID_PAM,
422     sizeof(PNMContext),
423     common_init,
424     pam_encode_frame,
425     NULL, //encode_end,
426     pnm_decode_frame,
427     .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB32, PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, PIX_FMT_NONE},
428     .long_name= NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"),
429 };
430 #endif // CONFIG_PAM_ENCODER