LCOV - code coverage report
Current view: top level - libavcodec - xan.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 245 291 84.2 %
Date: 2017-12-14 19:11:59 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Wing Commander/Xan Video Decoder
       3             :  * Copyright (C) 2003 The FFmpeg project
       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             :  * @file
      24             :  * Xan video decoder for Wing Commander III computer game
      25             :  * by Mario Brito (mbrito@student.dei.uc.pt)
      26             :  * and Mike Melanson (melanson@pcisys.net)
      27             :  *
      28             :  * The xan_wc3 decoder outputs PAL8 data.
      29             :  */
      30             : 
      31             : #include <stdio.h>
      32             : #include <stdlib.h>
      33             : #include <string.h>
      34             : 
      35             : #include "libavutil/intreadwrite.h"
      36             : #include "libavutil/mem.h"
      37             : 
      38             : #define BITSTREAM_READER_LE
      39             : #include "avcodec.h"
      40             : #include "bytestream.h"
      41             : #include "get_bits.h"
      42             : #include "internal.h"
      43             : 
      44             : #define RUNTIME_GAMMA 0
      45             : 
      46             : #define VGA__TAG MKTAG('V', 'G', 'A', ' ')
      47             : #define PALT_TAG MKTAG('P', 'A', 'L', 'T')
      48             : #define SHOT_TAG MKTAG('S', 'H', 'O', 'T')
      49             : #define PALETTE_COUNT 256
      50             : #define PALETTE_SIZE (PALETTE_COUNT * 3)
      51             : #define PALETTES_MAX 256
      52             : 
      53             : typedef struct XanContext {
      54             : 
      55             :     AVCodecContext *avctx;
      56             :     AVFrame *last_frame;
      57             : 
      58             :     const uint8_t *buf;
      59             :     int size;
      60             : 
      61             :     /* scratch space */
      62             :     uint8_t *buffer1;
      63             :     int buffer1_size;
      64             :     uint8_t *buffer2;
      65             :     int buffer2_size;
      66             : 
      67             :     unsigned *palettes;
      68             :     int palettes_count;
      69             :     int cur_palette;
      70             : 
      71             :     int frame_size;
      72             : 
      73             : } XanContext;
      74             : 
      75           2 : static av_cold int xan_decode_end(AVCodecContext *avctx)
      76             : {
      77           2 :     XanContext *s = avctx->priv_data;
      78             : 
      79           2 :     av_frame_free(&s->last_frame);
      80             : 
      81           2 :     av_freep(&s->buffer1);
      82           2 :     av_freep(&s->buffer2);
      83           2 :     av_freep(&s->palettes);
      84             : 
      85           2 :     return 0;
      86             : }
      87             : 
      88           2 : static av_cold int xan_decode_init(AVCodecContext *avctx)
      89             : {
      90           2 :     XanContext *s = avctx->priv_data;
      91             : 
      92           2 :     s->avctx = avctx;
      93           2 :     s->frame_size = 0;
      94             : 
      95           2 :     avctx->pix_fmt = AV_PIX_FMT_PAL8;
      96             : 
      97           2 :     s->buffer1_size = avctx->width * avctx->height;
      98           2 :     s->buffer1 = av_malloc(s->buffer1_size);
      99           2 :     if (!s->buffer1)
     100           0 :         return AVERROR(ENOMEM);
     101           2 :     s->buffer2_size = avctx->width * avctx->height;
     102           2 :     s->buffer2 = av_malloc(s->buffer2_size + 130);
     103           2 :     if (!s->buffer2) {
     104           0 :         av_freep(&s->buffer1);
     105           0 :         return AVERROR(ENOMEM);
     106             :     }
     107             : 
     108           2 :     s->last_frame = av_frame_alloc();
     109           2 :     if (!s->last_frame) {
     110           0 :         xan_decode_end(avctx);
     111           0 :         return AVERROR(ENOMEM);
     112             :     }
     113             : 
     114           2 :     return 0;
     115             : }
     116             : 
     117          35 : static int xan_huffman_decode(uint8_t *dest, int dest_len,
     118             :                               const uint8_t *src, int src_len)
     119             : {
     120          35 :     uint8_t byte = *src++;
     121          35 :     uint8_t ival = byte + 0x16;
     122          35 :     const uint8_t * ptr = src + byte*2;
     123          35 :     int ptr_len = src_len - 1 - byte*2;
     124          35 :     uint8_t val = ival;
     125          35 :     uint8_t *dest_end = dest + dest_len;
     126          35 :     uint8_t *dest_start = dest;
     127             :     int ret;
     128             :     GetBitContext gb;
     129             : 
     130          35 :     if ((ret = init_get_bits8(&gb, ptr, ptr_len)) < 0)
     131           0 :         return ret;
     132             : 
     133      568526 :     while (val != 0x16) {
     134             :         unsigned idx;
     135      568456 :         if (get_bits_left(&gb) < 1)
     136           0 :             return AVERROR_INVALIDDATA;
     137      568456 :         idx = val - 0x17 + get_bits1(&gb) * byte;
     138      568456 :         if (idx >= 2 * byte)
     139           0 :             return AVERROR_INVALIDDATA;
     140      568456 :         val = src[idx];
     141             : 
     142      568456 :         if (val < 0x16) {
     143      170624 :             if (dest >= dest_end)
     144           0 :                 return dest_len;
     145      170624 :             *dest++ = val;
     146      170624 :             val = ival;
     147             :         }
     148             :     }
     149             : 
     150          35 :     return dest - dest_start;
     151             : }
     152             : 
     153             : /**
     154             :  * unpack simple compression
     155             :  *
     156             :  * @param dest destination buffer of dest_len, must be padded with at least 130 bytes
     157             :  */
     158          21 : static void xan_unpack(uint8_t *dest, int dest_len,
     159             :                        const uint8_t *src, int src_len)
     160             : {
     161             :     uint8_t opcode;
     162             :     int size;
     163          21 :     uint8_t *dest_org = dest;
     164          21 :     uint8_t *dest_end = dest + dest_len;
     165             :     GetByteContext ctx;
     166             : 
     167          21 :     bytestream2_init(&ctx, src, src_len);
     168          21 :     while (dest < dest_end && bytestream2_get_bytes_left(&ctx)) {
     169       29043 :         opcode = bytestream2_get_byte(&ctx);
     170             : 
     171       29043 :         if (opcode < 0xe0) {
     172             :             int size2, back;
     173       22017 :             if ((opcode & 0x80) == 0) {
     174       17508 :                 size = opcode & 3;
     175             : 
     176       17508 :                 back  = ((opcode & 0x60) << 3) + bytestream2_get_byte(&ctx) + 1;
     177       17508 :                 size2 = ((opcode & 0x1c) >> 2) + 3;
     178        4509 :             } else if ((opcode & 0x40) == 0) {
     179        4241 :                 size = bytestream2_peek_byte(&ctx) >> 6;
     180             : 
     181        4241 :                 back  = (bytestream2_get_be16(&ctx) & 0x3fff) + 1;
     182        4241 :                 size2 = (opcode & 0x3f) + 4;
     183             :             } else {
     184         268 :                 size = opcode & 3;
     185             : 
     186         268 :                 back  = ((opcode & 0x10) << 12) + bytestream2_get_be16(&ctx) + 1;
     187         268 :                 size2 = ((opcode & 0x0c) <<  6) + bytestream2_get_byte(&ctx) + 5;
     188             :             }
     189             : 
     190       44034 :             if (dest_end - dest < size + size2 ||
     191       44034 :                 dest + size - dest_org < back ||
     192       22017 :                 bytestream2_get_bytes_left(&ctx) < size)
     193          20 :                 return;
     194       22017 :             bytestream2_get_buffer(&ctx, dest, size);
     195       22017 :             dest += size;
     196       22017 :             av_memcpy_backptr(dest, back, size2);
     197       22017 :             dest += size2;
     198             :         } else {
     199        7026 :             int finish = opcode >= 0xfc;
     200        7026 :             size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
     201             : 
     202        7026 :             if (dest_end - dest < size || bytestream2_get_bytes_left(&ctx) < size)
     203           0 :                 return;
     204        7026 :             bytestream2_get_buffer(&ctx, dest, size);
     205        7026 :             dest += size;
     206        7026 :             if (finish)
     207          20 :                 return;
     208             :         }
     209             :     }
     210             : }
     211             : 
     212       50368 : static inline void xan_wc3_output_pixel_run(XanContext *s, AVFrame *frame,
     213             :     const uint8_t *pixel_buffer, int x, int y, int pixel_count)
     214             : {
     215             :     int stride;
     216             :     int line_inc;
     217             :     int index;
     218             :     int current_x;
     219       50368 :     int width = s->avctx->width;
     220             :     uint8_t *palette_plane;
     221             : 
     222       50368 :     palette_plane = frame->data[0];
     223       50368 :     stride = frame->linesize[0];
     224       50368 :     line_inc = stride - width;
     225       50368 :     index = y * stride + x;
     226       50368 :     current_x = x;
     227      151305 :     while (pixel_count && index < s->frame_size) {
     228       50569 :         int count = FFMIN(pixel_count, width - current_x);
     229       50569 :         memcpy(palette_plane + index, pixel_buffer, count);
     230       50569 :         pixel_count  -= count;
     231       50569 :         index        += count;
     232       50569 :         pixel_buffer += count;
     233       50569 :         current_x    += count;
     234             : 
     235       50569 :         if (current_x >= width) {
     236        1828 :             index += line_inc;
     237        1828 :             current_x = 0;
     238             :         }
     239             :     }
     240       50368 : }
     241             : 
     242      111283 : static inline void xan_wc3_copy_pixel_run(XanContext *s, AVFrame *frame,
     243             :                                           int x, int y,
     244             :                                           int pixel_count, int motion_x,
     245             :                                           int motion_y)
     246             : {
     247             :     int stride;
     248             :     int line_inc;
     249             :     int curframe_index, prevframe_index;
     250             :     int curframe_x, prevframe_x;
     251      111283 :     int width = s->avctx->width;
     252             :     uint8_t *palette_plane, *prev_palette_plane;
     253             : 
     254      222566 :     if (y + motion_y < 0 || y + motion_y >= s->avctx->height ||
     255      222566 :         x + motion_x < 0 || x + motion_x >= s->avctx->width)
     256           0 :         return;
     257             : 
     258      111283 :     palette_plane = frame->data[0];
     259      111283 :     prev_palette_plane = s->last_frame->data[0];
     260      111283 :     if (!prev_palette_plane)
     261           0 :         prev_palette_plane = palette_plane;
     262      111283 :     stride = frame->linesize[0];
     263      111283 :     line_inc = stride - width;
     264      111283 :     curframe_index = y * stride + x;
     265      111283 :     curframe_x = x;
     266      111283 :     prevframe_index = (y + motion_y) * stride + x + motion_x;
     267      111283 :     prevframe_x = x + motion_x;
     268             : 
     269      111283 :     if (prev_palette_plane == palette_plane && FFABS(motion_x + width*motion_y) < pixel_count) {
     270           0 :          avpriv_request_sample(s->avctx, "Overlapping copy");
     271           0 :          return ;
     272             :     }
     273             : 
     274      451912 :     while (pixel_count &&
     275      229346 :            curframe_index  < s->frame_size &&
     276      114673 :            prevframe_index < s->frame_size) {
     277      114673 :         int count = FFMIN3(pixel_count, width - curframe_x,
     278             :                            width - prevframe_x);
     279             : 
     280      229346 :         memcpy(palette_plane + curframe_index,
     281      114673 :                prev_palette_plane + prevframe_index, count);
     282      114673 :         pixel_count     -= count;
     283      114673 :         curframe_index  += count;
     284      114673 :         prevframe_index += count;
     285      114673 :         curframe_x      += count;
     286      114673 :         prevframe_x     += count;
     287             : 
     288      114673 :         if (curframe_x >= width) {
     289        3947 :             curframe_index += line_inc;
     290        3947 :             curframe_x = 0;
     291             :         }
     292             : 
     293      114673 :         if (prevframe_x >= width) {
     294        3892 :             prevframe_index += line_inc;
     295        3892 :             prevframe_x = 0;
     296             :         }
     297             :     }
     298             : }
     299             : 
     300          35 : static int xan_wc3_decode_frame(XanContext *s, AVFrame *frame)
     301             : {
     302             : 
     303          35 :     int width  = s->avctx->width;
     304          35 :     int height = s->avctx->height;
     305          35 :     int total_pixels = width * height;
     306             :     uint8_t opcode;
     307          35 :     uint8_t flag = 0;
     308          35 :     int size = 0;
     309             :     int motion_x, motion_y;
     310             :     int x, y, ret;
     311             : 
     312          35 :     uint8_t *opcode_buffer = s->buffer1;
     313          35 :     uint8_t *opcode_buffer_end = s->buffer1 + s->buffer1_size;
     314          35 :     int opcode_buffer_size = s->buffer1_size;
     315          35 :     const uint8_t *imagedata_buffer = s->buffer2;
     316             : 
     317             :     /* pointers to segments inside the compressed chunk */
     318             :     const uint8_t *huffman_segment;
     319             :     GetByteContext       size_segment;
     320             :     GetByteContext       vector_segment;
     321             :     const uint8_t *imagedata_segment;
     322             :     int huffman_offset, size_offset, vector_offset, imagedata_offset,
     323             :         imagedata_size;
     324             : 
     325          35 :     if (s->size < 8)
     326           0 :         return AVERROR_INVALIDDATA;
     327             : 
     328          35 :     huffman_offset    = AV_RL16(&s->buf[0]);
     329          35 :     size_offset       = AV_RL16(&s->buf[2]);
     330          35 :     vector_offset     = AV_RL16(&s->buf[4]);
     331          35 :     imagedata_offset  = AV_RL16(&s->buf[6]);
     332             : 
     333          70 :     if (huffman_offset   >= s->size ||
     334          70 :         size_offset      >= s->size ||
     335          70 :         vector_offset    >= s->size ||
     336          35 :         imagedata_offset >= s->size)
     337           0 :         return AVERROR_INVALIDDATA;
     338             : 
     339          35 :     huffman_segment   = s->buf + huffman_offset;
     340          35 :     bytestream2_init(&size_segment,   s->buf + size_offset,   s->size - size_offset);
     341          35 :     bytestream2_init(&vector_segment, s->buf + vector_offset, s->size - vector_offset);
     342          35 :     imagedata_segment = s->buf + imagedata_offset;
     343             : 
     344          35 :     if ((ret = xan_huffman_decode(opcode_buffer, opcode_buffer_size,
     345          35 :                                   huffman_segment, s->size - huffman_offset)) < 0)
     346           0 :         return AVERROR_INVALIDDATA;
     347          35 :     opcode_buffer_end = opcode_buffer + ret;
     348             : 
     349          35 :     if (imagedata_segment[0] == 2) {
     350          21 :         xan_unpack(s->buffer2, s->buffer2_size,
     351          21 :                    &imagedata_segment[1], s->size - imagedata_offset - 1);
     352          21 :         imagedata_size = s->buffer2_size;
     353             :     } else {
     354          14 :         imagedata_size = s->size - imagedata_offset - 1;
     355          14 :         imagedata_buffer = &imagedata_segment[1];
     356             :     }
     357             : 
     358             :     /* use the decoded data segments to build the frame */
     359          35 :     x = y = 0;
     360      170690 :     while (total_pixels && opcode_buffer < opcode_buffer_end) {
     361             : 
     362      170620 :         opcode = *opcode_buffer++;
     363      170620 :         size = 0;
     364             : 
     365      170620 :         switch (opcode) {
     366             : 
     367        8969 :         case 0:
     368        8969 :             flag ^= 1;
     369        8969 :             continue;
     370             : 
     371       91913 :         case 1:
     372             :         case 2:
     373             :         case 3:
     374             :         case 4:
     375             :         case 5:
     376             :         case 6:
     377             :         case 7:
     378             :         case 8:
     379       91913 :             size = opcode;
     380       91913 :             break;
     381             : 
     382       48168 :         case 12:
     383             :         case 13:
     384             :         case 14:
     385             :         case 15:
     386             :         case 16:
     387             :         case 17:
     388             :         case 18:
     389       48168 :             size += (opcode - 10);
     390       48168 :             break;
     391             : 
     392       20805 :         case 9:
     393             :         case 19:
     394       20805 :             if (bytestream2_get_bytes_left(&size_segment) < 1) {
     395           0 :                 av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
     396           0 :                 return AVERROR_INVALIDDATA;
     397             :             }
     398       20805 :             size = bytestream2_get_byte(&size_segment);
     399       20805 :             break;
     400             : 
     401         765 :         case 10:
     402             :         case 20:
     403         765 :             if (bytestream2_get_bytes_left(&size_segment) < 2) {
     404           0 :                 av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
     405           0 :                 return AVERROR_INVALIDDATA;
     406             :             }
     407         765 :             size = bytestream2_get_be16(&size_segment);
     408         765 :             break;
     409             : 
     410           0 :         case 11:
     411             :         case 21:
     412           0 :             if (bytestream2_get_bytes_left(&size_segment) < 3) {
     413           0 :                 av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
     414           0 :                 return AVERROR_INVALIDDATA;
     415             :             }
     416           0 :             size = bytestream2_get_be24(&size_segment);
     417           0 :             break;
     418             :         }
     419             : 
     420      161651 :         if (size > total_pixels)
     421           0 :             break;
     422             : 
     423      161651 :         if (opcode < 12) {
     424      112748 :             flag ^= 1;
     425      112748 :             if (flag) {
     426             :                 /* run of (size) pixels is unchanged from last frame */
     427       62380 :                 xan_wc3_copy_pixel_run(s, frame, x, y, size, 0, 0);
     428             :             } else {
     429             :                 /* output a run of pixels from imagedata_buffer */
     430       50368 :                 if (imagedata_size < size)
     431           0 :                     break;
     432       50368 :                 xan_wc3_output_pixel_run(s, frame, imagedata_buffer, x, y, size);
     433       50368 :                 imagedata_buffer += size;
     434       50368 :                 imagedata_size -= size;
     435             :             }
     436             :         } else {
     437             :             uint8_t vector;
     438       48903 :             if (bytestream2_get_bytes_left(&vector_segment) <= 0) {
     439           0 :                 av_log(s->avctx, AV_LOG_ERROR, "vector_segment overread\n");
     440           0 :                 return AVERROR_INVALIDDATA;
     441             :             }
     442             :             /* run-based motion compensation from last frame */
     443       48903 :             vector = bytestream2_get_byte(&vector_segment);
     444       48903 :             motion_x = sign_extend(vector >> 4,  4);
     445       48903 :             motion_y = sign_extend(vector & 0xF, 4);
     446             : 
     447             :             /* copy a run of pixels from the previous frame */
     448       48903 :             xan_wc3_copy_pixel_run(s, frame, x, y, size, motion_x, motion_y);
     449             : 
     450       48903 :             flag = 0;
     451             :         }
     452             : 
     453             :         /* coordinate accounting */
     454      161651 :         total_pixels -= size;
     455      161651 :         y += (x + size) / width;
     456      161651 :         x  = (x + size) % width;
     457             :     }
     458          35 :     return 0;
     459             : }
     460             : 
     461             : #if RUNTIME_GAMMA
     462             : static inline unsigned mul(unsigned a, unsigned b)
     463             : {
     464             :     return (a * b) >> 16;
     465             : }
     466             : 
     467             : static inline unsigned pow4(unsigned a)
     468             : {
     469             :     unsigned square = mul(a, a);
     470             :     return mul(square, square);
     471             : }
     472             : 
     473             : static inline unsigned pow5(unsigned a)
     474             : {
     475             :     return mul(pow4(a), a);
     476             : }
     477             : 
     478             : static uint8_t gamma_corr(uint8_t in) {
     479             :     unsigned lo, hi = 0xff40, target;
     480             :     int i = 15;
     481             :     in = (in << 2) | (in >> 6);
     482             :     /*  equivalent float code:
     483             :     if (in >= 252)
     484             :         return 253;
     485             :     return round(pow(in / 256.0, 0.8) * 256);
     486             :     */
     487             :     lo = target = in << 8;
     488             :     do {
     489             :         unsigned mid = (lo + hi) >> 1;
     490             :         unsigned pow = pow5(mid);
     491             :         if (pow > target) hi = mid;
     492             :         else lo = mid;
     493             :     } while (--i);
     494             :     return (pow4((lo + hi) >> 1) + 0x80) >> 8;
     495             : }
     496             : #else
     497             : /**
     498             :  * This is a gamma correction that xan3 applies to all palette entries.
     499             :  *
     500             :  * There is a peculiarity, namely that the values are clamped to 253 -
     501             :  * it seems likely that this table was calculated by a buggy fixed-point
     502             :  * implementation, the one above under RUNTIME_GAMMA behaves like this for
     503             :  * example.
     504             :  * The exponent value of 0.8 can be explained by this as well, since 0.8 = 4/5
     505             :  * and thus pow(x, 0.8) is still easy to calculate.
     506             :  * Also, the input values are first rotated to the left by 2.
     507             :  */
     508             : static const uint8_t gamma_lookup[256] = {
     509             :     0x00, 0x09, 0x10, 0x16, 0x1C, 0x21, 0x27, 0x2C,
     510             :     0x31, 0x35, 0x3A, 0x3F, 0x43, 0x48, 0x4C, 0x50,
     511             :     0x54, 0x59, 0x5D, 0x61, 0x65, 0x69, 0x6D, 0x71,
     512             :     0x75, 0x79, 0x7D, 0x80, 0x84, 0x88, 0x8C, 0x8F,
     513             :     0x93, 0x97, 0x9A, 0x9E, 0xA2, 0xA5, 0xA9, 0xAC,
     514             :     0xB0, 0xB3, 0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8,
     515             :     0xCB, 0xCF, 0xD2, 0xD5, 0xD9, 0xDC, 0xDF, 0xE3,
     516             :     0xE6, 0xE9, 0xED, 0xF0, 0xF3, 0xF6, 0xFA, 0xFD,
     517             :     0x03, 0x0B, 0x12, 0x18, 0x1D, 0x23, 0x28, 0x2D,
     518             :     0x32, 0x36, 0x3B, 0x40, 0x44, 0x49, 0x4D, 0x51,
     519             :     0x56, 0x5A, 0x5E, 0x62, 0x66, 0x6A, 0x6E, 0x72,
     520             :     0x76, 0x7A, 0x7D, 0x81, 0x85, 0x89, 0x8D, 0x90,
     521             :     0x94, 0x98, 0x9B, 0x9F, 0xA2, 0xA6, 0xAA, 0xAD,
     522             :     0xB1, 0xB4, 0xB8, 0xBB, 0xBF, 0xC2, 0xC5, 0xC9,
     523             :     0xCC, 0xD0, 0xD3, 0xD6, 0xDA, 0xDD, 0xE0, 0xE4,
     524             :     0xE7, 0xEA, 0xED, 0xF1, 0xF4, 0xF7, 0xFA, 0xFD,
     525             :     0x05, 0x0D, 0x13, 0x19, 0x1F, 0x24, 0x29, 0x2E,
     526             :     0x33, 0x38, 0x3C, 0x41, 0x45, 0x4A, 0x4E, 0x52,
     527             :     0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x6F, 0x73,
     528             :     0x77, 0x7B, 0x7E, 0x82, 0x86, 0x8A, 0x8D, 0x91,
     529             :     0x95, 0x99, 0x9C, 0xA0, 0xA3, 0xA7, 0xAA, 0xAE,
     530             :     0xB2, 0xB5, 0xB9, 0xBC, 0xBF, 0xC3, 0xC6, 0xCA,
     531             :     0xCD, 0xD0, 0xD4, 0xD7, 0xDA, 0xDE, 0xE1, 0xE4,
     532             :     0xE8, 0xEB, 0xEE, 0xF1, 0xF5, 0xF8, 0xFB, 0xFD,
     533             :     0x07, 0x0E, 0x15, 0x1A, 0x20, 0x25, 0x2A, 0x2F,
     534             :     0x34, 0x39, 0x3D, 0x42, 0x46, 0x4B, 0x4F, 0x53,
     535             :     0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, 0x70, 0x74,
     536             :     0x78, 0x7C, 0x7F, 0x83, 0x87, 0x8B, 0x8E, 0x92,
     537             :     0x96, 0x99, 0x9D, 0xA1, 0xA4, 0xA8, 0xAB, 0xAF,
     538             :     0xB2, 0xB6, 0xB9, 0xBD, 0xC0, 0xC4, 0xC7, 0xCB,
     539             :     0xCE, 0xD1, 0xD5, 0xD8, 0xDB, 0xDF, 0xE2, 0xE5,
     540             :     0xE9, 0xEC, 0xEF, 0xF2, 0xF6, 0xF9, 0xFC, 0xFD
     541             : };
     542             : #endif
     543             : 
     544          35 : static int xan_decode_frame(AVCodecContext *avctx,
     545             :                             void *data, int *got_frame,
     546             :                             AVPacket *avpkt)
     547             : {
     548          35 :     AVFrame *frame = data;
     549          35 :     const uint8_t *buf = avpkt->data;
     550          35 :     int ret, buf_size = avpkt->size;
     551          35 :     XanContext *s = avctx->priv_data;
     552             :     GetByteContext ctx;
     553          35 :     int tag = 0;
     554             : 
     555          35 :     bytestream2_init(&ctx, buf, buf_size);
     556         130 :     while (bytestream2_get_bytes_left(&ctx) > 8 && tag != VGA__TAG) {
     557             :         unsigned *tmpptr;
     558             :         uint32_t new_pal;
     559             :         int size;
     560             :         int i;
     561          60 :         tag  = bytestream2_get_le32(&ctx);
     562          60 :         size = bytestream2_get_be32(&ctx);
     563          60 :         if (size < 0) {
     564           0 :             av_log(avctx, AV_LOG_ERROR, "Invalid tag size %d\n", size);
     565           0 :             return AVERROR_INVALIDDATA;
     566             :         }
     567          60 :         size = FFMIN(size, bytestream2_get_bytes_left(&ctx));
     568          60 :         switch (tag) {
     569          24 :         case PALT_TAG:
     570          24 :             if (size < PALETTE_SIZE)
     571           0 :                 return AVERROR_INVALIDDATA;
     572          24 :             if (s->palettes_count >= PALETTES_MAX)
     573           0 :                 return AVERROR_INVALIDDATA;
     574          24 :             tmpptr = av_realloc_array(s->palettes,
     575          24 :                                       s->palettes_count + 1, AVPALETTE_SIZE);
     576          24 :             if (!tmpptr)
     577           0 :                 return AVERROR(ENOMEM);
     578          24 :             s->palettes = tmpptr;
     579          24 :             tmpptr += s->palettes_count * AVPALETTE_COUNT;
     580        6168 :             for (i = 0; i < PALETTE_COUNT; i++) {
     581             : #if RUNTIME_GAMMA
     582             :                 int r = gamma_corr(bytestream2_get_byteu(&ctx));
     583             :                 int g = gamma_corr(bytestream2_get_byteu(&ctx));
     584             :                 int b = gamma_corr(bytestream2_get_byteu(&ctx));
     585             : #else
     586        6144 :                 int r = gamma_lookup[bytestream2_get_byteu(&ctx)];
     587        6144 :                 int g = gamma_lookup[bytestream2_get_byteu(&ctx)];
     588        6144 :                 int b = gamma_lookup[bytestream2_get_byteu(&ctx)];
     589             : #endif
     590        6144 :                 *tmpptr++ = (0xFFU << 24) | (r << 16) | (g << 8) | b;
     591             :             }
     592          24 :             s->palettes_count++;
     593          24 :             break;
     594           1 :         case SHOT_TAG:
     595           1 :             if (size < 4)
     596           0 :                 return AVERROR_INVALIDDATA;
     597           1 :             new_pal = bytestream2_get_le32(&ctx);
     598           1 :             if (new_pal < s->palettes_count) {
     599           1 :                 s->cur_palette = new_pal;
     600             :             } else
     601           0 :                 av_log(avctx, AV_LOG_ERROR, "Invalid palette selected\n");
     602           1 :             break;
     603          35 :         case VGA__TAG:
     604          35 :             break;
     605           0 :         default:
     606           0 :             bytestream2_skip(&ctx, size);
     607           0 :             break;
     608             :         }
     609             :     }
     610          35 :     buf_size = bytestream2_get_bytes_left(&ctx);
     611             : 
     612          35 :     if (s->palettes_count <= 0) {
     613           0 :         av_log(s->avctx, AV_LOG_ERROR, "No palette found\n");
     614           0 :         return AVERROR_INVALIDDATA;
     615             :     }
     616             : 
     617          35 :     if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
     618           0 :         return ret;
     619             : 
     620          35 :     if (!s->frame_size)
     621           1 :         s->frame_size = frame->linesize[0] * s->avctx->height;
     622             : 
     623          70 :     memcpy(frame->data[1],
     624          70 :            s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE);
     625             : 
     626          35 :     s->buf = ctx.buffer;
     627          35 :     s->size = buf_size;
     628             : 
     629          35 :     if (xan_wc3_decode_frame(s, frame) < 0)
     630           0 :         return AVERROR_INVALIDDATA;
     631             : 
     632          35 :     av_frame_unref(s->last_frame);
     633          35 :     if ((ret = av_frame_ref(s->last_frame, frame)) < 0)
     634           0 :         return ret;
     635             : 
     636          35 :     *got_frame = 1;
     637             : 
     638             :     /* always report that the buffer was completely consumed */
     639          35 :     return buf_size;
     640             : }
     641             : 
     642             : AVCodec ff_xan_wc3_decoder = {
     643             :     .name           = "xan_wc3",
     644             :     .long_name      = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
     645             :     .type           = AVMEDIA_TYPE_VIDEO,
     646             :     .id             = AV_CODEC_ID_XAN_WC3,
     647             :     .priv_data_size = sizeof(XanContext),
     648             :     .init           = xan_decode_init,
     649             :     .close          = xan_decode_end,
     650             :     .decode         = xan_decode_frame,
     651             :     .capabilities   = AV_CODEC_CAP_DR1,
     652             : };

Generated by: LCOV version 1.13