pnm.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:16k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*
  2.  * PNM image format
  3.  * Copyright (c) 2002, 2003 Fabrice Bellard.
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  */
  19. #include "avcodec.h"
  20. #include "mpegvideo.h" //only for ParseContext
  21. typedef struct PNMContext {
  22.     uint8_t *bytestream;
  23.     uint8_t *bytestream_start;
  24.     uint8_t *bytestream_end;
  25.     AVFrame picture;
  26. } PNMContext;
  27. static inline int pnm_space(int c)  
  28. {
  29.     return (c == ' ' || c == 'n' || c == 'r' || c == 't');
  30. }
  31. static void pnm_get(PNMContext *sc, char *str, int buf_size) 
  32. {
  33.     char *s;
  34.     int c;
  35.     
  36.     /* skip spaces and comments */
  37.     for(;;) {
  38.         c = *sc->bytestream++;
  39.         if (c == '#')  {
  40.             do  {
  41.                 c = *sc->bytestream++;
  42.             } while (c != 'n' && sc->bytestream < sc->bytestream_end);
  43.         } else if (!pnm_space(c)) {
  44.             break;
  45.         }
  46.     }
  47.     
  48.     s = str;
  49.     while (sc->bytestream < sc->bytestream_end && !pnm_space(c)) {
  50.         if ((s - str)  < buf_size - 1)
  51.             *s++ = c;
  52.         c = *sc->bytestream++;
  53.     }
  54.     *s = '';
  55. }
  56. static int common_init(AVCodecContext *avctx){
  57.     PNMContext *s = avctx->priv_data;
  58.     avcodec_get_frame_defaults((AVFrame*)&s->picture);
  59.     avctx->coded_frame= (AVFrame*)&s->picture;
  60.     return 0;
  61. }
  62. static int pnm_decode_header(AVCodecContext *avctx, PNMContext * const s){
  63.     char buf1[32], tuple_type[32];
  64.     int h, w, depth, maxval;;
  65.     pnm_get(s, buf1, sizeof(buf1));
  66.     if (!strcmp(buf1, "P4")) {
  67.         avctx->pix_fmt = PIX_FMT_MONOWHITE;
  68.     } else if (!strcmp(buf1, "P5")) {
  69.         if (avctx->codec_id == CODEC_ID_PGMYUV) 
  70.             avctx->pix_fmt = PIX_FMT_YUV420P;
  71.         else
  72.             avctx->pix_fmt = PIX_FMT_GRAY8;
  73.     } else if (!strcmp(buf1, "P6")) {
  74.         avctx->pix_fmt = PIX_FMT_RGB24;
  75.     } else if (!strcmp(buf1, "P7")) {
  76.         w = -1;
  77.         h = -1;
  78.         maxval = -1;
  79.         depth = -1;
  80.         tuple_type[0] = '';
  81.         for(;;) {
  82.             pnm_get(s, buf1, sizeof(buf1));
  83.             if (!strcmp(buf1, "WIDTH")) {
  84.                 pnm_get(s, buf1, sizeof(buf1));
  85.                 w = strtol(buf1, NULL, 10);
  86.             } else if (!strcmp(buf1, "HEIGHT")) {
  87.                 pnm_get(s, buf1, sizeof(buf1));
  88.                 h = strtol(buf1, NULL, 10);
  89.             } else if (!strcmp(buf1, "DEPTH")) {
  90.                 pnm_get(s, buf1, sizeof(buf1));
  91.                 depth = strtol(buf1, NULL, 10);
  92.             } else if (!strcmp(buf1, "MAXVAL")) {
  93.                 pnm_get(s, buf1, sizeof(buf1));
  94.                 maxval = strtol(buf1, NULL, 10);
  95.             } else if (!strcmp(buf1, "TUPLETYPE")) {
  96.                 pnm_get(s, tuple_type, sizeof(tuple_type));
  97.             } else if (!strcmp(buf1, "ENDHDR")) {
  98.                 break;
  99.             } else {
  100.                 return -1;
  101.             }
  102.         }
  103.         /* check that all tags are present */
  104.         if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '' || avcodec_check_dimensions(avctx, w, h))
  105.             return -1;
  106.                    
  107.         avctx->width = w;
  108.         avctx->height = h;
  109.         if (depth == 1) {
  110.             if (maxval == 1)
  111.                 avctx->pix_fmt = PIX_FMT_MONOWHITE;
  112.             else 
  113.                 avctx->pix_fmt = PIX_FMT_GRAY8;
  114.         } else if (depth == 3) {
  115.             avctx->pix_fmt = PIX_FMT_RGB24;
  116.         } else if (depth == 4) {
  117.             avctx->pix_fmt = PIX_FMT_RGBA32;
  118.         } else {
  119.             return -1;
  120.         }
  121.         return 0;
  122.     } else {
  123.         return -1;
  124.     }
  125.     pnm_get(s, buf1, sizeof(buf1));
  126.     avctx->width = atoi(buf1);
  127.     if (avctx->width <= 0)
  128.         return -1;
  129.     pnm_get(s, buf1, sizeof(buf1));
  130.     avctx->height = atoi(buf1);
  131.     if(avcodec_check_dimensions(avctx, avctx->width, avctx->height))
  132.         return -1;
  133.     if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
  134.         pnm_get(s, buf1, sizeof(buf1));
  135.     }
  136.     /* more check if YUV420 */
  137.     if (avctx->pix_fmt == PIX_FMT_YUV420P) {
  138.         if ((avctx->width & 1) != 0)
  139.             return -1;
  140.         h = (avctx->height * 2);
  141.         if ((h % 3) != 0)
  142.             return -1;
  143.         h /= 3;
  144.         avctx->height = h;
  145.     }
  146.     return 0;
  147. }
  148. static int pnm_decode_frame(AVCodecContext *avctx, 
  149.                         void *data, int *data_size,
  150.                         uint8_t *buf, int buf_size)
  151. {
  152.     PNMContext * const s = avctx->priv_data;
  153.     AVFrame *picture = data;
  154.     AVFrame * const p= (AVFrame*)&s->picture;
  155.     int i, n, linesize, h;
  156.     unsigned char *ptr;
  157.     s->bytestream_start=
  158.     s->bytestream= buf;
  159.     s->bytestream_end= buf + buf_size;
  160.     
  161.     if(pnm_decode_header(avctx, s) < 0)
  162.         return -1;
  163.     
  164.     if(p->data[0])
  165.         avctx->release_buffer(avctx, p);
  166.     p->reference= 0;
  167.     if(avctx->get_buffer(avctx, p) < 0){
  168.         av_log(avctx, AV_LOG_ERROR, "get_buffer() failedn");
  169.         return -1;
  170.     }
  171.     p->pict_type= FF_I_TYPE;
  172.     p->key_frame= 1;
  173.     
  174.     switch(avctx->pix_fmt) {
  175.     default:
  176.         return -1;
  177.     case PIX_FMT_RGB24:
  178.         n = avctx->width * 3;
  179.         goto do_read;
  180.     case PIX_FMT_GRAY8:
  181.         n = avctx->width;
  182.         goto do_read;
  183.     case PIX_FMT_MONOWHITE:
  184.     case PIX_FMT_MONOBLACK:
  185.         n = (avctx->width + 7) >> 3;
  186.     do_read:
  187.         ptr = p->data[0];
  188.         linesize = p->linesize[0];
  189.         if(s->bytestream + n*avctx->height > s->bytestream_end)
  190.             return -1;
  191.         for(i = 0; i < avctx->height; i++) {
  192.             memcpy(ptr, s->bytestream, n);
  193.             s->bytestream += n;
  194.             ptr += linesize;
  195.         }
  196.         break;
  197.     case PIX_FMT_YUV420P:
  198.         {
  199.             unsigned char *ptr1, *ptr2;
  200.             n = avctx->width;
  201.             ptr = p->data[0];
  202.             linesize = p->linesize[0];
  203.             if(s->bytestream + n*avctx->height*3/2 > s->bytestream_end)
  204.                 return -1;
  205.             for(i = 0; i < avctx->height; i++) {
  206.                 memcpy(ptr, s->bytestream, n);
  207.                 s->bytestream += n;
  208.                 ptr += linesize;
  209.             }
  210.             ptr1 = p->data[1];
  211.             ptr2 = p->data[2];
  212.             n >>= 1;
  213.             h = avctx->height >> 1;
  214.             for(i = 0; i < h; i++) {
  215.                 memcpy(ptr1, s->bytestream, n);
  216.                 s->bytestream += n;
  217.                 memcpy(ptr2, s->bytestream, n);
  218.                 s->bytestream += n;
  219.                 ptr1 += p->linesize[1];
  220.                 ptr2 += p->linesize[2];
  221.             }
  222.         }
  223.         break;
  224.     case PIX_FMT_RGBA32:
  225.         ptr = p->data[0];
  226.         linesize = p->linesize[0];
  227.         if(s->bytestream + avctx->width*avctx->height*4 > s->bytestream_end)
  228.             return -1;
  229.         for(i = 0; i < avctx->height; i++) {
  230.             int j, r, g, b, a;
  231.             for(j = 0;j < avctx->width; j++) {
  232.                 r = *s->bytestream++;
  233.                 g = *s->bytestream++;
  234.                 b = *s->bytestream++;
  235.                 a = *s->bytestream++;
  236.                 ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
  237.             }
  238.             ptr += linesize;
  239.         }
  240.         break;
  241.     }
  242.     *picture= *(AVFrame*)&s->picture;
  243.     *data_size = sizeof(AVPicture);
  244.     return s->bytestream - s->bytestream_start;
  245. }
  246. static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
  247.     PNMContext *s = avctx->priv_data;
  248.     AVFrame *pict = data;
  249.     AVFrame * const p= (AVFrame*)&s->picture;
  250.     int i, h, h1, c, n, linesize;
  251.     uint8_t *ptr, *ptr1, *ptr2;
  252.     if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
  253.         av_log(avctx, AV_LOG_ERROR, "encoded frame too largen");
  254.         return -1;
  255.     }
  256.     *p = *pict;
  257.     p->pict_type= FF_I_TYPE;
  258.     p->key_frame= 1;
  259.     
  260.     s->bytestream_start=
  261.     s->bytestream= outbuf;
  262.     s->bytestream_end= outbuf+buf_size;
  263.     h = avctx->height;
  264.     h1 = h;
  265.     switch(avctx->pix_fmt) {
  266.     case PIX_FMT_MONOWHITE:
  267.         c = '4';
  268.         n = (avctx->width + 7) >> 3;
  269.         break;
  270.     case PIX_FMT_GRAY8:
  271.         c = '5';
  272.         n = avctx->width;
  273.         break;
  274.     case PIX_FMT_RGB24:
  275.         c = '6';
  276.         n = avctx->width * 3;
  277.         break;
  278.     case PIX_FMT_YUV420P:
  279.         c = '5';
  280.         n = avctx->width;
  281.         h1 = (h * 3) / 2;
  282.         break;
  283.     default:
  284.         return -1;
  285.     }
  286.     snprintf(s->bytestream, s->bytestream_end - s->bytestream, 
  287.              "P%cn%d %dn",
  288.              c, avctx->width, h1);
  289.     s->bytestream += strlen(s->bytestream);
  290.     if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
  291.         snprintf(s->bytestream, s->bytestream_end - s->bytestream, 
  292.                  "%dn", 255);
  293.         s->bytestream += strlen(s->bytestream);
  294.     }
  295.     ptr = p->data[0];
  296.     linesize = p->linesize[0];
  297.     for(i=0;i<h;i++) {
  298.         memcpy(s->bytestream, ptr, n);
  299.         s->bytestream += n;
  300.         ptr += linesize;
  301.     }
  302.     
  303.     if (avctx->pix_fmt == PIX_FMT_YUV420P) {
  304.         h >>= 1;
  305.         n >>= 1;
  306.         ptr1 = p->data[1];
  307.         ptr2 = p->data[2];
  308.         for(i=0;i<h;i++) {
  309.             memcpy(s->bytestream, ptr1, n);
  310.             s->bytestream += n;
  311.             memcpy(s->bytestream, ptr2, n);
  312.             s->bytestream += n;
  313.                 ptr1 += p->linesize[1];
  314.                 ptr2 += p->linesize[2];
  315.         }
  316.     }
  317.     return s->bytestream - s->bytestream_start;
  318. }
  319. static int pam_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
  320.     PNMContext *s = avctx->priv_data;
  321.     AVFrame *pict = data;
  322.     AVFrame * const p= (AVFrame*)&s->picture;
  323.     int i, h, w, n, linesize, depth, maxval;
  324.     const char *tuple_type;
  325.     uint8_t *ptr;
  326.     if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
  327.         av_log(avctx, AV_LOG_ERROR, "encoded frame too largen");
  328.         return -1;
  329.     }
  330.     *p = *pict;
  331.     p->pict_type= FF_I_TYPE;
  332.     p->key_frame= 1;
  333.     
  334.     s->bytestream_start=
  335.     s->bytestream= outbuf;
  336.     s->bytestream_end= outbuf+buf_size;
  337.     h = avctx->height;
  338.     w = avctx->width;
  339.     switch(avctx->pix_fmt) {
  340.     case PIX_FMT_MONOWHITE:
  341.         n = (w + 7) >> 3;
  342.         depth = 1;
  343.         maxval = 1;
  344.         tuple_type = "BLACKANDWHITE";
  345.         break;
  346.     case PIX_FMT_GRAY8:
  347.         n = w;
  348.         depth = 1;
  349.         maxval = 255;
  350.         tuple_type = "GRAYSCALE";
  351.         break;
  352.     case PIX_FMT_RGB24:
  353.         n = w * 3;
  354.         depth = 3;
  355.         maxval = 255;
  356.         tuple_type = "RGB";
  357.         break;
  358.     case PIX_FMT_RGBA32:
  359.         n = w * 4;
  360.         depth = 4;
  361.         maxval = 255;
  362.         tuple_type = "RGB_ALPHA";
  363.         break;
  364.     default:
  365.         return -1;
  366.     }
  367.     snprintf(s->bytestream, s->bytestream_end - s->bytestream, 
  368.              "P7nWIDTH %dnHEIGHT %dnDEPTH %dnMAXVAL %dnTUPLETYPE %snENDHDRn",
  369.              w, h, depth, maxval, tuple_type);
  370.     s->bytestream += strlen(s->bytestream);
  371.     
  372.     ptr = p->data[0];
  373.     linesize = p->linesize[0];
  374.     
  375.     if (avctx->pix_fmt == PIX_FMT_RGBA32) {
  376.         int j;
  377.         unsigned int v;
  378.         for(i=0;i<h;i++) {
  379.             for(j=0;j<w;j++) {
  380.                 v = ((uint32_t *)ptr)[j];
  381.                 *s->bytestream++ = v >> 16;
  382.                 *s->bytestream++ = v >> 8;
  383.                 *s->bytestream++ = v;
  384.                 *s->bytestream++ = v >> 24;
  385.             }
  386.             ptr += linesize;
  387.         }
  388.     } else {
  389.         for(i=0;i<h;i++) {
  390.             memcpy(s->bytestream, ptr, n);
  391.             s->bytestream += n;
  392.             ptr += linesize;
  393.         }
  394.     }
  395.     return s->bytestream - s->bytestream_start;
  396. }
  397. #if 0
  398. static int pnm_probe(AVProbeData *pd)
  399. {
  400.     const char *p = pd->buf;
  401.     if (pd->buf_size >= 8 &&
  402.         p[0] == 'P' &&
  403.         p[1] >= '4' && p[1] <= '6' &&
  404.         pnm_space(p[2]) )
  405.         return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
  406.     else
  407.         return 0;
  408. }
  409. static int pgmyuv_probe(AVProbeData *pd)
  410. {
  411.     if (match_ext(pd->filename, "pgmyuv"))
  412.         return AVPROBE_SCORE_MAX;
  413.     else
  414.         return 0;
  415. }
  416. static int pam_probe(AVProbeData *pd)
  417. {
  418.     const char *p = pd->buf;
  419.     if (pd->buf_size >= 8 &&
  420.         p[0] == 'P' &&
  421.         p[1] == '7' &&
  422.         p[2] == 'n')
  423.         return AVPROBE_SCORE_MAX;
  424.     else
  425.         return 0;
  426. }
  427. #endif
  428. static int pnm_parse(AVCodecParserContext *s,
  429.                            AVCodecContext *avctx,
  430.                            uint8_t **poutbuf, int *poutbuf_size, 
  431.                            const uint8_t *buf, int buf_size)
  432. {
  433.     ParseContext *pc = s->priv_data;
  434.     PNMContext pnmctx;
  435.     int next;
  436.     for(; pc->overread>0; pc->overread--){
  437.         pc->buffer[pc->index++]= pc->buffer[pc->overread_index++];
  438.     }
  439. retry:
  440.     if(pc->index){
  441.         pnmctx.bytestream_start=
  442.         pnmctx.bytestream= pc->buffer;
  443.         pnmctx.bytestream_end= pc->buffer + pc->index;
  444.     }else{
  445.         pnmctx.bytestream_start=
  446.         pnmctx.bytestream= (uint8_t *) buf; /* casts avoid warnings */
  447.         pnmctx.bytestream_end= (uint8_t *) buf + buf_size;
  448.     }
  449.     if(pnm_decode_header(avctx, &pnmctx) < 0){
  450.         if(pnmctx.bytestream < pnmctx.bytestream_end){
  451.             if(pc->index){
  452.                 pc->index=0;
  453.             }else{
  454.                 buf++;
  455.                 buf_size--;
  456.             }
  457.             goto retry;
  458.         }
  459. #if 0
  460.         if(pc->index && pc->index*2 + FF_INPUT_BUFFER_PADDING_SIZE < pc->buffer_size && buf_size > pc->index){
  461.             memcpy(pc->buffer + pc->index, buf, pc->index);
  462.             pc->index += pc->index;
  463.             buf += pc->index;
  464.             buf_size -= pc->index;
  465.             goto retry;
  466.         }
  467. #endif
  468.         next= END_NOT_FOUND;
  469.     }else{
  470.         next= pnmctx.bytestream - pnmctx.bytestream_start 
  471.             + avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height);
  472.         if(pnmctx.bytestream_start!=buf)
  473.             next-= pc->index;
  474.         if(next > buf_size)
  475.             next= END_NOT_FOUND;
  476.     }
  477.     
  478.     if(ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size)<0){
  479.         *poutbuf = NULL;
  480.         *poutbuf_size = 0;
  481.         return buf_size;
  482.     }
  483.     *poutbuf = (uint8_t *)buf;
  484.     *poutbuf_size = buf_size;
  485.     return next;
  486. }
  487. AVCodecParser pnm_parser = {
  488.     { CODEC_ID_PGM, CODEC_ID_PGMYUV, CODEC_ID_PPM, CODEC_ID_PBM, CODEC_ID_PAM},
  489.     sizeof(ParseContext),
  490.     NULL,
  491.     pnm_parse,
  492.     ff_parse_close,
  493. };
  494. #ifdef CONFIG_PGM_ENCODER
  495. AVCodec pgm_encoder = {
  496.     "pgm",
  497.     CODEC_TYPE_VIDEO,
  498.     CODEC_ID_PGM,
  499.     sizeof(PNMContext),
  500.     common_init,
  501.     pnm_encode_frame,
  502.     NULL, //encode_end,
  503.     pnm_decode_frame,
  504.     .pix_fmts= (enum PixelFormat[]){PIX_FMT_GRAY8, -1}, 
  505. };
  506. #endif // CONFIG_PGM_ENCODER
  507. #ifdef CONFIG_PGMYUV_ENCODER
  508. AVCodec pgmyuv_encoder = {
  509.     "pgmyuv",
  510.     CODEC_TYPE_VIDEO,
  511.     CODEC_ID_PGMYUV,
  512.     sizeof(PNMContext),
  513.     common_init,
  514.     pnm_encode_frame,
  515.     NULL, //encode_end,
  516.     pnm_decode_frame,
  517.     .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1}, 
  518. };
  519. #endif // CONFIG_PGMYUV_ENCODER
  520. #ifdef CONFIG_PPM_ENCODER
  521. AVCodec ppm_encoder = {
  522.     "ppm",
  523.     CODEC_TYPE_VIDEO,
  524.     CODEC_ID_PPM,
  525.     sizeof(PNMContext),
  526.     common_init,
  527.     pnm_encode_frame,
  528.     NULL, //encode_end,
  529.     pnm_decode_frame,
  530.     .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, -1}, 
  531. };
  532. #endif // CONFIG_PPM_ENCODER
  533. #ifdef CONFIG_PBM_ENCODER
  534. AVCodec pbm_encoder = {
  535.     "pbm",
  536.     CODEC_TYPE_VIDEO,
  537.     CODEC_ID_PBM,
  538.     sizeof(PNMContext),
  539.     common_init,
  540.     pnm_encode_frame,
  541.     NULL, //encode_end,
  542.     pnm_decode_frame,
  543.     .pix_fmts= (enum PixelFormat[]){PIX_FMT_MONOWHITE, -1}, 
  544. };
  545. #endif // CONFIG_PBM_ENCODER
  546. #ifdef CONFIG_PAM_ENCODER
  547. AVCodec pam_encoder = {
  548.     "pam",
  549.     CODEC_TYPE_VIDEO,
  550.     CODEC_ID_PAM,
  551.     sizeof(PNMContext),
  552.     common_init,
  553.     pam_encode_frame,
  554.     NULL, //encode_end,
  555.     pnm_decode_frame,
  556.     .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA32, PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, -1}, 
  557. };
  558. #endif // CONFIG_PAM_ENCODER