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= NULL_IF_CONFIG_SMALL("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= NULL_IF_CONFIG_SMALL("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= NULL_IF_CONFIG_SMALL("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= NULL_IF_CONFIG_SMALL("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= NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"),
430 #endif // CONFIG_PAM_ENCODER