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
,
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;
49 s
->bytestream_end
= buf
+ buf_size
;
51 if(ff_pnm_decode_header(avctx
, s
) < 0)
55 avctx
->release_buffer(avctx
, p
);
58 if(avctx
->get_buffer(avctx
, p
) < 0){
59 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
62 p
->pict_type
= FF_I_TYPE
;
65 switch(avctx
->pix_fmt
) {
79 case PIX_FMT_GRAY16BE
:
80 case PIX_FMT_GRAY16LE
:
82 if (s
->maxval
< 65535)
85 case PIX_FMT_MONOWHITE
:
86 case PIX_FMT_MONOBLACK
:
87 n
= (avctx
->width
+ 7) >> 3;
90 linesize
= p
->linesize
[0];
91 if(s
->bytestream
+ n
*avctx
->height
> s
->bytestream_end
)
93 for(i
= 0; i
< avctx
->height
; i
++) {
95 memcpy(ptr
, s
->bytestream
, n
);
96 else if (upgrade
== 1) {
97 unsigned int j
, f
= (255*128 + s
->maxval
/2) / s
->maxval
;
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;
111 case PIX_FMT_YUV420P
:
113 unsigned char *ptr1
, *ptr2
;
117 linesize
= p
->linesize
[0];
118 if(s
->bytestream
+ n
*avctx
->height
*3/2 > s
->bytestream_end
)
120 for(i
= 0; i
< avctx
->height
; i
++) {
121 memcpy(ptr
, s
->bytestream
, n
);
128 h
= avctx
->height
>> 1;
129 for(i
= 0; i
< h
; i
++) {
130 memcpy(ptr1
, s
->bytestream
, n
);
132 memcpy(ptr2
, s
->bytestream
, n
);
134 ptr1
+= p
->linesize
[1];
135 ptr2
+= p
->linesize
[2];
141 linesize
= p
->linesize
[0];
142 if(s
->bytestream
+ avctx
->width
*avctx
->height
*4 > s
->bytestream_end
)
144 for(i
= 0; i
< avctx
->height
; i
++) {
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
;
158 *picture
= *(AVFrame
*)&s
->picture
;
159 *data_size
= sizeof(AVPicture
);
161 return s
->bytestream
- s
->bytestream_start
;
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
;
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");
177 p
->pict_type
= FF_I_TYPE
;
181 s
->bytestream
= outbuf
;
182 s
->bytestream_end
= outbuf
+buf_size
;
186 switch(avctx
->pix_fmt
) {
187 case PIX_FMT_MONOWHITE
:
189 n
= (avctx
->width
+ 7) >> 3;
195 case PIX_FMT_GRAY16BE
:
197 n
= avctx
->width
* 2;
201 n
= avctx
->width
* 3;
203 case PIX_FMT_RGB48BE
:
205 n
= avctx
->width
* 6;
207 case PIX_FMT_YUV420P
:
215 snprintf(s
->bytestream
, s
->bytestream_end
- s
->bytestream
,
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
);
226 linesize
= p
->linesize
[0];
228 memcpy(s
->bytestream
, ptr
, n
);
233 if (avctx
->pix_fmt
== PIX_FMT_YUV420P
) {
239 memcpy(s
->bytestream
, ptr1
, n
);
241 memcpy(s
->bytestream
, ptr2
, n
);
243 ptr1
+= p
->linesize
[1];
244 ptr2
+= p
->linesize
[2];
247 return s
->bytestream
- s
->bytestream_start
;
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
;
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");
264 p
->pict_type
= FF_I_TYPE
;
268 s
->bytestream
= outbuf
;
269 s
->bytestream_end
= outbuf
+buf_size
;
273 switch(avctx
->pix_fmt
) {
274 case PIX_FMT_MONOWHITE
:
278 tuple_type
= "BLACKANDWHITE";
284 tuple_type
= "GRAYSCALE";
296 tuple_type
= "RGB_ALPHA";
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
);
307 linesize
= p
->linesize
[0];
309 if (avctx
->pix_fmt
== PIX_FMT_RGB32
) {
315 v
= ((uint32_t *)ptr
)[j
];
316 bytestream_put_be24(&s
->bytestream
, v
);
317 *s
->bytestream
++ = v
>> 24;
323 memcpy(s
->bytestream
, ptr
, n
);
328 return s
->bytestream
- s
->bytestream_start
;
332 static int pnm_probe(AVProbeData
*pd
)
334 const char *p
= pd
->buf
;
335 if (pd
->buf_size
>= 8 &&
337 p
[1] >= '4' && p
[1] <= '6' &&
339 return AVPROBE_SCORE_MAX
- 1; /* to permit pgmyuv probe */
344 static int pgmyuv_probe(AVProbeData
*pd
)
346 if (match_ext(pd
->filename
, "pgmyuv"))
347 return AVPROBE_SCORE_MAX
;
352 static int pam_probe(AVProbeData
*pd
)
354 const char *p
= pd
->buf
;
355 if (pd
->buf_size
>= 8 &&
359 return AVPROBE_SCORE_MAX
;
366 #if CONFIG_PGM_DECODER
367 AVCodec pgm_decoder
= {
377 .pix_fmts
= (const enum PixelFormat
[]){PIX_FMT_GRAY8
, PIX_FMT_GRAY16BE
, PIX_FMT_NONE
},
378 .long_name
= NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"),
382 #if CONFIG_PGM_ENCODER
383 AVCodec pgm_encoder
= {
390 .pix_fmts
= (const enum PixelFormat
[]){PIX_FMT_GRAY8
, PIX_FMT_GRAY16BE
, PIX_FMT_NONE
},
391 .long_name
= NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"),
393 #endif // CONFIG_PGM_ENCODER
395 #if CONFIG_PGMYUV_DECODER
396 AVCodec pgmyuv_decoder
= {
406 .pix_fmts
= (const enum PixelFormat
[]){PIX_FMT_YUV420P
, PIX_FMT_NONE
},
407 .long_name
= NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"),
411 #if CONFIG_PGMYUV_ENCODER
412 AVCodec pgmyuv_encoder
= {
419 .pix_fmts
= (const enum PixelFormat
[]){PIX_FMT_YUV420P
, PIX_FMT_NONE
},
420 .long_name
= NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"),
422 #endif // CONFIG_PGMYUV_ENCODER
424 #if CONFIG_PPM_DECODER
425 AVCodec ppm_decoder
= {
435 .pix_fmts
= (const enum PixelFormat
[]){PIX_FMT_RGB24
, PIX_FMT_RGB48BE
, PIX_FMT_NONE
},
436 .long_name
= NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"),
440 #if CONFIG_PPM_ENCODER
441 AVCodec ppm_encoder
= {
448 .pix_fmts
= (const enum PixelFormat
[]){PIX_FMT_RGB24
, PIX_FMT_RGB48BE
, PIX_FMT_NONE
},
449 .long_name
= NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"),
451 #endif // CONFIG_PPM_ENCODER
453 #if CONFIG_PBM_DECODER
454 AVCodec pbm_decoder
= {
464 .pix_fmts
= (const enum PixelFormat
[]){PIX_FMT_MONOWHITE
, PIX_FMT_NONE
},
465 .long_name
= NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"),
469 #if CONFIG_PBM_ENCODER
470 AVCodec pbm_encoder
= {
477 .pix_fmts
= (const enum PixelFormat
[]){PIX_FMT_MONOWHITE
, PIX_FMT_NONE
},
478 .long_name
= NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"),
480 #endif // CONFIG_PBM_ENCODER
482 #if CONFIG_PAM_DECODER
483 AVCodec pam_decoder
= {
493 .pix_fmts
= (const enum PixelFormat
[]){PIX_FMT_RGB24
, PIX_FMT_RGB32
, PIX_FMT_GRAY8
, PIX_FMT_MONOWHITE
, PIX_FMT_NONE
},
494 .long_name
= NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"),
498 #if CONFIG_PAM_ENCODER
499 AVCodec pam_encoder
= {
506 .pix_fmts
= (const enum PixelFormat
[]){PIX_FMT_RGB24
, PIX_FMT_RGB32
, PIX_FMT_GRAY8
, PIX_FMT_MONOWHITE
, PIX_FMT_NONE
},
507 .long_name
= NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"),
509 #endif // CONFIG_PAM_ENCODER