Libav 0.7.1
|
00001 /* 00002 * PNM image format 00003 * Copyright (c) 2002, 2003 Fabrice Bellard 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "avcodec.h" 00023 #include "bytestream.h" 00024 #include "pnm.h" 00025 00026 00027 static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, 00028 int buf_size, void *data) 00029 { 00030 PNMContext *s = avctx->priv_data; 00031 AVFrame *pict = data; 00032 AVFrame * const p = (AVFrame*)&s->picture; 00033 int i, h, h1, c, n, linesize; 00034 uint8_t *ptr, *ptr1, *ptr2; 00035 00036 if (buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200) { 00037 av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n"); 00038 return -1; 00039 } 00040 00041 *p = *pict; 00042 p->pict_type = AV_PICTURE_TYPE_I; 00043 p->key_frame = 1; 00044 00045 s->bytestream_start = 00046 s->bytestream = outbuf; 00047 s->bytestream_end = outbuf + buf_size; 00048 00049 h = avctx->height; 00050 h1 = h; 00051 switch (avctx->pix_fmt) { 00052 case PIX_FMT_MONOWHITE: 00053 c = '4'; 00054 n = (avctx->width + 7) >> 3; 00055 break; 00056 case PIX_FMT_GRAY8: 00057 c = '5'; 00058 n = avctx->width; 00059 break; 00060 case PIX_FMT_GRAY16BE: 00061 c = '5'; 00062 n = avctx->width * 2; 00063 break; 00064 case PIX_FMT_RGB24: 00065 c = '6'; 00066 n = avctx->width * 3; 00067 break; 00068 case PIX_FMT_RGB48BE: 00069 c = '6'; 00070 n = avctx->width * 6; 00071 break; 00072 case PIX_FMT_YUV420P: 00073 c = '5'; 00074 n = avctx->width; 00075 h1 = (h * 3) / 2; 00076 break; 00077 default: 00078 return -1; 00079 } 00080 snprintf(s->bytestream, s->bytestream_end - s->bytestream, 00081 "P%c\n%d %d\n", c, avctx->width, h1); 00082 s->bytestream += strlen(s->bytestream); 00083 if (avctx->pix_fmt != PIX_FMT_MONOWHITE) { 00084 snprintf(s->bytestream, s->bytestream_end - s->bytestream, 00085 "%d\n", (avctx->pix_fmt != PIX_FMT_GRAY16BE && avctx->pix_fmt != PIX_FMT_RGB48BE) ? 255 : 65535); 00086 s->bytestream += strlen(s->bytestream); 00087 } 00088 00089 ptr = p->data[0]; 00090 linesize = p->linesize[0]; 00091 for (i = 0; i < h; i++) { 00092 memcpy(s->bytestream, ptr, n); 00093 s->bytestream += n; 00094 ptr += linesize; 00095 } 00096 00097 if (avctx->pix_fmt == PIX_FMT_YUV420P) { 00098 h >>= 1; 00099 n >>= 1; 00100 ptr1 = p->data[1]; 00101 ptr2 = p->data[2]; 00102 for (i = 0; i < h; i++) { 00103 memcpy(s->bytestream, ptr1, n); 00104 s->bytestream += n; 00105 memcpy(s->bytestream, ptr2, n); 00106 s->bytestream += n; 00107 ptr1 += p->linesize[1]; 00108 ptr2 += p->linesize[2]; 00109 } 00110 } 00111 return s->bytestream - s->bytestream_start; 00112 } 00113 00114 00115 #if CONFIG_PGM_ENCODER 00116 AVCodec ff_pgm_encoder = { 00117 "pgm", 00118 AVMEDIA_TYPE_VIDEO, 00119 CODEC_ID_PGM, 00120 sizeof(PNMContext), 00121 ff_pnm_init, 00122 pnm_encode_frame, 00123 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_GRAY8, PIX_FMT_GRAY16BE, PIX_FMT_NONE}, 00124 .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), 00125 }; 00126 #endif 00127 00128 #if CONFIG_PGMYUV_ENCODER 00129 AVCodec ff_pgmyuv_encoder = { 00130 "pgmyuv", 00131 AVMEDIA_TYPE_VIDEO, 00132 CODEC_ID_PGMYUV, 00133 sizeof(PNMContext), 00134 ff_pnm_init, 00135 pnm_encode_frame, 00136 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, 00137 .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), 00138 }; 00139 #endif 00140 00141 #if CONFIG_PPM_ENCODER 00142 AVCodec ff_ppm_encoder = { 00143 "ppm", 00144 AVMEDIA_TYPE_VIDEO, 00145 CODEC_ID_PPM, 00146 sizeof(PNMContext), 00147 ff_pnm_init, 00148 pnm_encode_frame, 00149 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB48BE, PIX_FMT_NONE}, 00150 .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), 00151 }; 00152 #endif 00153 00154 #if CONFIG_PBM_ENCODER 00155 AVCodec ff_pbm_encoder = { 00156 "pbm", 00157 AVMEDIA_TYPE_VIDEO, 00158 CODEC_ID_PBM, 00159 sizeof(PNMContext), 00160 ff_pnm_init, 00161 pnm_encode_frame, 00162 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_MONOWHITE, PIX_FMT_NONE}, 00163 .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), 00164 }; 00165 #endif