00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "avcodec.h"
00023 #include "pnm.h"
00024
00025
00026 static int pam_encode_frame(AVCodecContext *avctx, unsigned char *outbuf,
00027 int buf_size, void *data)
00028 {
00029 PNMContext *s = avctx->priv_data;
00030 AVFrame *pict = data;
00031 AVFrame * const p = (AVFrame*)&s->picture;
00032 int i, h, w, n, linesize, depth, maxval;
00033 const char *tuple_type;
00034 uint8_t *ptr;
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 w = avctx->width;
00051 switch (avctx->pix_fmt) {
00052 case PIX_FMT_MONOBLACK:
00053 n = (w + 7) >> 3;
00054 depth = 1;
00055 maxval = 1;
00056 tuple_type = "BLACKANDWHITE";
00057 break;
00058 case PIX_FMT_GRAY8:
00059 n = w;
00060 depth = 1;
00061 maxval = 255;
00062 tuple_type = "GRAYSCALE";
00063 break;
00064 case PIX_FMT_GRAY16BE:
00065 n = w * 2;
00066 depth = 1;
00067 maxval = 0xFFFF;
00068 tuple_type = "GRAYSCALE";
00069 break;
00070 case PIX_FMT_GRAY8A:
00071 n = w * 2;
00072 depth = 2;
00073 maxval = 255;
00074 tuple_type = "GRAYSCALE_ALPHA";
00075 break;
00076 case PIX_FMT_RGB24:
00077 n = w * 3;
00078 depth = 3;
00079 maxval = 255;
00080 tuple_type = "RGB";
00081 break;
00082 case PIX_FMT_RGBA:
00083 n = w * 4;
00084 depth = 4;
00085 maxval = 255;
00086 tuple_type = "RGB_ALPHA";
00087 break;
00088 case PIX_FMT_RGB48BE:
00089 n = w * 6;
00090 depth = 3;
00091 maxval = 0xFFFF;
00092 tuple_type = "RGB";
00093 break;
00094 case PIX_FMT_RGBA64BE:
00095 n = w * 8;
00096 depth = 4;
00097 maxval = 0xFFFF;
00098 tuple_type = "RGB_ALPHA";
00099 break;
00100 default:
00101 return -1;
00102 }
00103 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
00104 "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
00105 w, h, depth, maxval, tuple_type);
00106 s->bytestream += strlen(s->bytestream);
00107
00108 ptr = p->data[0];
00109 linesize = p->linesize[0];
00110
00111 if (avctx->pix_fmt == PIX_FMT_MONOBLACK){
00112 int j;
00113 for (i = 0; i < h; i++) {
00114 for (j = 0; j < w; j++)
00115 *s->bytestream++ = ptr[j >> 3] >> (7 - j & 7) & 1;
00116 ptr += linesize;
00117 }
00118 } else {
00119 for (i = 0; i < h; i++) {
00120 memcpy(s->bytestream, ptr, n);
00121 s->bytestream += n;
00122 ptr += linesize;
00123 }
00124 }
00125 return s->bytestream - s->bytestream_start;
00126 }
00127
00128
00129 AVCodec ff_pam_encoder = {
00130 .name = "pam",
00131 .type = AVMEDIA_TYPE_VIDEO,
00132 .id = CODEC_ID_PAM,
00133 .priv_data_size = sizeof(PNMContext),
00134 .init = ff_pnm_init,
00135 .encode = pam_encode_frame,
00136 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA, PIX_FMT_RGB48BE, PIX_FMT_RGBA64BE, PIX_FMT_GRAY8, PIX_FMT_GRAY8A, PIX_FMT_GRAY16BE, PIX_FMT_MONOBLACK, PIX_FMT_NONE},
00137 .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"),
00138 };