comparison pnmenc.c @ 4985:15577904cb95 libavcodec

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