Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * XBM image format
  3.  *
  4.  * Copyright (c) 2012 Paul B Mahol
  5.  *
  6.  * This file is part of FFmpeg.
  7.  *
  8.  * FFmpeg is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Lesser General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2.1 of the License, or (at your option) any later version.
  12.  *
  13.  * FFmpeg is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Lesser General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Lesser General Public
  19.  * License along with FFmpeg; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21.  */
  22.  
  23. #include "libavutil/avstring.h"
  24.  
  25. #include "avcodec.h"
  26. #include "internal.h"
  27. #include "mathops.h"
  28.  
  29. static int convert(uint8_t x)
  30. {
  31.     if (x >= 'a')
  32.         x -= 87;
  33.     else if (x >= 'A')
  34.         x -= 55;
  35.     else
  36.         x -= '0';
  37.     return x;
  38. }
  39.  
  40. static int parse_str_int(const uint8_t *p, int len, const uint8_t *key)
  41. {
  42.     const uint8_t *end = p + len;
  43.  
  44.     for(; p<end - strlen(key); p++) {
  45.         if (!memcmp(p, key, strlen(key)))
  46.             break;
  47.     }
  48.     p += strlen(key);
  49.     if (p >= end)
  50.         return INT_MIN;
  51.  
  52.     for(; p<end; p++) {
  53.         char *eptr;
  54.         int64_t ret = strtol(p, &eptr, 10);
  55.         if ((const uint8_t *)eptr != p)
  56.             return ret;
  57.     }
  58.     return INT_MIN;
  59. }
  60.  
  61. static int xbm_decode_frame(AVCodecContext *avctx, void *data,
  62.                             int *got_frame, AVPacket *avpkt)
  63. {
  64.     AVFrame *p = data;
  65.     int ret, linesize, i, j;
  66.     int width  = 0;
  67.     int height = 0;
  68.     const uint8_t *end, *ptr = avpkt->data;
  69.     const uint8_t *next;
  70.     uint8_t *dst;
  71.  
  72.     avctx->pix_fmt = AV_PIX_FMT_MONOWHITE;
  73.     end = avpkt->data + avpkt->size;
  74.  
  75.     width  = parse_str_int(avpkt->data, avpkt->size, "_width");
  76.     height = parse_str_int(avpkt->data, avpkt->size, "_height");
  77.  
  78.     if ((ret = ff_set_dimensions(avctx, width, height)) < 0)
  79.         return ret;
  80.  
  81.     if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
  82.         return ret;
  83.  
  84.     // goto start of image data
  85.     next = memchr(ptr, '{', avpkt->size);
  86.     if (!next)
  87.         next = memchr(ptr, '(', avpkt->size);
  88.     if (!next)
  89.         return AVERROR_INVALIDDATA;
  90.     ptr = next + 1;
  91.  
  92.     linesize = (avctx->width + 7) / 8;
  93.     for (i = 0; i < avctx->height; i++) {
  94.         dst = p->data[0] + i * p->linesize[0];
  95.         for (j = 0; j < linesize; j++) {
  96.             uint8_t val;
  97.  
  98.             while (ptr < end && *ptr != 'x' && *ptr != '$')
  99.                 ptr++;
  100.  
  101.             ptr ++;
  102.             if (ptr < end && av_isxdigit(*ptr)) {
  103.                 val = convert(*ptr++);
  104.                 if (av_isxdigit(*ptr))
  105.                     val = (val << 4) + convert(*ptr++);
  106.                 *dst++ = ff_reverse[val];
  107.                 if (av_isxdigit(*ptr) && j+1 < linesize) {
  108.                     j++;
  109.                     val = convert(*ptr++);
  110.                     if (av_isxdigit(*ptr))
  111.                         val = (val << 4) + convert(*ptr++);
  112.                     *dst++ = ff_reverse[val];
  113.                 }
  114.             } else {
  115.                 av_log(avctx, AV_LOG_ERROR,
  116.                        "Unexpected data at %.8s.\n", ptr);
  117.                 return AVERROR_INVALIDDATA;
  118.             }
  119.         }
  120.     }
  121.  
  122.     p->key_frame = 1;
  123.     p->pict_type = AV_PICTURE_TYPE_I;
  124.  
  125.     *got_frame       = 1;
  126.  
  127.     return avpkt->size;
  128. }
  129.  
  130. AVCodec ff_xbm_decoder = {
  131.     .name         = "xbm",
  132.     .long_name    = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"),
  133.     .type         = AVMEDIA_TYPE_VIDEO,
  134.     .id           = AV_CODEC_ID_XBM,
  135.     .decode       = xbm_decode_frame,
  136.     .capabilities = AV_CODEC_CAP_DR1,
  137. };
  138.