Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * BRender PIX (.pix) image decoder
  3.  * Copyright (c) 2012 Aleksi Nurmi
  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. /*
  23.  * Tested against samples from I-War / Independence War and Defiance.
  24.  * If the PIX file does not contain a palette, the
  25.  * palette_has_changed property of the AVFrame is set to 0.
  26.  */
  27.  
  28. #include "libavutil/imgutils.h"
  29. #include "avcodec.h"
  30. #include "bytestream.h"
  31. #include "internal.h"
  32.  
  33. typedef struct BRPixHeader {
  34.     int format;
  35.     unsigned int width, height;
  36. } BRPixHeader;
  37.  
  38. static int brpix_decode_header(BRPixHeader *out, GetByteContext *pgb)
  39. {
  40.     unsigned int header_len = bytestream2_get_be32(pgb);
  41.  
  42.     out->format = bytestream2_get_byte(pgb);
  43.     bytestream2_skip(pgb, 2);
  44.     out->width = bytestream2_get_be16(pgb);
  45.     out->height = bytestream2_get_be16(pgb);
  46.  
  47.     // the header is at least 11 bytes long; we read the first 7
  48.     if (header_len < 11) {
  49.         return 0;
  50.     }
  51.  
  52.     // skip the rest of the header
  53.     bytestream2_skip(pgb, header_len-7);
  54.  
  55.     return 1;
  56. }
  57.  
  58. static int brpix_decode_frame(AVCodecContext *avctx,
  59.                               void *data, int *got_frame,
  60.                               AVPacket *avpkt)
  61. {
  62.     AVFrame *frame = data;
  63.  
  64.     int ret;
  65.     GetByteContext gb;
  66.  
  67.     unsigned int bytes_pp;
  68.  
  69.     unsigned int magic[4];
  70.     unsigned int chunk_type;
  71.     unsigned int data_len;
  72.     BRPixHeader hdr;
  73.  
  74.     bytestream2_init(&gb, avpkt->data, avpkt->size);
  75.  
  76.     magic[0] = bytestream2_get_be32(&gb);
  77.     magic[1] = bytestream2_get_be32(&gb);
  78.     magic[2] = bytestream2_get_be32(&gb);
  79.     magic[3] = bytestream2_get_be32(&gb);
  80.  
  81.     if (magic[0] != 0x12 ||
  82.         magic[1] != 0x8 ||
  83.         magic[2] != 0x2 ||
  84.         magic[3] != 0x2) {
  85.         av_log(avctx, AV_LOG_ERROR, "Not a BRender PIX file\n");
  86.         return AVERROR_INVALIDDATA;
  87.     }
  88.  
  89.     chunk_type = bytestream2_get_be32(&gb);
  90.     if (chunk_type != 0x3 && chunk_type != 0x3d) {
  91.         av_log(avctx, AV_LOG_ERROR, "Invalid chunk type %d\n", chunk_type);
  92.         return AVERROR_INVALIDDATA;
  93.     }
  94.  
  95.     ret = brpix_decode_header(&hdr, &gb);
  96.     if (!ret) {
  97.         av_log(avctx, AV_LOG_ERROR, "Invalid header length\n");
  98.         return AVERROR_INVALIDDATA;
  99.     }
  100.     switch (hdr.format) {
  101.     case 3:
  102.         avctx->pix_fmt = AV_PIX_FMT_PAL8;
  103.         bytes_pp = 1;
  104.         break;
  105.     case 4:
  106.         avctx->pix_fmt = AV_PIX_FMT_RGB555BE;
  107.         bytes_pp = 2;
  108.         break;
  109.     case 5:
  110.         avctx->pix_fmt = AV_PIX_FMT_RGB565BE;
  111.         bytes_pp = 2;
  112.         break;
  113.     case 6:
  114.         avctx->pix_fmt = AV_PIX_FMT_RGB24;
  115.         bytes_pp = 3;
  116.         break;
  117.     case 7:
  118.         avctx->pix_fmt = AV_PIX_FMT_0RGB;
  119.         bytes_pp = 4;
  120.         break;
  121.     case 18:
  122.         avctx->pix_fmt = AV_PIX_FMT_GRAY8A;
  123.         bytes_pp = 2;
  124.         break;
  125.     default:
  126.         av_log(avctx, AV_LOG_ERROR, "Format %d is not supported\n",
  127.                                     hdr.format);
  128.         return AVERROR_PATCHWELCOME;
  129.     }
  130.  
  131.     if (av_image_check_size(hdr.width, hdr.height, 0, avctx) < 0)
  132.         return AVERROR_INVALIDDATA;
  133.  
  134.     if (hdr.width != avctx->width || hdr.height != avctx->height)
  135.         avcodec_set_dimensions(avctx, hdr.width, hdr.height);
  136.  
  137.     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
  138.         return ret;
  139.  
  140.     chunk_type = bytestream2_get_be32(&gb);
  141.  
  142.     if (avctx->pix_fmt == AV_PIX_FMT_PAL8 &&
  143.         (chunk_type == 0x3 || chunk_type == 0x3d)) {
  144.         BRPixHeader palhdr;
  145.         uint32_t *pal_out = (uint32_t *)frame->data[1];
  146.         int i;
  147.  
  148.         ret = brpix_decode_header(&palhdr, &gb);
  149.         if (!ret) {
  150.             av_log(avctx, AV_LOG_ERROR, "Invalid palette header length\n");
  151.             return AVERROR_INVALIDDATA;
  152.         }
  153.         if (palhdr.format != 7) {
  154.             av_log(avctx, AV_LOG_ERROR, "Palette is not in 0RGB format\n");
  155.             return AVERROR_INVALIDDATA;
  156.         }
  157.  
  158.         chunk_type = bytestream2_get_be32(&gb);
  159.         data_len = bytestream2_get_be32(&gb);
  160.         bytestream2_skip(&gb, 8);
  161.         if (chunk_type != 0x21 || data_len != 1032 ||
  162.             bytestream2_get_bytes_left(&gb) < 1032) {
  163.             av_log(avctx, AV_LOG_ERROR, "Invalid palette data\n");
  164.             return AVERROR_INVALIDDATA;
  165.         }
  166.         // convert 0RGB to machine endian format (ARGB32)
  167.         for (i = 0; i < 256; ++i) {
  168.             bytestream2_skipu(&gb, 1);
  169.             *pal_out++ = (0xFFU << 24) | bytestream2_get_be24u(&gb);
  170.         }
  171.         bytestream2_skip(&gb, 8);
  172.  
  173.         frame->palette_has_changed = 1;
  174.  
  175.         chunk_type = bytestream2_get_be32(&gb);
  176.     } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
  177.         uint32_t *pal_out = (uint32_t *)frame->data[1];
  178.         int i;
  179.  
  180.         for (i = 0; i < 256; ++i) {
  181.             *pal_out++ = (0xFFU << 24) | (i * 0x010101);
  182.         }
  183.         frame->palette_has_changed = 1;
  184.     }
  185.  
  186.     data_len = bytestream2_get_be32(&gb);
  187.     bytestream2_skip(&gb, 8);
  188.  
  189.     // read the image data to the buffer
  190.     {
  191.         unsigned int bytes_per_scanline = bytes_pp * hdr.width;
  192.         unsigned int bytes_left = bytestream2_get_bytes_left(&gb);
  193.  
  194.         if (chunk_type != 0x21 || data_len != bytes_left ||
  195.             bytes_left / bytes_per_scanline < hdr.height)
  196.         {
  197.             av_log(avctx, AV_LOG_ERROR, "Invalid image data\n");
  198.             return AVERROR_INVALIDDATA;
  199.         }
  200.  
  201.         av_image_copy_plane(frame->data[0], frame->linesize[0],
  202.                             avpkt->data + bytestream2_tell(&gb),
  203.                             bytes_per_scanline,
  204.                             bytes_per_scanline, hdr.height);
  205.     }
  206.  
  207.     *got_frame = 1;
  208.  
  209.     return avpkt->size;
  210. }
  211.  
  212. AVCodec ff_brender_pix_decoder = {
  213.     .name           = "brender_pix",
  214.     .long_name      = NULL_IF_CONFIG_SMALL("BRender PIX image"),
  215.     .type           = AVMEDIA_TYPE_VIDEO,
  216.     .id             = AV_CODEC_ID_BRENDER_PIX,
  217.     .decode         = brpix_decode_frame,
  218.     .capabilities   = CODEC_CAP_DR1,
  219. };
  220.