LCOV - code coverage report
Current view: top level - libavcodec - dxv.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 228 804 28.4 %
Date: 2018-05-20 11:54:08 Functions: 7 23 30.4 %

          Line data    Source code
       1             : /*
       2             :  * Resolume DXV decoder
       3             :  * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
       4             :  * Copyright (C) 2018 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 <stdint.h>
      24             : 
      25             : #include "libavutil/imgutils.h"
      26             : 
      27             : #include "mathops.h"
      28             : #include "avcodec.h"
      29             : #include "bytestream.h"
      30             : #include "internal.h"
      31             : #include "lzf.h"
      32             : #include "texturedsp.h"
      33             : #include "thread.h"
      34             : 
      35             : typedef struct DXVContext {
      36             :     TextureDSPContext texdsp;
      37             :     GetByteContext gbc;
      38             : 
      39             :     uint8_t *tex_data;   // Compressed texture
      40             :     uint8_t *ctex_data;  // Compressed texture
      41             :     int tex_rat;         // Compression ratio
      42             :     int tex_step;        // Distance between blocks
      43             :     int ctex_step;       // Distance between blocks
      44             :     int64_t tex_size;    // Texture size
      45             :     int64_t ctex_size;   // Texture size
      46             : 
      47             :     /* Optimal number of slices for parallel decoding */
      48             :     int slice_count;
      49             : 
      50             :     uint8_t *op_data[4]; // Opcodes
      51             :     int64_t op_size[4];  // Opcodes size
      52             : 
      53             :     int texture_block_w;
      54             :     int texture_block_h;
      55             : 
      56             :     int ctexture_block_w;
      57             :     int ctexture_block_h;
      58             : 
      59             :     /* Pointer to the selected decompression function */
      60             :     int (*tex_funct)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block);
      61             :     int (*tex_funct_planar[2])(uint8_t *plane0, ptrdiff_t stride0,
      62             :                                uint8_t *plane1, ptrdiff_t stride1,
      63             :                                const uint8_t *block);
      64             : } DXVContext;
      65             : 
      66           0 : static void decompress_indices(uint8_t *dst, const uint8_t *src)
      67             : {
      68             :     int block, i;
      69             : 
      70           0 :     for (block = 0; block < 2; block++) {
      71           0 :         int tmp = AV_RL24(src);
      72             : 
      73             :         /* Unpack 8x3 bit from last 3 byte block */
      74           0 :         for (i = 0; i < 8; i++)
      75           0 :             dst[i] = (tmp >> (i * 3)) & 0x7;
      76             : 
      77           0 :         src += 3;
      78           0 :         dst += 8;
      79             :     }
      80           0 : }
      81             : 
      82           0 : static int extract_component(int yo0, int yo1, int code)
      83             : {
      84             :     int yo;
      85             : 
      86           0 :     if (yo0 == yo1) {
      87           0 :         yo = yo0;
      88           0 :     } else if (code == 0) {
      89           0 :         yo = yo0;
      90           0 :     } else if (code == 1) {
      91           0 :         yo = yo1;
      92             :     } else {
      93           0 :         if (yo0 > yo1) {
      94           0 :             yo = (uint8_t) (((8 - code) * yo0 +
      95           0 :                              (code - 1) * yo1) / 7);
      96             :         } else {
      97           0 :             if (code == 6) {
      98           0 :                 yo = 0;
      99           0 :             } else if (code == 7) {
     100           0 :                 yo = 255;
     101             :             } else {
     102           0 :                 yo = (uint8_t) (((6 - code) * yo0 +
     103           0 :                                  (code - 1) * yo1) / 5);
     104             :             }
     105             :         }
     106             :     }
     107             : 
     108           0 :     return yo;
     109             : }
     110             : 
     111           0 : static int cocg_block(uint8_t *plane0, ptrdiff_t stride0,
     112             :                       uint8_t *plane1, ptrdiff_t stride1,
     113             :                       const uint8_t *block)
     114             : {
     115             :     uint8_t co_indices[16];
     116             :     uint8_t cg_indices[16];
     117           0 :     uint8_t co0 = *(block);
     118           0 :     uint8_t co1 = *(block + 1);
     119           0 :     uint8_t cg0 = *(block + 8);
     120           0 :     uint8_t cg1 = *(block + 9);
     121             :     int x, y;
     122             : 
     123           0 :     decompress_indices(co_indices, block + 2);
     124           0 :     decompress_indices(cg_indices, block + 10);
     125             : 
     126           0 :     for (y = 0; y < 4; y++) {
     127           0 :         for (x = 0; x < 4; x++) {
     128           0 :             int co_code = co_indices[x + y * 4];
     129           0 :             int cg_code = cg_indices[x + y * 4];
     130             : 
     131           0 :             plane0[x] = extract_component(cg0, cg1, cg_code);
     132           0 :             plane1[x] = extract_component(co0, co1, co_code);
     133             :         }
     134           0 :         plane0 += stride0;
     135           0 :         plane1 += stride1;
     136             :     }
     137             : 
     138           0 :     return 16;
     139             : }
     140             : 
     141           0 : static void yao_subblock(uint8_t *dst, uint8_t *yo_indices,
     142             :                         ptrdiff_t stride, const uint8_t *block)
     143             : {
     144           0 :     uint8_t yo0 = *(block);
     145           0 :     uint8_t yo1 = *(block + 1);
     146             :     int x, y;
     147             : 
     148           0 :     decompress_indices(yo_indices, block + 2);
     149             : 
     150           0 :     for (y = 0; y < 4; y++) {
     151           0 :         for (x = 0; x < 4; x++) {
     152           0 :             int yo_code = yo_indices[x + y * 4];
     153             : 
     154           0 :             dst[x] = extract_component(yo0, yo1, yo_code);
     155             :         }
     156           0 :         dst += stride;
     157             :     }
     158           0 : }
     159             : 
     160           0 : static int yo_block(uint8_t *dst, ptrdiff_t stride,
     161             :                     uint8_t *unused0, ptrdiff_t unused1,
     162             :                     const uint8_t *block)
     163             : {
     164             :     uint8_t yo_indices[16];
     165             : 
     166           0 :     yao_subblock(dst,      yo_indices, stride, block);
     167           0 :     yao_subblock(dst + 4,  yo_indices, stride, block + 8);
     168           0 :     yao_subblock(dst + 8,  yo_indices, stride, block + 16);
     169           0 :     yao_subblock(dst + 12, yo_indices, stride, block + 24);
     170             : 
     171           0 :     return 32;
     172             : }
     173             : 
     174           0 : static int yao_block(uint8_t *plane0, ptrdiff_t stride0,
     175             :                      uint8_t *plane3, ptrdiff_t stride1,
     176             :                      const uint8_t *block)
     177             : {
     178             :     uint8_t yo_indices[16];
     179             :     uint8_t a_indices[16];
     180             : 
     181           0 :     yao_subblock(plane0,      yo_indices, stride0, block);
     182           0 :     yao_subblock(plane3,      a_indices,  stride1, block + 8);
     183           0 :     yao_subblock(plane0 + 4,  yo_indices, stride0, block + 16);
     184           0 :     yao_subblock(plane3 + 4,  a_indices,  stride1, block + 24);
     185           0 :     yao_subblock(plane0 + 8,  yo_indices, stride0, block + 32);
     186           0 :     yao_subblock(plane3 + 8,  a_indices,  stride1, block + 40);
     187           0 :     yao_subblock(plane0 + 12, yo_indices, stride0, block + 48);
     188           0 :     yao_subblock(plane3 + 12, a_indices,  stride1, block + 56);
     189             : 
     190           0 :     return 64;
     191             : }
     192             : 
     193           8 : static int decompress_texture_thread(AVCodecContext *avctx, void *arg,
     194             :                                      int slice, int thread_nb)
     195             : {
     196           8 :     DXVContext *ctx = avctx->priv_data;
     197           8 :     AVFrame *frame = arg;
     198           8 :     const uint8_t *d = ctx->tex_data;
     199           8 :     int w_block = avctx->coded_width / ctx->texture_block_w;
     200           8 :     int h_block = avctx->coded_height / ctx->texture_block_h;
     201             :     int x, y;
     202             :     int start_slice, end_slice;
     203             : 
     204           8 :     start_slice = h_block * slice / ctx->slice_count;
     205           8 :     end_slice = h_block * (slice + 1) / ctx->slice_count;
     206             : 
     207           8 :     if (ctx->tex_funct) {
     208        2184 :         for (y = start_slice; y < end_slice; y++) {
     209        2176 :             uint8_t *p = frame->data[0] + y * frame->linesize[0] * ctx->texture_block_h;
     210        2176 :             int off = y * w_block;
     211     1046656 :             for (x = 0; x < w_block; x++) {
     212     2088960 :                 ctx->tex_funct(p + x * 4 * ctx->texture_block_w, frame->linesize[0],
     213     1044480 :                                d + (off + x) * ctx->tex_step);
     214             :             }
     215             :         }
     216             :     } else {
     217           0 :         const uint8_t *c = ctx->ctex_data;
     218             : 
     219           0 :         for (y = start_slice; y < end_slice; y++) {
     220           0 :             uint8_t *p0 = frame->data[0] + y * frame->linesize[0] * ctx->texture_block_h;
     221           0 :             uint8_t *p3 = ctx->tex_step != 64 ? NULL : frame->data[3] + y * frame->linesize[3] * ctx->texture_block_h;
     222           0 :             int off = y * w_block;
     223           0 :             for (x = 0; x < w_block; x++) {
     224           0 :                 ctx->tex_funct_planar[0](p0 + x * ctx->texture_block_w, frame->linesize[0],
     225           0 :                                          p3 != NULL ? p3 + x * ctx->texture_block_w : NULL, frame->linesize[3],
     226           0 :                                          d + (off + x) * ctx->tex_step);
     227             :             }
     228             :         }
     229             : 
     230           0 :         w_block = (avctx->coded_width / 2) / ctx->ctexture_block_w;
     231           0 :         h_block = (avctx->coded_height / 2) / ctx->ctexture_block_h;
     232           0 :         start_slice = h_block * slice / ctx->slice_count;
     233           0 :         end_slice = h_block * (slice + 1) / ctx->slice_count;
     234             : 
     235           0 :         for (y = start_slice; y < end_slice; y++) {
     236           0 :             uint8_t *p0 = frame->data[1] + y * frame->linesize[1] * ctx->ctexture_block_h;
     237           0 :             uint8_t *p1 = frame->data[2] + y * frame->linesize[2] * ctx->ctexture_block_h;
     238           0 :             int off = y * w_block;
     239           0 :             for (x = 0; x < w_block; x++) {
     240           0 :                 ctx->tex_funct_planar[1](p0 + x * ctx->ctexture_block_w, frame->linesize[1],
     241           0 :                                          p1 + x * ctx->ctexture_block_w, frame->linesize[2],
     242           0 :                                          c + (off + x) * ctx->ctex_step);
     243             :             }
     244             :         }
     245             :     }
     246             : 
     247           8 :     return 0;
     248             : }
     249             : 
     250             : /* This scheme addresses already decoded elements depending on 2-bit status:
     251             :  *   0 -> copy new element
     252             :  *   1 -> copy one element from position -x
     253             :  *   2 -> copy one element from position -(get_byte() + 2) * x
     254             :  *   3 -> copy one element from position -(get_16le() + 0x102) * x
     255             :  * x is always 2 for dxt1 and 4 for dxt5. */
     256             : #define CHECKPOINT(x)                                                         \
     257             :     do {                                                                      \
     258             :         if (state == 0) {                                                     \
     259             :             value = bytestream2_get_le32(gbc);                                \
     260             :             state = 16;                                                       \
     261             :         }                                                                     \
     262             :         op = value & 0x3;                                                     \
     263             :         value >>= 2;                                                          \
     264             :         state--;                                                              \
     265             :         switch (op) {                                                         \
     266             :         case 1:                                                               \
     267             :             idx = x;                                                          \
     268             :             break;                                                            \
     269             :         case 2:                                                               \
     270             :             idx = (bytestream2_get_byte(gbc) + 2) * x;                        \
     271             :             if (idx > pos) {                                                  \
     272             :                 av_log(avctx, AV_LOG_ERROR, "idx %d > %d\n", idx, pos);       \
     273             :                 return AVERROR_INVALIDDATA;                                   \
     274             :             }                                                                 \
     275             :             break;                                                            \
     276             :         case 3:                                                               \
     277             :             idx = (bytestream2_get_le16(gbc) + 0x102) * x;                    \
     278             :             if (idx > pos) {                                                  \
     279             :                 av_log(avctx, AV_LOG_ERROR, "idx %d > %d\n", idx, pos);       \
     280             :                 return AVERROR_INVALIDDATA;                                   \
     281             :             }                                                                 \
     282             :             break;                                                            \
     283             :         }                                                                     \
     284             :     } while(0)
     285             : 
     286           2 : static int dxv_decompress_dxt1(AVCodecContext *avctx)
     287             : {
     288           2 :     DXVContext *ctx = avctx->priv_data;
     289           2 :     GetByteContext *gbc = &ctx->gbc;
     290             :     uint32_t value, prev, op;
     291           2 :     int idx = 0, state = 0;
     292           2 :     int pos = 2;
     293             : 
     294             :     /* Copy the first two elements */
     295           2 :     AV_WL32(ctx->tex_data, bytestream2_get_le32(gbc));
     296           2 :     AV_WL32(ctx->tex_data + 4, bytestream2_get_le32(gbc));
     297             : 
     298             :     /* Process input until the whole texture has been filled */
     299      261122 :     while (pos + 2 <= ctx->tex_size / 4) {
     300      261118 :         CHECKPOINT(2);
     301             : 
     302             :         /* Copy two elements from a previous offset or from the input buffer */
     303      261118 :         if (op) {
     304      254910 :             prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
     305      254910 :             AV_WL32(ctx->tex_data + 4 * pos, prev);
     306      254910 :             pos++;
     307             : 
     308      254910 :             prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
     309      254910 :             AV_WL32(ctx->tex_data + 4 * pos, prev);
     310      254910 :             pos++;
     311             :         } else {
     312        6208 :             CHECKPOINT(2);
     313             : 
     314        6208 :             if (op)
     315        1602 :                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
     316             :             else
     317        4606 :                 prev = bytestream2_get_le32(gbc);
     318        6208 :             AV_WL32(ctx->tex_data + 4 * pos, prev);
     319        6208 :             pos++;
     320             : 
     321        6208 :             CHECKPOINT(2);
     322             : 
     323        6208 :             if (op)
     324        3196 :                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
     325             :             else
     326        3012 :                 prev = bytestream2_get_le32(gbc);
     327        6208 :             AV_WL32(ctx->tex_data + 4 * pos, prev);
     328        6208 :             pos++;
     329             :         }
     330             :     }
     331             : 
     332           2 :     return 0;
     333             : }
     334             : 
     335             : typedef struct OpcodeTable {
     336             :     int16_t next;
     337             :     uint8_t val1;
     338             :     uint8_t val2;
     339             : } OpcodeTable;
     340             : 
     341           0 : static int fill_ltable(GetByteContext *gb, uint32_t *table, int *nb_elements)
     342             : {
     343           0 :     unsigned half = 512, bits = 1023, left = 1024, input, mask;
     344           0 :     int value, counter = 0, rshift = 10, lshift = 30;
     345             : 
     346           0 :     mask = bytestream2_get_le32(gb) >> 2;
     347           0 :     while (left) {
     348           0 :         if (counter >= 256)
     349           0 :             return AVERROR_INVALIDDATA;
     350           0 :         value = bits & mask;
     351           0 :         left -= bits & mask;
     352           0 :         mask >>= rshift;
     353           0 :         lshift -= rshift;
     354           0 :         table[counter++] = value;
     355           0 :         if (lshift < 16) {
     356           0 :             if (bytestream2_get_bytes_left(gb) <= 0)
     357           0 :                 return AVERROR_INVALIDDATA;
     358             : 
     359           0 :             input = bytestream2_get_le16(gb);
     360           0 :             mask += input << lshift;
     361           0 :             lshift += 16;
     362             :         }
     363           0 :         if (left < half) {
     364           0 :             half >>= 1;
     365           0 :             bits >>= 1;
     366           0 :             rshift--;
     367             :         }
     368             :     }
     369             : 
     370           0 :     for (; !table[counter - 1]; counter--)
     371           0 :         if (counter <= 0)
     372           0 :             return AVERROR_INVALIDDATA;
     373             : 
     374           0 :     *nb_elements = counter;
     375             : 
     376           0 :     if (counter < 256)
     377           0 :         memset(&table[counter], 0, 4 * (256 - counter));
     378             : 
     379           0 :     if (lshift >= 16)
     380           0 :         bytestream2_seek(gb, -2, SEEK_CUR);
     381             : 
     382           0 :     return 0;
     383             : }
     384             : 
     385           0 : static int fill_optable(unsigned *table0, OpcodeTable *table1, int nb_elements)
     386             : {
     387           0 :     unsigned table2[256] = { 0 };
     388           0 :     unsigned x = 0;
     389           0 :     int val0, val1, i, j = 2, k = 0;
     390             : 
     391           0 :     table2[0] = table0[0];
     392           0 :     for (i = 0; i < nb_elements - 1; i++, table2[i] = val0) {
     393           0 :         val0 = table0[i + 1] + table2[i];
     394             :     }
     395             : 
     396           0 :     if (!table2[0]) {
     397             :         do {
     398           0 :             k++;
     399           0 :         } while (!table2[k]);
     400             :     }
     401             : 
     402           0 :     j = 2;
     403           0 :     for (i = 1024; i > 0; i--) {
     404           0 :         for (table1[x].val1 = k; k < 256 && j > table2[k]; k++);
     405           0 :         x = (x - 383) & 0x3FF;
     406           0 :         j++;
     407             :     }
     408             : 
     409           0 :     if (nb_elements > 0)
     410           0 :         memcpy(&table2[0], table0, 4 * nb_elements);
     411             : 
     412           0 :     for (i = 0; i < 1024; i++) {
     413           0 :         val0 = table1[i].val1;
     414           0 :         val1 = table2[val0];
     415           0 :         table2[val0]++;
     416           0 :         x = 31 - ff_clz(val1);
     417           0 :         if (x > 10)
     418           0 :             return AVERROR_INVALIDDATA;
     419           0 :         table1[i].val2 = 10 - x;
     420           0 :         table1[i].next = (val1 << table1[i].val2) - 1024;
     421             :     }
     422             : 
     423           0 :     return 0;
     424             : }
     425             : 
     426           0 : static int get_opcodes(GetByteContext *gb, uint32_t *table, uint8_t *dst, int op_size, int nb_elements)
     427             : {
     428             :     OpcodeTable optable[1024];
     429             :     int sum, x, val, lshift, rshift, ret, size_in_bits, i, idx;
     430             :     unsigned endoffset, newoffset, offset;
     431             :     unsigned next;
     432           0 :     uint8_t *src = (uint8_t *)gb->buffer;
     433             : 
     434           0 :     ret = fill_optable(table, optable, nb_elements);
     435           0 :     if (ret < 0)
     436           0 :         return ret;
     437             : 
     438           0 :     size_in_bits = bytestream2_get_le32(gb);
     439           0 :     endoffset = ((size_in_bits + 7) >> 3) - 4;
     440           0 :     if (endoffset <= 0 || bytestream2_get_bytes_left(gb) < endoffset)
     441           0 :         return AVERROR_INVALIDDATA;
     442             : 
     443           0 :     offset = endoffset;
     444           0 :     next = AV_RL32(src + endoffset);
     445           0 :     rshift = (((size_in_bits & 0xFF) - 1) & 7) + 15;
     446           0 :     lshift = 32 - rshift;
     447           0 :     idx = (next >> rshift) & 0x3FF;
     448           0 :     for (i = 0; i < op_size; i++) {
     449           0 :         dst[i] = optable[idx].val1;
     450           0 :         val = optable[idx].val2;
     451           0 :         sum = val + lshift;
     452           0 :         x = (next << lshift) >> 1 >> (31 - val);
     453           0 :         newoffset = offset - (sum >> 3);
     454           0 :         lshift = sum & 7;
     455           0 :         idx = x + optable[idx].next;
     456           0 :         offset = newoffset;
     457           0 :         if (offset > endoffset)
     458           0 :             return AVERROR_INVALIDDATA;
     459           0 :         next = AV_RL32(src + offset);
     460             :     }
     461             : 
     462           0 :     bytestream2_skip(gb, (size_in_bits + 7 >> 3) - 4);
     463             : 
     464           0 :     return 0;
     465             : }
     466             : 
     467           0 : static int dxv_decompress_opcodes(GetByteContext *gb, void *dstp, size_t op_size)
     468             : {
     469           0 :     int pos = bytestream2_tell(gb);
     470           0 :     int flag = bytestream2_peek_byte(gb);
     471             : 
     472           0 :     if ((flag & 3) == 0) {
     473           0 :         bytestream2_skip(gb, 1);
     474           0 :         bytestream2_get_buffer(gb, dstp, op_size);
     475           0 :     } else if ((flag & 3) == 1) {
     476           0 :         bytestream2_skip(gb, 1);
     477           0 :         memset(dstp, bytestream2_get_byte(gb), op_size);
     478             :     } else {
     479             :         uint32_t table[256];
     480           0 :         int ret, elements = 0;
     481             : 
     482           0 :         ret = fill_ltable(gb, table, &elements);
     483           0 :         if (ret < 0)
     484           0 :             return ret;
     485           0 :         ret = get_opcodes(gb, table, dstp, op_size, elements);
     486           0 :         if (ret < 0)
     487           0 :             return ret;
     488             :     }
     489           0 :     return bytestream2_tell(gb) - pos;
     490             : }
     491             : 
     492           0 : static int dxv_decompress_cgo(DXVContext *ctx, GetByteContext *gb,
     493             :                               uint8_t *tex_data, int tex_size,
     494             :                               uint8_t *op_data, int *oindex,
     495             :                               int op_size,
     496             :                               uint8_t **dstp, int *statep,
     497             :                               uint8_t **tab0, uint8_t **tab1,
     498             :                               int offset)
     499             : {
     500           0 :     uint8_t *dst = *dstp;
     501             :     uint8_t *tptr0, *tptr1, *tptr3;
     502           0 :     int oi = *oindex;
     503           0 :     int state = *statep;
     504             :     int opcode, v, vv;
     505             : 
     506           0 :     if (state <= 0) {
     507           0 :         if (oi >= op_size)
     508           0 :             return AVERROR_INVALIDDATA;
     509           0 :         opcode = op_data[oi++];
     510           0 :         if (!opcode) {
     511           0 :             v = bytestream2_get_byte(gb);
     512           0 :             if (v == 255) {
     513             :                 do {
     514           0 :                     if (bytestream2_get_bytes_left(gb) <= 0)
     515           0 :                         return AVERROR_INVALIDDATA;
     516           0 :                     opcode = bytestream2_get_le16(gb);
     517           0 :                     v += opcode;
     518           0 :                 } while (opcode == 0xFFFF);
     519             :             }
     520           0 :             AV_WL32(dst, AV_RL32(dst - (8 + offset)));
     521           0 :             AV_WL32(dst + 4, AV_RL32(dst - (4 + offset)));
     522           0 :             state = v + 4;
     523           0 :             goto done;
     524             :         }
     525             : 
     526           0 :         switch (opcode) {
     527           0 :         case 1:
     528           0 :             AV_WL32(dst, AV_RL32(dst - (8 + offset)));
     529           0 :             AV_WL32(dst + 4, AV_RL32(dst - (4 + offset)));
     530           0 :             break;
     531           0 :         case 2:
     532           0 :             vv = (8 + offset) * (bytestream2_get_le16(gb) + 1);
     533           0 :             if (vv < 0 || vv > dst - tex_data)
     534           0 :                 return AVERROR_INVALIDDATA;
     535           0 :             tptr0 = dst - vv;
     536           0 :             v = AV_RL32(tptr0);
     537           0 :             AV_WL32(dst, AV_RL32(tptr0));
     538           0 :             AV_WL32(dst + 4, AV_RL32(tptr0 + 4));
     539           0 :             tab0[0x9E3779B1 * (uint16_t)v >> 24] = dst;
     540           0 :             tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
     541           0 :             break;
     542           0 :         case 3:
     543           0 :             AV_WL32(dst, bytestream2_get_le32(gb));
     544           0 :             AV_WL32(dst + 4, bytestream2_get_le32(gb));
     545           0 :             tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
     546           0 :             tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
     547           0 :             break;
     548           0 :         case 4:
     549           0 :             tptr3 = tab1[bytestream2_get_byte(gb)];
     550           0 :             if (!tptr3)
     551           0 :                 return AVERROR_INVALIDDATA;
     552           0 :             AV_WL16(dst, bytestream2_get_le16(gb));
     553           0 :             AV_WL16(dst + 2, AV_RL16(tptr3));
     554           0 :             dst[4] = tptr3[2];
     555           0 :             AV_WL16(dst + 5, bytestream2_get_le16(gb));
     556           0 :             dst[7] = bytestream2_get_byte(gb);
     557           0 :             tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
     558           0 :             break;
     559           0 :         case 5:
     560           0 :             tptr3 = tab1[bytestream2_get_byte(gb)];
     561           0 :             if (!tptr3)
     562           0 :                 return AVERROR_INVALIDDATA;
     563           0 :             AV_WL16(dst, bytestream2_get_le16(gb));
     564           0 :             AV_WL16(dst + 2, bytestream2_get_le16(gb));
     565           0 :             dst[4] = bytestream2_get_byte(gb);
     566           0 :             AV_WL16(dst + 5, AV_RL16(tptr3));
     567           0 :             dst[7] = tptr3[2];
     568           0 :             tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
     569           0 :             tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
     570           0 :             break;
     571           0 :         case 6:
     572           0 :             tptr0 = tab1[bytestream2_get_byte(gb)];
     573           0 :             if (!tptr0)
     574           0 :                 return AVERROR_INVALIDDATA;
     575           0 :             tptr1 = tab1[bytestream2_get_byte(gb)];
     576           0 :             if (!tptr1)
     577           0 :                 return AVERROR_INVALIDDATA;
     578           0 :             AV_WL16(dst, bytestream2_get_le16(gb));
     579           0 :             AV_WL16(dst + 2, AV_RL16(tptr0));
     580           0 :             dst[4] = tptr0[2];
     581           0 :             AV_WL16(dst + 5, AV_RL16(tptr1));
     582           0 :             dst[7] = tptr1[2];
     583           0 :             tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
     584           0 :             break;
     585           0 :         case 7:
     586           0 :             v = (8 + offset) * (bytestream2_get_le16(gb) + 1);
     587           0 :             if (v < 0 || v > dst - tex_data)
     588           0 :                 return AVERROR_INVALIDDATA;
     589           0 :             tptr0 = dst - v;
     590           0 :             AV_WL16(dst, bytestream2_get_le16(gb));
     591           0 :             AV_WL16(dst + 2, AV_RL16(tptr0 + 2));
     592           0 :             AV_WL32(dst + 4, AV_RL32(tptr0 + 4));
     593           0 :             tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
     594           0 :             tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
     595           0 :             break;
     596           0 :         case 8:
     597           0 :             tptr1 = tab0[bytestream2_get_byte(gb)];
     598           0 :             if (!tptr1)
     599           0 :                 return AVERROR_INVALIDDATA;
     600           0 :             AV_WL16(dst, AV_RL16(tptr1));
     601           0 :             AV_WL16(dst + 2, bytestream2_get_le16(gb));
     602           0 :             AV_WL32(dst + 4, bytestream2_get_le32(gb));
     603           0 :             tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
     604           0 :             break;
     605           0 :         case 9:
     606           0 :             tptr1 = tab0[bytestream2_get_byte(gb)];
     607           0 :             if (!tptr1)
     608           0 :                 return AVERROR_INVALIDDATA;
     609           0 :             tptr3 = tab1[bytestream2_get_byte(gb)];
     610           0 :             if (!tptr3)
     611           0 :                 return AVERROR_INVALIDDATA;
     612           0 :             AV_WL16(dst, AV_RL16(tptr1));
     613           0 :             AV_WL16(dst + 2, AV_RL16(tptr3));
     614           0 :             dst[4] = tptr3[2];
     615           0 :             AV_WL16(dst + 5, bytestream2_get_le16(gb));
     616           0 :             dst[7] = bytestream2_get_byte(gb);
     617           0 :             tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
     618           0 :             break;
     619           0 :         case 10:
     620           0 :             tptr1 = tab0[bytestream2_get_byte(gb)];
     621           0 :             if (!tptr1)
     622           0 :                 return AVERROR_INVALIDDATA;
     623           0 :             tptr3 = tab1[bytestream2_get_byte(gb)];
     624           0 :             if (!tptr3)
     625           0 :                 return AVERROR_INVALIDDATA;
     626           0 :             AV_WL16(dst, AV_RL16(tptr1));
     627           0 :             AV_WL16(dst + 2, bytestream2_get_le16(gb));
     628           0 :             dst[4] = bytestream2_get_byte(gb);
     629           0 :             AV_WL16(dst + 5, AV_RL16(tptr3));
     630           0 :             dst[7] = tptr3[2];
     631           0 :             tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
     632           0 :             break;
     633           0 :         case 11:
     634           0 :             tptr0 = tab0[bytestream2_get_byte(gb)];
     635           0 :             if (!tptr0)
     636           0 :                 return AVERROR_INVALIDDATA;
     637           0 :             tptr3 = tab1[bytestream2_get_byte(gb)];
     638           0 :             if (!tptr3)
     639           0 :                 return AVERROR_INVALIDDATA;
     640           0 :             tptr1 = tab1[bytestream2_get_byte(gb)];
     641           0 :             if (!tptr1)
     642           0 :                 return AVERROR_INVALIDDATA;
     643           0 :             AV_WL16(dst, AV_RL16(tptr0));
     644           0 :             AV_WL16(dst + 2, AV_RL16(tptr3));
     645           0 :             dst[4] = tptr3[2];
     646           0 :             AV_WL16(dst + 5, AV_RL16(tptr1));
     647           0 :             dst[7] = tptr1[2];
     648           0 :             break;
     649           0 :         case 12:
     650           0 :             tptr1 = tab0[bytestream2_get_byte(gb)];
     651           0 :             if (!tptr1)
     652           0 :                 return AVERROR_INVALIDDATA;
     653           0 :             v = (8 + offset) * (bytestream2_get_le16(gb) + 1);
     654           0 :             if (v < 0 || v > dst - tex_data)
     655           0 :                 return AVERROR_INVALIDDATA;
     656           0 :             tptr0 = dst - v;
     657           0 :             AV_WL16(dst, AV_RL16(tptr1));
     658           0 :             AV_WL16(dst + 2, AV_RL16(tptr0 + 2));
     659           0 :             AV_WL32(dst + 4, AV_RL32(tptr0 + 4));
     660           0 :             tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
     661           0 :             break;
     662           0 :         case 13:
     663           0 :             AV_WL16(dst, AV_RL16(dst - (8 + offset)));
     664           0 :             AV_WL16(dst + 2, bytestream2_get_le16(gb));
     665           0 :             AV_WL32(dst + 4, bytestream2_get_le32(gb));
     666           0 :             tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
     667           0 :             break;
     668           0 :         case 14:
     669           0 :             tptr3 = tab1[bytestream2_get_byte(gb)];
     670           0 :             if (!tptr3)
     671           0 :                 return AVERROR_INVALIDDATA;
     672           0 :             AV_WL16(dst, AV_RL16(dst - (8 + offset)));
     673           0 :             AV_WL16(dst + 2, AV_RL16(tptr3));
     674           0 :             dst[4] = tptr3[2];
     675           0 :             AV_WL16(dst + 5, bytestream2_get_le16(gb));
     676           0 :             dst[7] = bytestream2_get_byte(gb);
     677           0 :             tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
     678           0 :             break;
     679           0 :         case 15:
     680           0 :             tptr3 = tab1[bytestream2_get_byte(gb)];
     681           0 :             if (!tptr3)
     682           0 :                 return AVERROR_INVALIDDATA;
     683           0 :             AV_WL16(dst, AV_RL16(dst - (8 + offset)));
     684           0 :             AV_WL16(dst + 2, bytestream2_get_le16(gb));
     685           0 :             dst[4] = bytestream2_get_byte(gb);
     686           0 :             AV_WL16(dst + 5, AV_RL16(tptr3));
     687           0 :             dst[7] = tptr3[2];
     688           0 :             tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
     689           0 :             break;
     690           0 :         case 16:
     691           0 :             tptr3 = tab1[bytestream2_get_byte(gb)];
     692           0 :             if (!tptr3)
     693           0 :                 return AVERROR_INVALIDDATA;
     694           0 :             tptr1 = tab1[bytestream2_get_byte(gb)];
     695           0 :             if (!tptr1)
     696           0 :                 return AVERROR_INVALIDDATA;
     697           0 :             AV_WL16(dst, AV_RL16(dst - (8 + offset)));
     698           0 :             AV_WL16(dst + 2, AV_RL16(tptr3));
     699           0 :             dst[4] = tptr3[2];
     700           0 :             AV_WL16(dst + 5, AV_RL16(tptr1));
     701           0 :             dst[7] = tptr1[2];
     702           0 :             break;
     703           0 :         case 17:
     704           0 :             v = (8 + offset) * (bytestream2_get_le16(gb) + 1);
     705           0 :             if (v < 0 || v > dst - tex_data)
     706           0 :                 return AVERROR_INVALIDDATA;
     707           0 :             AV_WL16(dst, AV_RL16(dst - (8 + offset)));
     708           0 :             AV_WL16(dst + 2, AV_RL16(&dst[-v + 2]));
     709           0 :             AV_WL32(dst + 4, AV_RL32(&dst[-v + 4]));
     710           0 :             tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
     711           0 :             break;
     712           0 :         default:
     713           0 :             break;
     714             :         }
     715             :     } else {
     716           0 : done:
     717           0 :         AV_WL32(dst, AV_RL32(dst - (8 + offset)));
     718           0 :         AV_WL32(dst + 4, AV_RL32(dst - (4 + offset)));
     719           0 :         state--;
     720             :     }
     721           0 :     if (dst - tex_data + 8 > tex_size)
     722           0 :         return AVERROR_INVALIDDATA;
     723           0 :     dst += 8;
     724             : 
     725           0 :     *oindex = oi;
     726           0 :     *dstp = dst;
     727           0 :     *statep = state;
     728             : 
     729           0 :     return 0;
     730             : }
     731             : 
     732           0 : static int dxv_decompress_cocg(DXVContext *ctx, GetByteContext *gb,
     733             :                                uint8_t *tex_data, int tex_size,
     734             :                                uint8_t *op_data0, uint8_t *op_data1,
     735             :                                int max_op_size0, int max_op_size1)
     736             : {
     737           0 :     uint8_t *dst, *tab2[256] = { 0 }, *tab0[256] = { 0 }, *tab3[256] = { 0 }, *tab1[256] = { 0 };
     738           0 :     int op_offset = bytestream2_get_le32(gb);
     739           0 :     unsigned op_size0 = bytestream2_get_le32(gb);
     740           0 :     unsigned op_size1 = bytestream2_get_le32(gb);
     741           0 :     int data_start = bytestream2_tell(gb);
     742           0 :     int skip0, skip1, oi0 = 0, oi1 = 0;
     743           0 :     int ret, state0 = 0, state1 = 0;
     744             : 
     745           0 :     dst = tex_data;
     746           0 :     bytestream2_skip(gb, op_offset - 12);
     747           0 :     if (op_size0 > max_op_size0)
     748           0 :         return AVERROR_INVALIDDATA;
     749           0 :     skip0 = dxv_decompress_opcodes(gb, op_data0, op_size0);
     750           0 :     if (skip0 < 0)
     751           0 :         return skip0;
     752           0 :     bytestream2_seek(gb, data_start + op_offset + skip0 - 12, SEEK_SET);
     753           0 :     if (op_size1 > max_op_size1)
     754           0 :         return AVERROR_INVALIDDATA;
     755           0 :     skip1 = dxv_decompress_opcodes(gb, op_data1, op_size1);
     756           0 :     if (skip1 < 0)
     757           0 :         return skip1;
     758           0 :     bytestream2_seek(gb, data_start, SEEK_SET);
     759             : 
     760           0 :     AV_WL32(dst, bytestream2_get_le32(gb));
     761           0 :     AV_WL32(dst + 4, bytestream2_get_le32(gb));
     762           0 :     AV_WL32(dst + 8, bytestream2_get_le32(gb));
     763           0 :     AV_WL32(dst + 12, bytestream2_get_le32(gb));
     764             : 
     765           0 :     tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
     766           0 :     tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFF) >> 24] = dst + 2;
     767           0 :     tab2[0x9E3779B1 * AV_RL16(dst + 8) >> 24] = dst + 8;
     768           0 :     tab3[0x9E3779B1 * (AV_RL32(dst + 10) & 0xFFFFFF) >> 24] = dst + 10;
     769           0 :     dst += 16;
     770           0 :     while (dst + 10 < tex_data + tex_size) {
     771           0 :         ret = dxv_decompress_cgo(ctx, gb, tex_data, tex_size, op_data0, &oi0, op_size0,
     772             :                                  &dst, &state0, tab0, tab1, 8);
     773           0 :         if (ret < 0)
     774           0 :             return ret;
     775           0 :         ret = dxv_decompress_cgo(ctx, gb, tex_data, tex_size, op_data1, &oi1, op_size1,
     776             :                                  &dst, &state1, tab2, tab3, 8);
     777           0 :         if (ret < 0)
     778           0 :             return ret;
     779             :     }
     780             : 
     781           0 :     bytestream2_seek(gb, data_start + op_offset + skip0 + skip1 - 12, SEEK_SET);
     782             : 
     783           0 :     return 0;
     784             : }
     785             : 
     786           0 : static int dxv_decompress_yo(DXVContext *ctx, GetByteContext *gb,
     787             :                              uint8_t *tex_data, int tex_size,
     788             :                              uint8_t *op_data, int max_op_size)
     789             : {
     790           0 :     int op_offset = bytestream2_get_le32(gb);
     791           0 :     unsigned op_size = bytestream2_get_le32(gb);
     792           0 :     int data_start = bytestream2_tell(gb);
     793           0 :     uint8_t *dst, *table0[256] = { 0 }, *table1[256] = { 0 };
     794           0 :     int ret, state = 0, skip, oi = 0, v, vv;
     795             : 
     796           0 :     dst = tex_data;
     797           0 :     bytestream2_skip(gb, op_offset - 8);
     798           0 :     if (op_size > max_op_size)
     799           0 :         return AVERROR_INVALIDDATA;
     800           0 :     skip = dxv_decompress_opcodes(gb, op_data, op_size);
     801           0 :     if (skip < 0)
     802           0 :         return skip;
     803           0 :     bytestream2_seek(gb, data_start, SEEK_SET);
     804             : 
     805           0 :     v = bytestream2_get_le32(gb);
     806           0 :     AV_WL32(dst, v);
     807           0 :     vv = bytestream2_get_le32(gb);
     808           0 :     table0[0x9E3779B1 * (uint16_t)v >> 24] = dst;
     809           0 :     AV_WL32(dst + 4, vv);
     810           0 :     table1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFF) >> 24] = dst + 2;
     811           0 :     dst += 8;
     812             : 
     813           0 :     while (dst < tex_data + tex_size) {
     814           0 :         ret = dxv_decompress_cgo(ctx, gb, tex_data, tex_size, op_data, &oi, op_size,
     815             :                                  &dst, &state, table0, table1, 0);
     816           0 :         if (ret < 0)
     817           0 :             return ret;
     818             :     }
     819             : 
     820           0 :     bytestream2_seek(gb, data_start + op_offset + skip - 8, SEEK_SET);
     821             : 
     822           0 :     return 0;
     823             : }
     824             : 
     825           0 : static int dxv_decompress_ycg6(AVCodecContext *avctx)
     826             : {
     827           0 :     DXVContext *ctx = avctx->priv_data;
     828           0 :     GetByteContext *gb = &ctx->gbc;
     829             :     int ret;
     830             : 
     831           0 :     ret = dxv_decompress_yo(ctx, gb, ctx->tex_data, ctx->tex_size,
     832           0 :                             ctx->op_data[0], ctx->op_size[0]);
     833           0 :     if (ret < 0)
     834           0 :         return ret;
     835             : 
     836           0 :     return dxv_decompress_cocg(ctx, gb, ctx->ctex_data, ctx->ctex_size,
     837             :                                ctx->op_data[1], ctx->op_data[2],
     838           0 :                                ctx->op_size[1], ctx->op_size[2]);
     839             : }
     840             : 
     841           0 : static int dxv_decompress_yg10(AVCodecContext *avctx)
     842             : {
     843           0 :     DXVContext *ctx = avctx->priv_data;
     844           0 :     GetByteContext *gb = &ctx->gbc;
     845             :     int ret;
     846             : 
     847           0 :     ret = dxv_decompress_cocg(ctx, gb, ctx->tex_data, ctx->tex_size,
     848             :                               ctx->op_data[0], ctx->op_data[3],
     849           0 :                               ctx->op_size[0], ctx->op_size[3]);
     850           0 :     if (ret < 0)
     851           0 :         return ret;
     852             : 
     853           0 :     return dxv_decompress_cocg(ctx, gb, ctx->ctex_data, ctx->ctex_size,
     854             :                                ctx->op_data[1], ctx->op_data[2],
     855           0 :                                ctx->op_size[1], ctx->op_size[2]);
     856             : }
     857             : 
     858           2 : static int dxv_decompress_dxt5(AVCodecContext *avctx)
     859             : {
     860           2 :     DXVContext *ctx = avctx->priv_data;
     861           2 :     GetByteContext *gbc = &ctx->gbc;
     862             :     uint32_t value, op;
     863           2 :     int idx, prev, state = 0;
     864           2 :     int pos = 4;
     865           2 :     int run = 0;
     866             :     int probe, check;
     867             : 
     868             :     /* Copy the first four elements */
     869           2 :     AV_WL32(ctx->tex_data +  0, bytestream2_get_le32(gbc));
     870           2 :     AV_WL32(ctx->tex_data +  4, bytestream2_get_le32(gbc));
     871           2 :     AV_WL32(ctx->tex_data +  8, bytestream2_get_le32(gbc));
     872           2 :     AV_WL32(ctx->tex_data + 12, bytestream2_get_le32(gbc));
     873             : 
     874             :     /* Process input until the whole texture has been filled */
     875      251412 :     while (pos + 2 <= ctx->tex_size / 4) {
     876      251408 :         if (run) {
     877      251400 :             run--;
     878             : 
     879      251400 :             prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
     880      251400 :             AV_WL32(ctx->tex_data + 4 * pos, prev);
     881      251400 :             pos++;
     882      251400 :             prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
     883      251400 :             AV_WL32(ctx->tex_data + 4 * pos, prev);
     884      251400 :             pos++;
     885             :         } else {
     886           8 :             if (bytestream2_get_bytes_left(gbc) < 1)
     887           0 :                 return AVERROR_INVALIDDATA;
     888           8 :             if (state == 0) {
     889           2 :                 value = bytestream2_get_le32(gbc);
     890           2 :                 state = 16;
     891             :             }
     892           8 :             op = value & 0x3;
     893           8 :             value >>= 2;
     894           8 :             state--;
     895             : 
     896           8 :             switch (op) {
     897           4 :             case 0:
     898             :                 /* Long copy */
     899           4 :                 check = bytestream2_get_byte(gbc) + 1;
     900           4 :                 if (check == 256) {
     901             :                     do {
     902           4 :                         probe = bytestream2_get_le16(gbc);
     903           4 :                         check += probe;
     904           4 :                     } while (probe == 0xFFFF);
     905             :                 }
     906        9722 :                 while (check && pos + 4 <= ctx->tex_size / 4) {
     907        9714 :                     prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
     908        9714 :                     AV_WL32(ctx->tex_data + 4 * pos, prev);
     909        9714 :                     pos++;
     910             : 
     911        9714 :                     prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
     912        9714 :                     AV_WL32(ctx->tex_data + 4 * pos, prev);
     913        9714 :                     pos++;
     914             : 
     915        9714 :                     prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
     916        9714 :                     AV_WL32(ctx->tex_data + 4 * pos, prev);
     917        9714 :                     pos++;
     918             : 
     919        9714 :                     prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
     920        9714 :                     AV_WL32(ctx->tex_data + 4 * pos, prev);
     921        9714 :                     pos++;
     922             : 
     923        9714 :                     check--;
     924             :                 }
     925             : 
     926             :                 /* Restart (or exit) the loop */
     927           4 :                 continue;
     928             :                 break;
     929           2 :             case 1:
     930             :                 /* Load new run value */
     931           2 :                 run = bytestream2_get_byte(gbc);
     932           2 :                 if (run == 255) {
     933             :                     do {
     934           4 :                         probe = bytestream2_get_le16(gbc);
     935           4 :                         run += probe;
     936           4 :                     } while (probe == 0xFFFF);
     937             :                 }
     938             : 
     939             :                 /* Copy two dwords from previous data */
     940           2 :                 prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
     941           2 :                 AV_WL32(ctx->tex_data + 4 * pos, prev);
     942           2 :                 pos++;
     943             : 
     944           2 :                 prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
     945           2 :                 AV_WL32(ctx->tex_data + 4 * pos, prev);
     946           2 :                 pos++;
     947           2 :                 break;
     948           0 :             case 2:
     949             :                 /* Copy two dwords from a previous index */
     950           0 :                 idx = 8 + bytestream2_get_le16(gbc);
     951           0 :                 if (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4)
     952           0 :                     return AVERROR_INVALIDDATA;
     953           0 :                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
     954           0 :                 AV_WL32(ctx->tex_data + 4 * pos, prev);
     955           0 :                 pos++;
     956             : 
     957           0 :                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
     958           0 :                 AV_WL32(ctx->tex_data + 4 * pos, prev);
     959           0 :                 pos++;
     960           0 :                 break;
     961           2 :             case 3:
     962             :                 /* Copy two dwords from input */
     963           2 :                 prev = bytestream2_get_le32(gbc);
     964           2 :                 AV_WL32(ctx->tex_data + 4 * pos, prev);
     965           2 :                 pos++;
     966             : 
     967           2 :                 prev = bytestream2_get_le32(gbc);
     968           2 :                 AV_WL32(ctx->tex_data + 4 * pos, prev);
     969           2 :                 pos++;
     970           2 :                 break;
     971             :             }
     972             :         }
     973             : 
     974      251404 :         CHECKPOINT(4);
     975      251404 :         if (pos + 2 > ctx->tex_size / 4)
     976           0 :             return AVERROR_INVALIDDATA;
     977             : 
     978             :         /* Copy two elements from a previous offset or from the input buffer */
     979      251404 :         if (op) {
     980      245192 :             if (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4)
     981           0 :                 return AVERROR_INVALIDDATA;
     982      245192 :             prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
     983      245192 :             AV_WL32(ctx->tex_data + 4 * pos, prev);
     984      245192 :             pos++;
     985             : 
     986      245192 :             prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
     987      245192 :             AV_WL32(ctx->tex_data + 4 * pos, prev);
     988      245192 :             pos++;
     989             :         } else {
     990        6212 :             CHECKPOINT(4);
     991             : 
     992        6212 :             if (op && (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4))
     993           0 :                 return AVERROR_INVALIDDATA;
     994        6212 :             if (op)
     995        1608 :                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
     996             :             else
     997        4604 :                 prev = bytestream2_get_le32(gbc);
     998        6212 :             AV_WL32(ctx->tex_data + 4 * pos, prev);
     999        6212 :             pos++;
    1000             : 
    1001        6212 :             CHECKPOINT(4);
    1002             : 
    1003        6212 :             if (op)
    1004        3192 :                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
    1005             :             else
    1006        3020 :                 prev = bytestream2_get_le32(gbc);
    1007        6212 :             AV_WL32(ctx->tex_data + 4 * pos, prev);
    1008        6212 :             pos++;
    1009             :         }
    1010             :     }
    1011             : 
    1012           2 :     return 0;
    1013             : }
    1014             : 
    1015           4 : static int dxv_decompress_lzf(AVCodecContext *avctx)
    1016             : {
    1017           4 :     DXVContext *ctx = avctx->priv_data;
    1018           4 :     return ff_lzf_uncompress(&ctx->gbc, &ctx->tex_data, &ctx->tex_size);
    1019             : }
    1020             : 
    1021           0 : static int dxv_decompress_raw(AVCodecContext *avctx)
    1022             : {
    1023           0 :     DXVContext *ctx = avctx->priv_data;
    1024           0 :     GetByteContext *gbc = &ctx->gbc;
    1025             : 
    1026           0 :     if (bytestream2_get_bytes_left(gbc) < ctx->tex_size)
    1027           0 :         return AVERROR_INVALIDDATA;
    1028             : 
    1029           0 :     bytestream2_get_buffer(gbc, ctx->tex_data, ctx->tex_size);
    1030           0 :     return 0;
    1031             : }
    1032             : 
    1033           8 : static int dxv_decode(AVCodecContext *avctx, void *data,
    1034             :                       int *got_frame, AVPacket *avpkt)
    1035             : {
    1036           8 :     DXVContext *ctx = avctx->priv_data;
    1037             :     ThreadFrame tframe;
    1038           8 :     GetByteContext *gbc = &ctx->gbc;
    1039             :     int (*decompress_tex)(AVCodecContext *avctx);
    1040             :     const char *msgcomp, *msgtext;
    1041             :     uint32_t tag;
    1042           8 :     int version_major, version_minor = 0;
    1043           8 :     int size = 0, old_type = 0;
    1044             :     int ret;
    1045             : 
    1046           8 :     bytestream2_init(gbc, avpkt->data, avpkt->size);
    1047             : 
    1048           8 :     ctx->texture_block_h = 4;
    1049           8 :     ctx->texture_block_w = 4;
    1050             : 
    1051           8 :     avctx->pix_fmt = AV_PIX_FMT_RGBA;
    1052           8 :     avctx->colorspace = AVCOL_SPC_RGB;
    1053             : 
    1054           8 :     tag = bytestream2_get_le32(gbc);
    1055           8 :     switch (tag) {
    1056           2 :     case MKBETAG('D', 'X', 'T', '1'):
    1057           2 :         decompress_tex = dxv_decompress_dxt1;
    1058           2 :         ctx->tex_funct = ctx->texdsp.dxt1_block;
    1059           2 :         ctx->tex_rat   = 8;
    1060           2 :         ctx->tex_step  = 8;
    1061           2 :         msgcomp = "DXTR1";
    1062           2 :         msgtext = "DXT1";
    1063           2 :         break;
    1064           2 :     case MKBETAG('D', 'X', 'T', '5'):
    1065           2 :         decompress_tex = dxv_decompress_dxt5;
    1066           2 :         ctx->tex_funct = ctx->texdsp.dxt5_block;
    1067           2 :         ctx->tex_rat   = 4;
    1068           2 :         ctx->tex_step  = 16;
    1069           2 :         msgcomp = "DXTR5";
    1070           2 :         msgtext = "DXT5";
    1071           2 :         break;
    1072           0 :     case MKBETAG('Y', 'C', 'G', '6'):
    1073           0 :         decompress_tex = dxv_decompress_ycg6;
    1074           0 :         ctx->tex_funct_planar[0] = yo_block;
    1075           0 :         ctx->tex_funct_planar[1] = cocg_block;
    1076           0 :         ctx->tex_rat   = 8;
    1077           0 :         ctx->tex_step  = 32;
    1078           0 :         ctx->ctex_step = 16;
    1079           0 :         msgcomp = "YOCOCG6";
    1080           0 :         msgtext = "YCG6";
    1081           0 :         ctx->ctex_size = avctx->coded_width * avctx->coded_height / 4;
    1082           0 :         ctx->texture_block_h = 4;
    1083           0 :         ctx->texture_block_w = 16;
    1084           0 :         ctx->ctexture_block_h = 4;
    1085           0 :         ctx->ctexture_block_w = 4;
    1086           0 :         avctx->pix_fmt = AV_PIX_FMT_YUV420P;
    1087           0 :         avctx->colorspace = AVCOL_SPC_YCOCG;
    1088           0 :         break;
    1089           0 :     case MKBETAG('Y', 'G', '1', '0'):
    1090           0 :         decompress_tex = dxv_decompress_yg10;
    1091           0 :         ctx->tex_funct_planar[0] = yao_block;
    1092           0 :         ctx->tex_funct_planar[1] = cocg_block;
    1093           0 :         ctx->tex_rat   = 4;
    1094           0 :         ctx->tex_step  = 64;
    1095           0 :         ctx->ctex_step = 16;
    1096           0 :         msgcomp = "YAOCOCG10";
    1097           0 :         msgtext = "YG10";
    1098           0 :         ctx->ctex_size = avctx->coded_width * avctx->coded_height / 4;
    1099           0 :         ctx->texture_block_h = 4;
    1100           0 :         ctx->texture_block_w = 16;
    1101           0 :         ctx->ctexture_block_h = 4;
    1102           0 :         ctx->ctexture_block_w = 4;
    1103           0 :         avctx->pix_fmt = AV_PIX_FMT_YUVA420P;
    1104           0 :         avctx->colorspace = AVCOL_SPC_YCOCG;
    1105           0 :         break;
    1106           4 :     default:
    1107             :         /* Old version does not have a real header, just size and type. */
    1108           4 :         size = tag & 0x00FFFFFF;
    1109           4 :         old_type = tag >> 24;
    1110           4 :         version_major = (old_type & 0x0F) - 1;
    1111             : 
    1112           4 :         if (old_type & 0x80) {
    1113           0 :             msgcomp = "RAW";
    1114           0 :             decompress_tex = dxv_decompress_raw;
    1115             :         } else {
    1116           4 :             msgcomp = "LZF";
    1117           4 :             decompress_tex = dxv_decompress_lzf;
    1118             :         }
    1119             : 
    1120           4 :         if (old_type & 0x40) {
    1121           2 :             msgtext = "DXT5";
    1122             : 
    1123           2 :             ctx->tex_funct = ctx->texdsp.dxt5_block;
    1124           2 :             ctx->tex_step  = 16;
    1125           2 :         } else if (old_type & 0x20 || version_major == 1) {
    1126           2 :             msgtext = "DXT1";
    1127             : 
    1128           2 :             ctx->tex_funct = ctx->texdsp.dxt1_block;
    1129           2 :             ctx->tex_step  = 8;
    1130             :         } else {
    1131           0 :             av_log(avctx, AV_LOG_ERROR, "Unsupported header (0x%08"PRIX32")\n.", tag);
    1132           0 :             return AVERROR_INVALIDDATA;
    1133             :         }
    1134           4 :         ctx->tex_rat = 1;
    1135           4 :         break;
    1136             :     }
    1137             : 
    1138           8 :     ctx->slice_count = av_clip(avctx->thread_count, 1,
    1139           8 :                                avctx->coded_height / FFMAX(ctx->texture_block_h,
    1140             :                                                            ctx->ctexture_block_h));
    1141             : 
    1142             :     /* New header is 12 bytes long. */
    1143           8 :     if (!old_type) {
    1144           4 :         version_major = bytestream2_get_byte(gbc) - 1;
    1145           4 :         version_minor = bytestream2_get_byte(gbc);
    1146             : 
    1147             :         /* Encoder copies texture data when compression is not advantageous. */
    1148           4 :         if (bytestream2_get_byte(gbc)) {
    1149           0 :             msgcomp = "RAW";
    1150           0 :             ctx->tex_rat = 1;
    1151           0 :             decompress_tex = dxv_decompress_raw;
    1152             :         }
    1153             : 
    1154           4 :         bytestream2_skip(gbc, 1); // unknown
    1155           4 :         size = bytestream2_get_le32(gbc);
    1156             :     }
    1157           8 :     av_log(avctx, AV_LOG_DEBUG,
    1158             :            "%s compression with %s texture (version %d.%d)\n",
    1159             :            msgcomp, msgtext, version_major, version_minor);
    1160             : 
    1161           8 :     if (size != bytestream2_get_bytes_left(gbc)) {
    1162           0 :         av_log(avctx, AV_LOG_ERROR,
    1163             :                "Incomplete or invalid file (header %d, left %u).\n",
    1164             :                size, bytestream2_get_bytes_left(gbc));
    1165           0 :         return AVERROR_INVALIDDATA;
    1166             :     }
    1167             : 
    1168           8 :     ctx->tex_size = avctx->coded_width * avctx->coded_height * 4 / ctx->tex_rat;
    1169           8 :     ret = av_reallocp(&ctx->tex_data, ctx->tex_size + AV_INPUT_BUFFER_PADDING_SIZE);
    1170           8 :     if (ret < 0)
    1171           0 :         return ret;
    1172             : 
    1173           8 :     if (ctx->ctex_size) {
    1174             :         int i;
    1175             : 
    1176           0 :         ctx->op_size[0] = avctx->coded_width * avctx->coded_height / 16;
    1177           0 :         ctx->op_size[1] = avctx->coded_width * avctx->coded_height / 32;
    1178           0 :         ctx->op_size[2] = avctx->coded_width * avctx->coded_height / 32;
    1179           0 :         ctx->op_size[3] = avctx->coded_width * avctx->coded_height / 16;
    1180             : 
    1181           0 :         ret = av_reallocp(&ctx->ctex_data, ctx->ctex_size + AV_INPUT_BUFFER_PADDING_SIZE);
    1182           0 :         if (ret < 0)
    1183           0 :             return ret;
    1184           0 :         for (i = 0; i < 4; i++) {
    1185           0 :             ret = av_reallocp(&ctx->op_data[i], ctx->op_size[i]);
    1186           0 :             if (ret < 0)
    1187           0 :                 return ret;
    1188             :         }
    1189             :     }
    1190             : 
    1191             :     /* Decompress texture out of the intermediate compression. */
    1192           8 :     ret = decompress_tex(avctx);
    1193           8 :     if (ret < 0)
    1194           0 :         return ret;
    1195             : 
    1196           8 :     tframe.f = data;
    1197           8 :     ret = ff_thread_get_buffer(avctx, &tframe, 0);
    1198           8 :     if (ret < 0)
    1199           0 :         return ret;
    1200             : 
    1201             :     /* Now decompress the texture with the standard functions. */
    1202          16 :     avctx->execute2(avctx, decompress_texture_thread,
    1203           8 :                     tframe.f, NULL, ctx->slice_count);
    1204             : 
    1205             :     /* Frame is ready to be output. */
    1206           8 :     tframe.f->pict_type = AV_PICTURE_TYPE_I;
    1207           8 :     tframe.f->key_frame = 1;
    1208           8 :     *got_frame = 1;
    1209             : 
    1210           8 :     return avpkt->size;
    1211             : }
    1212             : 
    1213           8 : static int dxv_init(AVCodecContext *avctx)
    1214             : {
    1215           8 :     DXVContext *ctx = avctx->priv_data;
    1216           8 :     int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
    1217             : 
    1218           8 :     if (ret < 0) {
    1219           0 :         av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n",
    1220             :                avctx->width, avctx->height);
    1221           0 :         return ret;
    1222             :     }
    1223             : 
    1224             :     /* Codec requires 16x16 alignment. */
    1225           8 :     avctx->coded_width  = FFALIGN(avctx->width,  16);
    1226           8 :     avctx->coded_height = FFALIGN(avctx->height, 16);
    1227             : 
    1228           8 :     ff_texturedsp_init(&ctx->texdsp);
    1229             : 
    1230           8 :     return 0;
    1231             : }
    1232             : 
    1233           8 : static int dxv_close(AVCodecContext *avctx)
    1234             : {
    1235           8 :     DXVContext *ctx = avctx->priv_data;
    1236             : 
    1237           8 :     av_freep(&ctx->tex_data);
    1238           8 :     av_freep(&ctx->ctex_data);
    1239           8 :     av_freep(&ctx->op_data[0]);
    1240           8 :     av_freep(&ctx->op_data[1]);
    1241           8 :     av_freep(&ctx->op_data[2]);
    1242           8 :     av_freep(&ctx->op_data[3]);
    1243             : 
    1244           8 :     return 0;
    1245             : }
    1246             : 
    1247             : AVCodec ff_dxv_decoder = {
    1248             :     .name           = "dxv",
    1249             :     .long_name      = NULL_IF_CONFIG_SMALL("Resolume DXV"),
    1250             :     .type           = AVMEDIA_TYPE_VIDEO,
    1251             :     .id             = AV_CODEC_ID_DXV,
    1252             :     .init           = dxv_init,
    1253             :     .decode         = dxv_decode,
    1254             :     .close          = dxv_close,
    1255             :     .priv_data_size = sizeof(DXVContext),
    1256             :     .capabilities   = AV_CODEC_CAP_DR1 |
    1257             :                       AV_CODEC_CAP_SLICE_THREADS |
    1258             :                       AV_CODEC_CAP_FRAME_THREADS,
    1259             :     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
    1260             :                       FF_CODEC_CAP_INIT_CLEANUP,
    1261             : };

Generated by: LCOV version 1.13