Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Alias PIX image decoder
  3.  * Copyright (C) 2014 Vittorio Giovara <vittorio.giovara@gmail.com>
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. #include "libavutil/intreadwrite.h"
  23.  
  24. #include "avcodec.h"
  25. #include "bytestream.h"
  26. #include "internal.h"
  27.  
  28. #define ALIAS_HEADER_SIZE 10
  29.  
  30. static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
  31.                         AVPacket *avpkt)
  32. {
  33.     AVFrame *f = data;
  34.     GetByteContext gb;
  35.     int width, height, ret, bits_pixel, pixel;
  36.     uint8_t *out_buf;
  37.     uint8_t count;
  38.     int x, y;
  39.  
  40.     bytestream2_init(&gb, avpkt->data, avpkt->size);
  41.  
  42.     if (bytestream2_get_bytes_left(&gb) < ALIAS_HEADER_SIZE) {
  43.         av_log(avctx, AV_LOG_ERROR, "Header too small %d.\n", avpkt->size);
  44.         return AVERROR_INVALIDDATA;
  45.     }
  46.  
  47.     width  = bytestream2_get_be16u(&gb);
  48.     height = bytestream2_get_be16u(&gb);
  49.     bytestream2_skipu(&gb, 4); // obsolete X, Y offset
  50.     bits_pixel = bytestream2_get_be16u(&gb);
  51.  
  52.     if (bits_pixel == 24)
  53.         avctx->pix_fmt = AV_PIX_FMT_BGR24;
  54.     else if (bits_pixel == 8)
  55.         avctx->pix_fmt = AV_PIX_FMT_GRAY8;
  56.     else {
  57.         av_log(avctx, AV_LOG_ERROR, "Invalid pixel format.\n");
  58.         return AVERROR_INVALIDDATA;
  59.     }
  60.  
  61.     ret = ff_set_dimensions(avctx, width, height);
  62.     if (ret < 0)
  63.         return ret;
  64.  
  65.     ret = ff_get_buffer(avctx, f, 0);
  66.     if (ret < 0)
  67.         return ret;
  68.  
  69.     f->pict_type = AV_PICTURE_TYPE_I;
  70.     f->key_frame = 1;
  71.  
  72.     x = 0;
  73.     y = 1;
  74.     out_buf = f->data[0];
  75.     while (bytestream2_get_bytes_left(&gb) > 0) {
  76.         int i;
  77.  
  78.         /* set buffer at the right position at every new line */
  79.         if (x == avctx->width) {
  80.             x = 0;
  81.             out_buf = f->data[0] + f->linesize[0] * y++;
  82.             if (y > avctx->height) {
  83.                 av_log(avctx, AV_LOG_ERROR,
  84.                        "Ended frame decoding with %d bytes left.\n",
  85.                        bytestream2_get_bytes_left(&gb));
  86.                 return AVERROR_INVALIDDATA;
  87.             }
  88.         }
  89.  
  90.         /* read packet and copy data */
  91.         count = bytestream2_get_byteu(&gb);
  92.         if (!count || x + count > avctx->width) {
  93.             av_log(avctx, AV_LOG_ERROR, "Invalid run length %d.\n", count);
  94.             return AVERROR_INVALIDDATA;
  95.         }
  96.  
  97.         if (avctx->pix_fmt == AV_PIX_FMT_BGR24) {
  98.             pixel = bytestream2_get_be24(&gb);
  99.             for (i = 0; i < count; i++) {
  100.                 AV_WB24(out_buf, pixel);
  101.                 out_buf += 3;
  102.             }
  103.         } else { // AV_PIX_FMT_GRAY8
  104.             pixel = bytestream2_get_byte(&gb);
  105.             for (i = 0; i < count; i++)
  106.                 *out_buf++ = pixel;
  107.         }
  108.  
  109.         x += i;
  110.     }
  111.  
  112.     if (x != width || y != height) {
  113.         av_log(avctx, AV_LOG_ERROR, "Picture stopped at %d,%d.\n", x, y);
  114.         return AVERROR_INVALIDDATA;
  115.     }
  116.  
  117.     *got_frame = 1;
  118.     return avpkt->size;
  119. }
  120.  
  121. AVCodec ff_alias_pix_decoder = {
  122.     .name         = "alias_pix",
  123.     .long_name    = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"),
  124.     .type         = AVMEDIA_TYPE_VIDEO,
  125.     .id           = AV_CODEC_ID_ALIAS_PIX,
  126.     .decode       = decode_frame,
  127.     .capabilities = AV_CODEC_CAP_DR1,
  128. };
  129.