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
) {
74 case PIX_FMT_GRAY16BE
:
75 case PIX_FMT_GRAY16LE
:
77 if (s
->maxval
< 65535)
80 case PIX_FMT_MONOWHITE
:
81 case PIX_FMT_MONOBLACK
:
82 n
= (avctx
->width
+ 7) >> 3;
85 linesize
= p
->linesize
[0];
86 if(s
->bytestream
+ n
*avctx
->height
> s
->bytestream_end
)
88 for(i
= 0; i
< avctx
->height
; i
++) {
90 memcpy(ptr
, s
->bytestream
, n
);
91 else if (upgrade
== 1) {
92 unsigned int j
, f
= (255*128 + s
->maxval
/2) / s
->maxval
;
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;
106 case PIX_FMT_YUV420P
:
108 unsigned char *ptr1
, *ptr2
;
112 linesize
= p
->linesize
[0];
113 if(s
->bytestream
+ n
*avctx
->height
*3/2 > s
->bytestream_end
)
115 for(i
= 0; i
< avctx
->height
; i
++) {
116 memcpy(ptr
, s
->bytestream
, n
);
123 h
= avctx
->height
>> 1;
124 for(i
= 0; i
< h
; i
++) {
125 memcpy(ptr1
, s
->bytestream
, n
);
127 memcpy(ptr2
, s
->bytestream
, n
);
129 ptr1
+= p
->linesize
[1];
130 ptr2
+= p
->linesize
[2];
136 linesize
= p
->linesize
[0];
137 if(s
->bytestream
+ avctx
->width
*avctx
->height
*4 > s
->bytestream_end
)
139 for(i
= 0; i
< avctx
->height
; i
++) {
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
;
153 *picture
= *(AVFrame
*)&s
->picture
;
154 *data_size
= sizeof(AVPicture
);
156 return s
->bytestream
- s
->bytestream_start
;
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
;
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");
172 p
->pict_type
= FF_I_TYPE
;
176 s
->bytestream
= outbuf
;
177 s
->bytestream_end
= outbuf
+buf_size
;
181 switch(avctx
->pix_fmt
) {
182 case PIX_FMT_MONOWHITE
:
184 n
= (avctx
->width
+ 7) >> 3;
190 case PIX_FMT_GRAY16BE
:
192 n
= avctx
->width
* 2;
196 n
= avctx
->width
* 3;
198 case PIX_FMT_YUV420P
:
206 snprintf(s
->bytestream
, s
->bytestream_end
- s
->bytestream
,
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
);
217 linesize
= p
->linesize
[0];
219 memcpy(s
->bytestream
, ptr
, n
);
224 if (avctx
->pix_fmt
== PIX_FMT_YUV420P
) {
230 memcpy(s
->bytestream
, ptr1
, n
);
232 memcpy(s
->bytestream
, ptr2
, n
);
234 ptr1
+= p
->linesize
[1];
235 ptr2
+= p
->linesize
[2];
238 return s
->bytestream
- s
->bytestream_start
;
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
;
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");
255 p
->pict_type
= FF_I_TYPE
;
259 s
->bytestream
= outbuf
;
260 s
->bytestream_end
= outbuf
+buf_size
;
264 switch(avctx
->pix_fmt
) {
265 case PIX_FMT_MONOWHITE
:
269 tuple_type
= "BLACKANDWHITE";
275 tuple_type
= "GRAYSCALE";
287 tuple_type
= "RGB_ALPHA";
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
);
298 linesize
= p
->linesize
[0];
300 if (avctx
->pix_fmt
== PIX_FMT_RGB32
) {
306 v
= ((uint32_t *)ptr
)[j
];
307 bytestream_put_be24(&s
->bytestream
, v
);
308 *s
->bytestream
++ = v
>> 24;
314 memcpy(s
->bytestream
, ptr
, n
);
319 return s
->bytestream
- s
->bytestream_start
;
323 static int pnm_probe(AVProbeData
*pd
)
325 const char *p
= pd
->buf
;
326 if (pd
->buf_size
>= 8 &&
328 p
[1] >= '4' && p
[1] <= '6' &&
330 return AVPROBE_SCORE_MAX
- 1; /* to permit pgmyuv probe */
335 static int pgmyuv_probe(AVProbeData
*pd
)
337 if (match_ext(pd
->filename
, "pgmyuv"))
338 return AVPROBE_SCORE_MAX
;
343 static int pam_probe(AVProbeData
*pd
)
345 const char *p
= pd
->buf
;
346 if (pd
->buf_size
>= 8 &&
350 return AVPROBE_SCORE_MAX
;
357 #ifdef CONFIG_PGM_ENCODER
358 AVCodec pgm_encoder
= {
367 .pix_fmts
= (enum PixelFormat
[]){PIX_FMT_GRAY8
, PIX_FMT_GRAY16BE
, PIX_FMT_NONE
},
368 .long_name
= "PGM (Portable GrayMap) image",
370 #endif // CONFIG_PGM_ENCODER
372 #ifdef CONFIG_PGMYUV_ENCODER
373 AVCodec pgmyuv_encoder
= {
382 .pix_fmts
= (enum PixelFormat
[]){PIX_FMT_YUV420P
, PIX_FMT_NONE
},
383 .long_name
= "PGMYUV (Portable GrayMap YUV) image",
385 #endif // CONFIG_PGMYUV_ENCODER
387 #ifdef CONFIG_PPM_ENCODER
388 AVCodec ppm_encoder
= {
397 .pix_fmts
= (enum PixelFormat
[]){PIX_FMT_RGB24
, PIX_FMT_NONE
},
398 .long_name
= "PPM (Portable PixelMap) image",
400 #endif // CONFIG_PPM_ENCODER
402 #ifdef CONFIG_PBM_ENCODER
403 AVCodec pbm_encoder
= {
412 .pix_fmts
= (enum PixelFormat
[]){PIX_FMT_MONOWHITE
, PIX_FMT_NONE
},
413 .long_name
= "PBM (Portable BitMap) image",
415 #endif // CONFIG_PBM_ENCODER
417 #ifdef CONFIG_PAM_ENCODER
418 AVCodec pam_encoder
= {
427 .pix_fmts
= (enum PixelFormat
[]){PIX_FMT_RGB24
, PIX_FMT_RGB32
, PIX_FMT_GRAY8
, PIX_FMT_MONOWHITE
, PIX_FMT_NONE
},
428 .long_name
= "PAM (Portable AnyMap) image",
430 #endif // CONFIG_PAM_ENCODER