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
22 #include "bytestream.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;
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;
47 s->bytestream_end= buf + buf_size;
49 if(ff_pnm_decode_header(avctx, s) < 0)
53 avctx->release_buffer(avctx, p);
56 if(avctx->get_buffer(avctx, p) < 0){
57 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
60 p->pict_type= FF_I_TYPE;
63 switch(avctx->pix_fmt) {
77 case PIX_FMT_GRAY16BE:
78 case PIX_FMT_GRAY16LE:
80 if (s->maxval < 65535)
83 case PIX_FMT_MONOWHITE:
84 case PIX_FMT_MONOBLACK:
85 n = (avctx->width + 7) >> 3;
88 linesize = p->linesize[0];
89 if(s->bytestream + n*avctx->height > s->bytestream_end)
91 for(i = 0; i < avctx->height; i++) {
93 memcpy(ptr, s->bytestream, n);
94 else if (upgrade == 1) {
95 unsigned int j, f = (255*128 + s->maxval/2) / s->maxval;
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;
109 case PIX_FMT_YUV420P:
111 unsigned char *ptr1, *ptr2;
115 linesize = p->linesize[0];
116 if(s->bytestream + n*avctx->height*3/2 > s->bytestream_end)
118 for(i = 0; i < avctx->height; i++) {
119 memcpy(ptr, s->bytestream, n);
126 h = avctx->height >> 1;
127 for(i = 0; i < h; i++) {
128 memcpy(ptr1, s->bytestream, n);
130 memcpy(ptr2, s->bytestream, n);
132 ptr1 += p->linesize[1];
133 ptr2 += p->linesize[2];
139 linesize = p->linesize[0];
140 if(s->bytestream + avctx->width*avctx->height*4 > s->bytestream_end)
142 for(i = 0; i < avctx->height; i++) {
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;
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");
175 p->pict_type= FF_I_TYPE;
179 s->bytestream= outbuf;
180 s->bytestream_end= outbuf+buf_size;
184 switch(avctx->pix_fmt) {
185 case PIX_FMT_MONOWHITE:
187 n = (avctx->width + 7) >> 3;
193 case PIX_FMT_GRAY16BE:
195 n = avctx->width * 2;
199 n = avctx->width * 3;
201 case PIX_FMT_RGB48BE:
203 n = avctx->width * 6;
205 case PIX_FMT_YUV420P:
213 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
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);
224 linesize = p->linesize[0];
226 memcpy(s->bytestream, ptr, n);
231 if (avctx->pix_fmt == PIX_FMT_YUV420P) {
237 memcpy(s->bytestream, ptr1, n);
239 memcpy(s->bytestream, ptr2, 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;
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");
262 p->pict_type= FF_I_TYPE;
266 s->bytestream= outbuf;
267 s->bytestream_end= outbuf+buf_size;
271 switch(avctx->pix_fmt) {
272 case PIX_FMT_MONOWHITE:
276 tuple_type = "BLACKANDWHITE";
282 tuple_type = "GRAYSCALE";
294 tuple_type = "RGB_ALPHA";
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);
305 linesize = p->linesize[0];
307 if (avctx->pix_fmt == PIX_FMT_RGB32) {
313 v = ((uint32_t *)ptr)[j];
314 bytestream_put_be24(&s->bytestream, v);
315 *s->bytestream++ = v >> 24;
321 memcpy(s->bytestream, ptr, n);
326 return s->bytestream - s->bytestream_start;
330 static int pnm_probe(AVProbeData *pd)
332 const char *p = pd->buf;
333 if (pd->buf_size >= 8 &&
335 p[1] >= '4' && p[1] <= '6' &&
337 return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
342 static int pgmyuv_probe(AVProbeData *pd)
344 if (match_ext(pd->filename, "pgmyuv"))
345 return AVPROBE_SCORE_MAX;
350 static int pam_probe(AVProbeData *pd)
352 const char *p = pd->buf;
353 if (pd->buf_size >= 8 &&
357 return AVPROBE_SCORE_MAX;
364 #if CONFIG_PGM_DECODER
365 AVCodec pgm_decoder = {
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"),
379 #if CONFIG_PGM_ENCODER
380 AVCodec pgm_encoder = {
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 = {
402 .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
403 .long_name= NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"),
407 #if CONFIG_PGMYUV_ENCODER
408 AVCodec pgmyuv_encoder = {
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 = {
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"),
435 #if CONFIG_PPM_ENCODER
436 AVCodec ppm_encoder = {
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 = {
458 .pix_fmts= (enum PixelFormat[]){PIX_FMT_MONOWHITE, PIX_FMT_NONE},
459 .long_name= NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"),
463 #if CONFIG_PBM_ENCODER
464 AVCodec pbm_encoder = {
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 = {
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"),
491 #if CONFIG_PAM_ENCODER
492 AVCodec pam_encoder = {
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