• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/pnmenc.c

Go to the documentation of this file.
00001 /*
00002  * PNM image format
00003  * Copyright (c) 2002, 2003 Fabrice Bellard
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 #include "avcodec.h"
00022 #include "bytestream.h"
00023 #include "pnm.h"
00024 
00025 
00026 static av_cold int common_init(AVCodecContext *avctx){
00027     PNMContext *s = avctx->priv_data;
00028 
00029     avcodec_get_frame_defaults((AVFrame*)&s->picture);
00030     avctx->coded_frame= (AVFrame*)&s->picture;
00031 
00032     return 0;
00033 }
00034 
00035 static int pnm_decode_frame(AVCodecContext *avctx,
00036                         void *data, int *data_size,
00037                         const uint8_t *buf, int buf_size)
00038 {
00039     PNMContext * const s = avctx->priv_data;
00040     AVFrame *picture = data;
00041     AVFrame * const p= (AVFrame*)&s->picture;
00042     int i, n, linesize, h, upgrade = 0;
00043     unsigned char *ptr;
00044 
00045     s->bytestream_start=
00046     s->bytestream= buf;
00047     s->bytestream_end= buf + buf_size;
00048 
00049     if(ff_pnm_decode_header(avctx, s) < 0)
00050         return -1;
00051 
00052     if(p->data[0])
00053         avctx->release_buffer(avctx, p);
00054 
00055     p->reference= 0;
00056     if(avctx->get_buffer(avctx, p) < 0){
00057         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00058         return -1;
00059     }
00060     p->pict_type= FF_I_TYPE;
00061     p->key_frame= 1;
00062 
00063     switch(avctx->pix_fmt) {
00064     default:
00065         return -1;
00066     case PIX_FMT_RGB48BE:
00067         n = avctx->width * 6;
00068         goto do_read;
00069     case PIX_FMT_RGB24:
00070         n = avctx->width * 3;
00071         goto do_read;
00072     case PIX_FMT_GRAY8:
00073         n = avctx->width;
00074         if (s->maxval < 255)
00075             upgrade = 1;
00076         goto do_read;
00077     case PIX_FMT_GRAY16BE:
00078     case PIX_FMT_GRAY16LE:
00079         n = avctx->width * 2;
00080         if (s->maxval < 65535)
00081             upgrade = 2;
00082         goto do_read;
00083     case PIX_FMT_MONOWHITE:
00084     case PIX_FMT_MONOBLACK:
00085         n = (avctx->width + 7) >> 3;
00086     do_read:
00087         ptr = p->data[0];
00088         linesize = p->linesize[0];
00089         if(s->bytestream + n*avctx->height > s->bytestream_end)
00090             return -1;
00091         for(i = 0; i < avctx->height; i++) {
00092             if (!upgrade)
00093                 memcpy(ptr, s->bytestream, n);
00094             else if (upgrade == 1) {
00095                 unsigned int j, f = (255*128 + s->maxval/2) / s->maxval;
00096                 for (j=0; j<n; j++)
00097                     ptr[j] = (s->bytestream[j] * f + 64) >> 7;
00098             } else if (upgrade == 2) {
00099                 unsigned int j, v, f = (65535*32768 + s->maxval/2) / s->maxval;
00100                 for (j=0; j<n/2; j++) {
00101                     v = be2me_16(((uint16_t *)s->bytestream)[j]);
00102                     ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15;
00103                 }
00104             }
00105             s->bytestream += n;
00106             ptr += linesize;
00107         }
00108         break;
00109     case PIX_FMT_YUV420P:
00110         {
00111             unsigned char *ptr1, *ptr2;
00112 
00113             n = avctx->width;
00114             ptr = p->data[0];
00115             linesize = p->linesize[0];
00116             if(s->bytestream + n*avctx->height*3/2 > s->bytestream_end)
00117                 return -1;
00118             for(i = 0; i < avctx->height; i++) {
00119                 memcpy(ptr, s->bytestream, n);
00120                 s->bytestream += n;
00121                 ptr += linesize;
00122             }
00123             ptr1 = p->data[1];
00124             ptr2 = p->data[2];
00125             n >>= 1;
00126             h = avctx->height >> 1;
00127             for(i = 0; i < h; i++) {
00128                 memcpy(ptr1, s->bytestream, n);
00129                 s->bytestream += n;
00130                 memcpy(ptr2, s->bytestream, n);
00131                 s->bytestream += n;
00132                 ptr1 += p->linesize[1];
00133                 ptr2 += p->linesize[2];
00134             }
00135         }
00136         break;
00137     case PIX_FMT_RGB32:
00138         ptr = p->data[0];
00139         linesize = p->linesize[0];
00140         if(s->bytestream + avctx->width*avctx->height*4 > s->bytestream_end)
00141             return -1;
00142         for(i = 0; i < avctx->height; i++) {
00143             int j, r, g, b, a;
00144 
00145             for(j = 0;j < avctx->width; j++) {
00146                 r = *s->bytestream++;
00147                 g = *s->bytestream++;
00148                 b = *s->bytestream++;
00149                 a = *s->bytestream++;
00150                 ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
00151             }
00152             ptr += linesize;
00153         }
00154         break;
00155     }
00156     *picture= *(AVFrame*)&s->picture;
00157     *data_size = sizeof(AVPicture);
00158 
00159     return s->bytestream - s->bytestream_start;
00160 }
00161 
00162 static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
00163     PNMContext *s = avctx->priv_data;
00164     AVFrame *pict = data;
00165     AVFrame * const p= (AVFrame*)&s->picture;
00166     int i, h, h1, c, n, linesize;
00167     uint8_t *ptr, *ptr1, *ptr2;
00168 
00169     if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
00170         av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
00171         return -1;
00172     }
00173 
00174     *p = *pict;
00175     p->pict_type= FF_I_TYPE;
00176     p->key_frame= 1;
00177 
00178     s->bytestream_start=
00179     s->bytestream= outbuf;
00180     s->bytestream_end= outbuf+buf_size;
00181 
00182     h = avctx->height;
00183     h1 = h;
00184     switch(avctx->pix_fmt) {
00185     case PIX_FMT_MONOWHITE:
00186         c = '4';
00187         n = (avctx->width + 7) >> 3;
00188         break;
00189     case PIX_FMT_GRAY8:
00190         c = '5';
00191         n = avctx->width;
00192         break;
00193     case PIX_FMT_GRAY16BE:
00194         c = '5';
00195         n = avctx->width * 2;
00196         break;
00197     case PIX_FMT_RGB24:
00198         c = '6';
00199         n = avctx->width * 3;
00200         break;
00201     case PIX_FMT_RGB48BE:
00202         c = '6';
00203         n = avctx->width * 6;
00204         break;
00205     case PIX_FMT_YUV420P:
00206         c = '5';
00207         n = avctx->width;
00208         h1 = (h * 3) / 2;
00209         break;
00210     default:
00211         return -1;
00212     }
00213     snprintf(s->bytestream, s->bytestream_end - s->bytestream,
00214              "P%c\n%d %d\n",
00215              c, avctx->width, h1);
00216     s->bytestream += strlen(s->bytestream);
00217     if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
00218         snprintf(s->bytestream, s->bytestream_end - s->bytestream,
00219                  "%d\n", (avctx->pix_fmt != PIX_FMT_GRAY16BE && avctx->pix_fmt != PIX_FMT_RGB48BE) ? 255 : 65535);
00220         s->bytestream += strlen(s->bytestream);
00221     }
00222 
00223     ptr = p->data[0];
00224     linesize = p->linesize[0];
00225     for(i=0;i<h;i++) {
00226         memcpy(s->bytestream, ptr, n);
00227         s->bytestream += n;
00228         ptr += linesize;
00229     }
00230 
00231     if (avctx->pix_fmt == PIX_FMT_YUV420P) {
00232         h >>= 1;
00233         n >>= 1;
00234         ptr1 = p->data[1];
00235         ptr2 = p->data[2];
00236         for(i=0;i<h;i++) {
00237             memcpy(s->bytestream, ptr1, n);
00238             s->bytestream += n;
00239             memcpy(s->bytestream, ptr2, n);
00240             s->bytestream += n;
00241                 ptr1 += p->linesize[1];
00242                 ptr2 += p->linesize[2];
00243         }
00244     }
00245     return s->bytestream - s->bytestream_start;
00246 }
00247 
00248 static int pam_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
00249     PNMContext *s = avctx->priv_data;
00250     AVFrame *pict = data;
00251     AVFrame * const p= (AVFrame*)&s->picture;
00252     int i, h, w, n, linesize, depth, maxval;
00253     const char *tuple_type;
00254     uint8_t *ptr;
00255 
00256     if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
00257         av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
00258         return -1;
00259     }
00260 
00261     *p = *pict;
00262     p->pict_type= FF_I_TYPE;
00263     p->key_frame= 1;
00264 
00265     s->bytestream_start=
00266     s->bytestream= outbuf;
00267     s->bytestream_end= outbuf+buf_size;
00268 
00269     h = avctx->height;
00270     w = avctx->width;
00271     switch(avctx->pix_fmt) {
00272     case PIX_FMT_MONOWHITE:
00273         n = (w + 7) >> 3;
00274         depth = 1;
00275         maxval = 1;
00276         tuple_type = "BLACKANDWHITE";
00277         break;
00278     case PIX_FMT_GRAY8:
00279         n = w;
00280         depth = 1;
00281         maxval = 255;
00282         tuple_type = "GRAYSCALE";
00283         break;
00284     case PIX_FMT_RGB24:
00285         n = w * 3;
00286         depth = 3;
00287         maxval = 255;
00288         tuple_type = "RGB";
00289         break;
00290     case PIX_FMT_RGB32:
00291         n = w * 4;
00292         depth = 4;
00293         maxval = 255;
00294         tuple_type = "RGB_ALPHA";
00295         break;
00296     default:
00297         return -1;
00298     }
00299     snprintf(s->bytestream, s->bytestream_end - s->bytestream,
00300              "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLETYPE %s\nENDHDR\n",
00301              w, h, depth, maxval, tuple_type);
00302     s->bytestream += strlen(s->bytestream);
00303 
00304     ptr = p->data[0];
00305     linesize = p->linesize[0];
00306 
00307     if (avctx->pix_fmt == PIX_FMT_RGB32) {
00308         int j;
00309         unsigned int v;
00310 
00311         for(i=0;i<h;i++) {
00312             for(j=0;j<w;j++) {
00313                 v = ((uint32_t *)ptr)[j];
00314                 bytestream_put_be24(&s->bytestream, v);
00315                 *s->bytestream++ = v >> 24;
00316             }
00317             ptr += linesize;
00318         }
00319     } else {
00320         for(i=0;i<h;i++) {
00321             memcpy(s->bytestream, ptr, n);
00322             s->bytestream += n;
00323             ptr += linesize;
00324         }
00325     }
00326     return s->bytestream - s->bytestream_start;
00327 }
00328 
00329 #if 0
00330 static int pnm_probe(AVProbeData *pd)
00331 {
00332     const char *p = pd->buf;
00333     if (pd->buf_size >= 8 &&
00334         p[0] == 'P' &&
00335         p[1] >= '4' && p[1] <= '6' &&
00336         pnm_space(p[2]) )
00337         return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
00338     else
00339         return 0;
00340 }
00341 
00342 static int pgmyuv_probe(AVProbeData *pd)
00343 {
00344     if (match_ext(pd->filename, "pgmyuv"))
00345         return AVPROBE_SCORE_MAX;
00346     else
00347         return 0;
00348 }
00349 
00350 static int pam_probe(AVProbeData *pd)
00351 {
00352     const char *p = pd->buf;
00353     if (pd->buf_size >= 8 &&
00354         p[0] == 'P' &&
00355         p[1] == '7' &&
00356         p[2] == '\n')
00357         return AVPROBE_SCORE_MAX;
00358     else
00359         return 0;
00360 }
00361 #endif
00362 
00363 
00364 #if CONFIG_PGM_ENCODER
00365 AVCodec pgm_encoder = {
00366     "pgm",
00367     CODEC_TYPE_VIDEO,
00368     CODEC_ID_PGM,
00369     sizeof(PNMContext),
00370     common_init,
00371     pnm_encode_frame,
00372     NULL, //encode_end,
00373     pnm_decode_frame,
00374     .pix_fmts= (enum PixelFormat[]){PIX_FMT_GRAY8, PIX_FMT_GRAY16BE, PIX_FMT_NONE},
00375     .long_name= NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"),
00376 };
00377 #endif // CONFIG_PGM_ENCODER
00378 
00379 #if CONFIG_PGMYUV_ENCODER
00380 AVCodec pgmyuv_encoder = {
00381     "pgmyuv",
00382     CODEC_TYPE_VIDEO,
00383     CODEC_ID_PGMYUV,
00384     sizeof(PNMContext),
00385     common_init,
00386     pnm_encode_frame,
00387     NULL, //encode_end,
00388     pnm_decode_frame,
00389     .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
00390     .long_name= NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"),
00391 };
00392 #endif // CONFIG_PGMYUV_ENCODER
00393 
00394 #if CONFIG_PPM_ENCODER
00395 AVCodec ppm_encoder = {
00396     "ppm",
00397     CODEC_TYPE_VIDEO,
00398     CODEC_ID_PPM,
00399     sizeof(PNMContext),
00400     common_init,
00401     pnm_encode_frame,
00402     NULL, //encode_end,
00403     pnm_decode_frame,
00404     .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB48BE, PIX_FMT_NONE},
00405     .long_name= NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"),
00406 };
00407 #endif // CONFIG_PPM_ENCODER
00408 
00409 #if CONFIG_PBM_ENCODER
00410 AVCodec pbm_encoder = {
00411     "pbm",
00412     CODEC_TYPE_VIDEO,
00413     CODEC_ID_PBM,
00414     sizeof(PNMContext),
00415     common_init,
00416     pnm_encode_frame,
00417     NULL, //encode_end,
00418     pnm_decode_frame,
00419     .pix_fmts= (enum PixelFormat[]){PIX_FMT_MONOWHITE, PIX_FMT_NONE},
00420     .long_name= NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"),
00421 };
00422 #endif // CONFIG_PBM_ENCODER
00423 
00424 #if CONFIG_PAM_ENCODER
00425 AVCodec pam_encoder = {
00426     "pam",
00427     CODEC_TYPE_VIDEO,
00428     CODEC_ID_PAM,
00429     sizeof(PNMContext),
00430     common_init,
00431     pam_encode_frame,
00432     NULL, //encode_end,
00433     pnm_decode_frame,
00434     .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB32, PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, PIX_FMT_NONE},
00435     .long_name= NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"),
00436 };
00437 #endif // CONFIG_PAM_ENCODER

Generated on Tue Nov 4 2014 12:59:22 for ffmpeg by  doxygen 1.7.1