1/* 2 * PNM image format 3 * Copyright (c) 2002, 2003 Fabrice Bellard 4 * 5 * This file is part of FFmpeg. 6 * 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. 11 * 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. 16 * 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 20 */ 21 22#include "avcodec.h" 23#include "bytestream.h" 24#include "pnm.h" 25 26 27static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, 28 int buf_size, void *data) 29{ 30 PNMContext *s = avctx->priv_data; 31 AVFrame *pict = data; 32 AVFrame * const p = (AVFrame*)&s->picture; 33 int i, h, h1, c, n, linesize; 34 uint8_t *ptr, *ptr1, *ptr2; 35 36 if (buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200) { 37 av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n"); 38 return -1; 39 } 40 41 *p = *pict; 42 p->pict_type = FF_I_TYPE; 43 p->key_frame = 1; 44 45 s->bytestream_start = 46 s->bytestream = outbuf; 47 s->bytestream_end = outbuf + buf_size; 48 49 h = avctx->height; 50 h1 = h; 51 switch (avctx->pix_fmt) { 52 case PIX_FMT_MONOWHITE: 53 c = '4'; 54 n = (avctx->width + 7) >> 3; 55 break; 56 case PIX_FMT_GRAY8: 57 c = '5'; 58 n = avctx->width; 59 break; 60 case PIX_FMT_GRAY16BE: 61 c = '5'; 62 n = avctx->width * 2; 63 break; 64 case PIX_FMT_RGB24: 65 c = '6'; 66 n = avctx->width * 3; 67 break; 68 case PIX_FMT_RGB48BE: 69 c = '6'; 70 n = avctx->width * 6; 71 break; 72 case PIX_FMT_YUV420P: 73 c = '5'; 74 n = avctx->width; 75 h1 = (h * 3) / 2; 76 break; 77 default: 78 return -1; 79 } 80 snprintf(s->bytestream, s->bytestream_end - s->bytestream, 81 "P%c\n%d %d\n", c, avctx->width, h1); 82 s->bytestream += strlen(s->bytestream); 83 if (avctx->pix_fmt != PIX_FMT_MONOWHITE) { 84 snprintf(s->bytestream, s->bytestream_end - s->bytestream, 85 "%d\n", (avctx->pix_fmt != PIX_FMT_GRAY16BE && avctx->pix_fmt != PIX_FMT_RGB48BE) ? 255 : 65535); 86 s->bytestream += strlen(s->bytestream); 87 } 88 89 ptr = p->data[0]; 90 linesize = p->linesize[0]; 91 for (i = 0; i < h; i++) { 92 memcpy(s->bytestream, ptr, n); 93 s->bytestream += n; 94 ptr += linesize; 95 } 96 97 if (avctx->pix_fmt == PIX_FMT_YUV420P) { 98 h >>= 1; 99 n >>= 1; 100 ptr1 = p->data[1]; 101 ptr2 = p->data[2]; 102 for (i = 0; i < h; i++) { 103 memcpy(s->bytestream, ptr1, n); 104 s->bytestream += n; 105 memcpy(s->bytestream, ptr2, n); 106 s->bytestream += n; 107 ptr1 += p->linesize[1]; 108 ptr2 += p->linesize[2]; 109 } 110 } 111 return s->bytestream - s->bytestream_start; 112} 113 114 115#if CONFIG_PGM_ENCODER 116AVCodec pgm_encoder = { 117 "pgm", 118 AVMEDIA_TYPE_VIDEO, 119 CODEC_ID_PGM, 120 sizeof(PNMContext), 121 ff_pnm_init, 122 pnm_encode_frame, 123 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_GRAY8, PIX_FMT_GRAY16BE, PIX_FMT_NONE}, 124 .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), 125}; 126#endif 127 128#if CONFIG_PGMYUV_ENCODER 129AVCodec pgmyuv_encoder = { 130 "pgmyuv", 131 AVMEDIA_TYPE_VIDEO, 132 CODEC_ID_PGMYUV, 133 sizeof(PNMContext), 134 ff_pnm_init, 135 pnm_encode_frame, 136 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, 137 .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), 138}; 139#endif 140 141#if CONFIG_PPM_ENCODER 142AVCodec ppm_encoder = { 143 "ppm", 144 AVMEDIA_TYPE_VIDEO, 145 CODEC_ID_PPM, 146 sizeof(PNMContext), 147 ff_pnm_init, 148 pnm_encode_frame, 149 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB48BE, PIX_FMT_NONE}, 150 .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), 151}; 152#endif 153 154#if CONFIG_PBM_ENCODER 155AVCodec pbm_encoder = { 156 "pbm", 157 AVMEDIA_TYPE_VIDEO, 158 CODEC_ID_PBM, 159 sizeof(PNMContext), 160 ff_pnm_init, 161 pnm_encode_frame, 162 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_MONOWHITE, PIX_FMT_NONE}, 163 .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), 164}; 165#endif 166