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_ENCODER
365 AVCodec pgm_encoder
= {
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"),
377 #endif // CONFIG_PGM_ENCODER
379 #if CONFIG_PGMYUV_ENCODER
380 AVCodec pgmyuv_encoder
= {
389 .pix_fmts
= (enum PixelFormat
[]){PIX_FMT_YUV420P
, PIX_FMT_NONE
},
390 .long_name
= NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"),
392 #endif // CONFIG_PGMYUV_ENCODER
394 #if CONFIG_PPM_ENCODER
395 AVCodec ppm_encoder
= {
404 .pix_fmts
= (enum PixelFormat
[]){PIX_FMT_RGB24
, PIX_FMT_RGB48BE
, PIX_FMT_NONE
},
405 .long_name
= NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"),
407 #endif // CONFIG_PPM_ENCODER
409 #if CONFIG_PBM_ENCODER
410 AVCodec pbm_encoder
= {
419 .pix_fmts
= (enum PixelFormat
[]){PIX_FMT_MONOWHITE
, PIX_FMT_NONE
},
420 .long_name
= NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"),
422 #endif // CONFIG_PBM_ENCODER
424 #if CONFIG_PAM_ENCODER
425 AVCodec pam_encoder
= {
434 .pix_fmts
= (enum PixelFormat
[]){PIX_FMT_RGB24
, PIX_FMT_RGB32
, PIX_FMT_GRAY8
, PIX_FMT_MONOWHITE
, PIX_FMT_NONE
},
435 .long_name
= NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"),
437 #endif // CONFIG_PAM_ENCODER