Merge commit 'c45fcf30cfab687004ed1cdc06ebaa21f4262a0b'
authorHendrik Leppkes <h.leppkes@gmail.com>
Mon, 7 Sep 2015 14:07:07 +0000 (16:07 +0200)
committerHendrik Leppkes <h.leppkes@gmail.com>
Mon, 7 Sep 2015 14:07:07 +0000 (16:07 +0200)
* commit 'c45fcf30cfab687004ed1cdc06ebaa21f4262a0b':
  DXV decoder

Merged-by: Hendrik Leppkes <h.leppkes@gmail.com>
15 files changed:
1  2 
Changelog
configure
doc/general.texi
libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/avcodec.h
libavcodec/dxv.c
libavcodec/utils.c
libavcodec/version.h
libavformat/isom.c
tests/fate/video.mak
tests/ref/fate/dxv-dxt1
tests/ref/fate/dxv-dxt5
tests/ref/fate/dxv3-dxt1
tests/ref/fate/dxv3-dxt5

diff --cc Changelog
+++ b/Changelog
@@@ -2,103 -2,17 +2,104 @@@ Entries are sorted chronologically fro
  releases are sorted from youngest to oldest.
  
  version <next>:
 -- aliases and defaults for Ogg subtypes (opus, spx)
 -- HEVC/H.265 RTP payload format (draft v6) packetizer and depacketizer
 -- avplay now exits by default at the end of playback
 -- XCB-based screen-grabber
 -- creating DASH compatible fragmented MP4, MPEG-DASH segmenting muxer
 -- H.261 RTP payload format (RFC 4587) depacketizer and experimental packetizer
++- DXV decoding
 +
 +
 +version 2.8:
 +- colorkey video filter
 +- BFSTM/BCSTM demuxer
 +- little-endian ADPCM_THP decoder
 +- Hap decoder and encoder
 +- DirectDraw Surface image/texture decoder
 +- ssim filter
 +- optional new ASF demuxer
 +- showvolume filter
 +- Many improvements to the JPEG 2000 decoder
 +- Go2Meeting decoding support
 +- adrawgraph audio and drawgraph video filter
 +- removegrain video filter
 +- Intel QSV-accelerated MPEG-2 video and HEVC encoding
 +- Intel QSV-accelerated MPEG-2 video and HEVC decoding
 +- Intel QSV-accelerated VC-1 video decoding
 +- libkvazaar HEVC encoder
 +- erosion, dilation, deflate and inflate video filters
 +- Dynamic Audio Normalizer as dynaudnorm filter
 +- Reverse video and areverse audio filter
 +- Random filter
 +- deband filter
 +- AAC fixed-point decoding
 +- sidechaincompress audio filter
 +- bitstream filter for converting HEVC from MP4 to Annex B
 +- acrossfade audio filter
 +- allyuv and allrgb video sources
 +- atadenoise video filter
 +- OS X VideoToolbox support
 +- aphasemeter filter
 +- showfreqs filter
 +- vectorscope filter
 +- waveform filter
 +- hstack and vstack filter
 +- Support DNx100 (1440x1080@8)
 +- VAAPI hevc hwaccel
 +- VDPAU hevc hwaccel
 +- framerate filter
 +- Switched default encoders for webm to VP9 and Opus
 +- Removed experimental flag from the JPEG 2000 encoder
 +
 +
 +version 2.7:
 +- FFT video filter
 +- TDSC decoder
 +- DTS lossless extension (XLL) decoding (not lossless, disabled by default)
 +- showwavespic filter
 +- DTS decoding through libdcadec
 +- Drop support for nvenc API before 5.0
 +- nvenc HEVC encoder
 +- Detelecine filter
 +- Intel QSV-accelerated H.264 encoding
 +- MMAL-accelerated H.264 decoding
 +- basic APNG encoder and muxer with default extension "apng"
 +- unpack DivX-style packed B-frames in MPEG-4 bitstream filter
 +- WebM Live Chunk Muxer
 +- nvenc level and tier options
 +- chorus filter
 +- Canopus HQ/HQA decoder
 +- Automatically rotate videos based on metadata in ffmpeg
 +- improved Quickdraw compatibility
 +- VP9 high bit-depth and extended colorspaces decoding support
 +- WebPAnimEncoder API when available for encoding and muxing WebP
 +- Direct3D11-accelerated decoding
 +- Support Secure Transport
 +- Multipart JPEG demuxer
 +
 +
 +version 2.6:
 +- nvenc encoder
 +- 10bit spp filter
 +- colorlevels filter
 +- RIFX format for *.wav files
  - RTP/mpegts muxer
 -- VP8 in Ogg demuxing
 +- non continuous cache protocol support
 +- tblend filter
 +- cropdetect support for non 8bpp, absolute (if limit >= 1) and relative (if limit < 1.0) threshold
 +- Camellia symmetric block cipher
  - OpenH264 encoder wrapper
 +- VOC seeking support
 +- Closed caption Decoder
 +- fspp, uspp, pp7 MPlayer postprocessing filters ported to native filters
 +- showpalette filter
 +- Twofish symmetric block cipher
  - Support DNx100 (960x720@8)
 -- Direct3D11-accelerated decoding
 +- eq2 filter ported from libmpcodecs as eq filter
 +- removed libmpcodecs
 +- Changed default DNxHD colour range in QuickTime .mov derivatives to mpeg range
 +- ported softpulldown filter from libmpcodecs as repeatfields filter
 +- dcshift filter
 +- RTP depacketizer for loss tolerant payload format for MP3 audio (RFC 5219)
 +- RTP depacketizer for AC3 payload format (RFC 4184)
 +- palettegen and paletteuse filters
 +- VP9 RTP payload format (draft 0) experimental depacketizer
 +- RTP depacketizer for DV (RFC 6469)
  - DXVA2-accelerated HEVC decoding
  - AAC ELD 480 decoding
  - Intel QSV-accelerated H.264 decoding
diff --cc configure
+++ b/configure
@@@ -2188,7 -1840,8 +2188,8 @@@ dnxhd_decoder_select="blockdsp idctdsp
  dnxhd_encoder_select="aandcttables blockdsp fdctdsp idctdsp mpegvideoenc pixblockdsp"
  dvvideo_decoder_select="dvprofile idctdsp"
  dvvideo_encoder_select="dvprofile fdctdsp me_cmp pixblockdsp"
 -dxa_decoder_deps="zlib"
 +dxa_decoder_select="zlib"
+ dxv_decoder_select="lzf texturedsp"
  eac3_decoder_select="ac3_decoder"
  eac3_encoder_select="ac3_encoder"
  eamad_decoder_select="aandcttables blockdsp bswapdsp idctdsp mpegvideo"
@@@ -461,8 -398,8 +461,9 @@@ library
      @tab File format used by RED Digital cameras, contains JPEG 2000 frames and PCM audio.
  @item RealMedia                 @tab X @tab X
  @item Redirector                @tab   @tab X
 +@item RedSpark                  @tab   @tab X
  @item Renderware TeXture Dictionary @tab   @tab X
+ @item Resolume DXV              @tab   @tab X
  @item RL2                       @tab   @tab X
      @tab Audio and video format used in some games by Entertainment Software Partners.
  @item RPL/ARMovie               @tab   @tab X
@@@ -242,7 -196,8 +242,8 @@@ OBJS-$(CONFIG_DVVIDEO_DECODER)         
  OBJS-$(CONFIG_DVVIDEO_ENCODER)         += dvenc.o dv.o dvdata.o
  OBJS-$(CONFIG_DXA_DECODER)             += dxa.o
  OBJS-$(CONFIG_DXTORY_DECODER)          += dxtory.o
 -OBJS-$(CONFIG_EAC3_DECODER)            += eac3dec.o eac3_data.o
+ OBJS-$(CONFIG_DXV_DECODER)             += dxv.o
 +OBJS-$(CONFIG_EAC3_DECODER)            += eac3_data.o
  OBJS-$(CONFIG_EAC3_ENCODER)            += eac3enc.o eac3_data.o
  OBJS-$(CONFIG_EACMV_DECODER)           += eacmv.o
  OBJS-$(CONFIG_EAMAD_DECODER)           += eamad.o eaidct.o mpeg12.o \
Simple merge
@@@ -295,37 -298,8 +295,38 @@@ enum AVCodecID 
      AV_CODEC_ID_HQ_HQA,
      AV_CODEC_ID_HAP,
      AV_CODEC_ID_DDS,
+     AV_CODEC_ID_DXV,
  
 +    AV_CODEC_ID_BRENDER_PIX= MKBETAG('B','P','I','X'),
 +    AV_CODEC_ID_Y41P       = MKBETAG('Y','4','1','P'),
 +    AV_CODEC_ID_ESCAPE130  = MKBETAG('E','1','3','0'),
 +    AV_CODEC_ID_EXR        = MKBETAG('0','E','X','R'),
 +    AV_CODEC_ID_AVRP       = MKBETAG('A','V','R','P'),
 +
 +    AV_CODEC_ID_012V       = MKBETAG('0','1','2','V'),
 +    AV_CODEC_ID_G2M        = MKBETAG( 0 ,'G','2','M'),
 +    AV_CODEC_ID_AVUI       = MKBETAG('A','V','U','I'),
 +    AV_CODEC_ID_AYUV       = MKBETAG('A','Y','U','V'),
 +    AV_CODEC_ID_TARGA_Y216 = MKBETAG('T','2','1','6'),
 +    AV_CODEC_ID_V308       = MKBETAG('V','3','0','8'),
 +    AV_CODEC_ID_V408       = MKBETAG('V','4','0','8'),
 +    AV_CODEC_ID_YUV4       = MKBETAG('Y','U','V','4'),
 +    AV_CODEC_ID_SANM       = MKBETAG('S','A','N','M'),
 +    AV_CODEC_ID_PAF_VIDEO  = MKBETAG('P','A','F','V'),
 +    AV_CODEC_ID_AVRN       = MKBETAG('A','V','R','n'),
 +    AV_CODEC_ID_CPIA       = MKBETAG('C','P','I','A'),
 +    AV_CODEC_ID_XFACE      = MKBETAG('X','F','A','C'),
 +    AV_CODEC_ID_SGIRLE     = MKBETAG('S','G','I','R'),
 +    AV_CODEC_ID_MVC1       = MKBETAG('M','V','C','1'),
 +    AV_CODEC_ID_MVC2       = MKBETAG('M','V','C','2'),
 +    AV_CODEC_ID_SNOW       = MKBETAG('S','N','O','W'),
 +    AV_CODEC_ID_WEBP       = MKBETAG('W','E','B','P'),
 +    AV_CODEC_ID_SMVJPEG    = MKBETAG('S','M','V','J'),
 +    AV_CODEC_ID_HEVC       = MKBETAG('H','2','6','5'),
 +#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC
 +    AV_CODEC_ID_VP7        = MKBETAG('V','P','7','0'),
 +    AV_CODEC_ID_APNG       = MKBETAG('A','P','N','G'),
 +
      /* various PCM "codecs" */
      AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
      AV_CODEC_ID_PCM_S16LE = 0x10000,
index 0000000,dc11f38..b0e252b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,461 +1,461 @@@
 - * This file is part of Libav.
+ /*
+  * Resolume DXV decoder
+  * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include <stdint.h>
+ #include "libavutil/imgutils.h"
+ #include "avcodec.h"
+ #include "bytestream.h"
+ #include "internal.h"
+ #include "lzf.h"
+ #include "texturedsp.h"
+ #include "thread.h"
+ typedef struct DXVContext {
+     TextureDSPContext texdsp;
+     GetByteContext gbc;
+     uint8_t *tex_data;  // Compressed texture
+     int tex_rat;        // Compression ratio
+     int tex_step;       // Distance between blocks
+     int64_t tex_size;   // Texture size
+     /* Optimal number of slices for parallel decoding */
+     int slice_count;
+     /* Pointer to the selected decompression function */
+     int (*tex_funct)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block);
+ } DXVContext;
+ static int decompress_texture_thread(AVCodecContext *avctx, void *arg,
+                                      int slice, int thread_nb)
+ {
+     DXVContext *ctx = avctx->priv_data;
+     AVFrame *frame = arg;
+     const uint8_t *d = ctx->tex_data;
+     int w_block = avctx->coded_width / TEXTURE_BLOCK_W;
+     int h_block = avctx->coded_height / TEXTURE_BLOCK_H;
+     int x, y;
+     int start_slice, end_slice;
+     int base_blocks_per_slice = h_block / ctx->slice_count;
+     int remainder_blocks = h_block % ctx->slice_count;
+     /* When the frame height (in blocks) doesn't divide evenly between the
+      * number of slices, spread the remaining blocks evenly between the first
+      * operations */
+     start_slice = slice * base_blocks_per_slice;
+     /* Add any extra blocks (one per slice) that have been added
+      * before this slice */
+     start_slice += FFMIN(slice, remainder_blocks);
+     end_slice = start_slice + base_blocks_per_slice;
+     /* Add an extra block if there are remainder blocks to be accounted for */
+     if (slice < remainder_blocks)
+         end_slice++;
+     for (y = start_slice; y < end_slice; y++) {
+         uint8_t *p = frame->data[0] + y * frame->linesize[0] * TEXTURE_BLOCK_H;
+         int off  = y * w_block;
+         for (x = 0; x < w_block; x++) {
+             ctx->tex_funct(p + x * 16, frame->linesize[0],
+                            d + (off + x) * ctx->tex_step);
+         }
+     }
+     return 0;
+ }
+ /* This scheme addresses already decoded elements depending on 2-bit status:
+  *   0 -> copy new element
+  *   1 -> copy one element from position -x
+  *   2 -> copy one element from position -(get_byte() + 2) * x
+  *   3 -> copy one element from position -(get_16le() + 0x102) * x
+  * x is always 2 for dxt1 and 4 for dxt5. */
+ #define CHECKPOINT(x)                                                         \
+     do {                                                                      \
+         if (state == 0) {                                                     \
+             value = bytestream2_get_le32(gbc);                                \
+             state = 16;                                                       \
+         }                                                                     \
+         op = value & 0x3;                                                     \
+         value >>= 2;                                                          \
+         state--;                                                              \
+         switch (op) {                                                         \
+         case 1:                                                               \
+             idx = x;                                                          \
+             break;                                                            \
+         case 2:                                                               \
+             idx = (bytestream2_get_byte(gbc) + 2) * x;                        \
+             break;                                                            \
+         case 3:                                                               \
+             idx = (bytestream2_get_le16(gbc) + 0x102) * x;                    \
+             break;                                                            \
+         }                                                                     \
+     } while(0)
+ static int dxv_decompress_dxt1(AVCodecContext *avctx)
+ {
+     DXVContext *ctx = avctx->priv_data;
+     GetByteContext *gbc = &ctx->gbc;
+     uint32_t value, prev, op;
+     int idx = 0, state = 0;
+     int pos = 2;
+     /* Copy the first two elements */
+     AV_WL32(ctx->tex_data, bytestream2_get_le32(gbc));
+     AV_WL32(ctx->tex_data + 4, bytestream2_get_le32(gbc));
+     /* Process input until the whole texture has been filled */
+     while (pos < ctx->tex_size / 4) {
+         CHECKPOINT(2);
+         /* Copy two elements from a previous offset or from the input buffer */
+         if (op) {
+             prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
+             AV_WL32(ctx->tex_data + 4 * pos, prev);
+             pos++;
+             prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
+             AV_WL32(ctx->tex_data + 4 * pos, prev);
+             pos++;
+         } else {
+             CHECKPOINT(2);
+             if (op)
+                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
+             else
+                 prev = bytestream2_get_le32(gbc);
+             AV_WL32(ctx->tex_data + 4 * pos, prev);
+             pos++;
+             CHECKPOINT(2);
+             if (op)
+                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
+             else
+                 prev = bytestream2_get_le32(gbc);
+             AV_WL32(ctx->tex_data + 4 * pos, prev);
+             pos++;
+         }
+     }
+     return 0;
+ }
+ static int dxv_decompress_dxt5(AVCodecContext *avctx)
+ {
+     DXVContext *ctx = avctx->priv_data;
+     GetByteContext *gbc = &ctx->gbc;
+     uint32_t value, op;
+     int idx, prev, state = 0;
+     int pos = 4;
+     int run = 0;
+     int probe, check;
+     /* Copy the first four elements */
+     AV_WL32(ctx->tex_data +  0, bytestream2_get_le32(gbc));
+     AV_WL32(ctx->tex_data +  4, bytestream2_get_le32(gbc));
+     AV_WL32(ctx->tex_data +  8, bytestream2_get_le32(gbc));
+     AV_WL32(ctx->tex_data + 12, bytestream2_get_le32(gbc));
+     /* Process input until the whole texture has been filled */
+     while (pos < ctx->tex_size / 4) {
+         if (run) {
+             run--;
+             prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
+             AV_WL32(ctx->tex_data + 4 * pos, prev);
+             pos++;
+             prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
+             AV_WL32(ctx->tex_data + 4 * pos, prev);
+             pos++;
+         } else {
+             if (state == 0) {
+                 value = bytestream2_get_le32(gbc);
+                 state = 16;
+             }
+             op = value & 0x3;
+             value >>= 2;
+             state--;
+             switch (op) {
+             case 0:
+                 /* Long copy */
+                 check = bytestream2_get_byte(gbc) + 1;
+                 if (check == 256) {
+                     do {
+                         probe = bytestream2_get_le16(gbc);
+                         check += probe;
+                     } while (probe == 0xFFFF);
+                 }
+                 while (check && pos < ctx->tex_size / 4) {
+                     prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
+                     AV_WL32(ctx->tex_data + 4 * pos, prev);
+                     pos++;
+                     prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
+                     AV_WL32(ctx->tex_data + 4 * pos, prev);
+                     pos++;
+                     prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
+                     AV_WL32(ctx->tex_data + 4 * pos, prev);
+                     pos++;
+                     prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
+                     AV_WL32(ctx->tex_data + 4 * pos, prev);
+                     pos++;
+                     check--;
+                 }
+                 /* Restart (or exit) the loop */
+                 continue;
+                 break;
+             case 1:
+                 /* Load new run value */
+                 run = bytestream2_get_byte(gbc);
+                 if (run == 255) {
+                     do {
+                         probe = bytestream2_get_le16(gbc);
+                         run += probe;
+                     } while (probe == 0xFFFF);
+                 }
+                 /* Copy two dwords from previous data */
+                 prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
+                 AV_WL32(ctx->tex_data + 4 * pos, prev);
+                 pos++;
+                 prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
+                 AV_WL32(ctx->tex_data + 4 * pos, prev);
+                 pos++;
+                 break;
+             case 2:
+                 /* Copy two dwords from a previous index */
+                 idx = 8 + bytestream2_get_le16(gbc);
+                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
+                 AV_WL32(ctx->tex_data + 4 * pos, prev);
+                 pos++;
+                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
+                 AV_WL32(ctx->tex_data + 4 * pos, prev);
+                 pos++;
+                 break;
+             case 3:
+                 /* Copy two dwords from input */
+                 prev = bytestream2_get_le32(gbc);
+                 AV_WL32(ctx->tex_data + 4 * pos, prev);
+                 pos++;
+                 prev = bytestream2_get_le32(gbc);
+                 AV_WL32(ctx->tex_data + 4 * pos, prev);
+                 pos++;
+                 break;
+             }
+         }
+         CHECKPOINT(4);
+         /* Copy two elements from a previous offset or from the input buffer */
+         if (op) {
+             prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
+             AV_WL32(ctx->tex_data + 4 * pos, prev);
+             pos++;
+             prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
+             AV_WL32(ctx->tex_data + 4 * pos, prev);
+             pos++;
+         } else {
+             CHECKPOINT(4);
+             if (op)
+                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
+             else
+                 prev = bytestream2_get_le32(gbc);
+             AV_WL32(ctx->tex_data + 4 * pos, prev);
+             pos++;
+             CHECKPOINT(4);
+             if (op)
+                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
+             else
+                 prev = bytestream2_get_le32(gbc);
+             AV_WL32(ctx->tex_data + 4 * pos, prev);
+             pos++;
+         }
+     }
+     return 0;
+ }
+ static int dxv_decompress_lzf(AVCodecContext *avctx)
+ {
+     DXVContext *ctx = avctx->priv_data;
+     return ff_lzf_uncompress(&ctx->gbc, &ctx->tex_data, &ctx->tex_size);
+ }
+ static int dxv_decode(AVCodecContext *avctx, void *data,
+                       int *got_frame, AVPacket *avpkt)
+ {
+     DXVContext *ctx = avctx->priv_data;
+     ThreadFrame tframe;
+     GetByteContext *gbc = &ctx->gbc;
+     int (*decompress_tex)(AVCodecContext *avctx);
+     uint32_t tag;
+     int channels, size = 0, old_type = 0;
+     int ret;
+     bytestream2_init(gbc, avpkt->data, avpkt->size);
+     tag = bytestream2_get_le32(gbc);
+     switch (tag) {
+     case MKBETAG('D', 'X', 'T', '1'):
+         decompress_tex = dxv_decompress_dxt1;
+         ctx->tex_funct = ctx->texdsp.dxt1_block;
+         ctx->tex_rat   = 8;
+         ctx->tex_step  = 8;
+         av_log(avctx, AV_LOG_DEBUG, "DXTR1 compression and DXT1 texture ");
+         break;
+     case MKBETAG('D', 'X', 'T', '5'):
+         decompress_tex = dxv_decompress_dxt5;
+         ctx->tex_funct = ctx->texdsp.dxt5_block;
+         ctx->tex_rat   = 4;
+         ctx->tex_step  = 16;
+         av_log(avctx, AV_LOG_DEBUG, "DXTR5 compression and DXT5 texture ");
+         break;
+     case MKBETAG('Y', 'C', 'G', '6'):
+     case MKBETAG('Y', 'G', '1', '0'):
+         avpriv_report_missing_feature(avctx, "Tag 0x%08X", tag);
+         return AVERROR_PATCHWELCOME;
+     default:
+         /* Old version does not have a real header, just size and type. */
+         size = tag & 0x00FFFFFF;
+         old_type = tag >> 24;
+         channels = old_type & 0x0F;
+         if (old_type & 0x40) {
+             av_log(avctx, AV_LOG_DEBUG, "LZF compression and DXT5 texture ");
+             ctx->tex_funct = ctx->texdsp.dxt5_block;
+             ctx->tex_step  = 16;
+         } else if (old_type & 0x20) {
+             av_log(avctx, AV_LOG_DEBUG, "LZF compression and DXT1 texture ");
+             ctx->tex_funct = ctx->texdsp.dxt1_block;
+             ctx->tex_step  = 8;
+         } else {
+             av_log(avctx, AV_LOG_ERROR, "Unsupported header (0x%08X)\n.", tag);
+             return AVERROR_INVALIDDATA;
+         }
+         decompress_tex = dxv_decompress_lzf;
+         ctx->tex_rat = 1;
+         break;
+     }
+     /* New header is 12 bytes long. */
+     if (!old_type) {
+         channels = bytestream2_get_byte(gbc);
+         bytestream2_skip(gbc, 3); // unknown
+         size = bytestream2_get_le32(gbc);
+     }
+     av_log(avctx, AV_LOG_DEBUG, "(%d channels)\n", channels);
+     if (size != bytestream2_get_bytes_left(gbc)) {
+         av_log(avctx, AV_LOG_ERROR, "Incomplete or invalid file (%u > %u)\n.",
+                size, bytestream2_get_bytes_left(gbc));
+         return AVERROR_INVALIDDATA;
+     }
+     ctx->tex_size = avctx->coded_width * avctx->coded_height * 4 / ctx->tex_rat;
+     ret = av_reallocp(&ctx->tex_data, ctx->tex_size);
+     if (ret < 0)
+         return ret;
+     /* Decompress texture out of the intermediate compression. */
+     ret = decompress_tex(avctx);
+     if (ret < 0)
+         return ret;
+     tframe.f = data;
+     ret = ff_thread_get_buffer(avctx, &tframe, 0);
+     if (ret < 0)
+         return ret;
+     ff_thread_finish_setup(avctx);
+     /* Now decompress the texture with the standard functions. */
+     avctx->execute2(avctx, decompress_texture_thread,
+                     tframe.f, NULL, ctx->slice_count);
+     /* Frame is ready to be output. */
+     tframe.f->pict_type = AV_PICTURE_TYPE_I;
+     tframe.f->key_frame = 1;
+     *got_frame = 1;
+     return avpkt->size;
+ }
+ static int dxv_init(AVCodecContext *avctx)
+ {
+     DXVContext *ctx = avctx->priv_data;
+     int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
+     if (ret < 0) {
+         av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n",
+                avctx->width, avctx->height);
+         return ret;
+     }
+     /* Codec requires 16x16 alignment. */
+     avctx->coded_width  = FFALIGN(avctx->width,  16);
+     avctx->coded_height = FFALIGN(avctx->height, 16);
+     ff_texturedsp_init(&ctx->texdsp);
+     avctx->pix_fmt = AV_PIX_FMT_RGBA;
+     ctx->slice_count = av_clip(avctx->thread_count, 1,
+                                avctx->coded_height / TEXTURE_BLOCK_H);
+     return 0;
+ }
+ static int dxv_close(AVCodecContext *avctx)
+ {
+     DXVContext *ctx = avctx->priv_data;
+     av_freep(&ctx->tex_data);
+     return 0;
+ }
+ AVCodec ff_dxv_decoder = {
+     .name           = "dxv",
+     .long_name      = NULL_IF_CONFIG_SMALL("Resolume DXV"),
+     .type           = AVMEDIA_TYPE_VIDEO,
+     .id             = AV_CODEC_ID_DXV,
+     .init           = dxv_init,
+     .decode         = dxv_decode,
+     .close          = dxv_close,
+     .priv_data_size = sizeof(DXVContext),
+     .capabilities   = AV_CODEC_CAP_DR1 |
+                       AV_CODEC_CAP_SLICE_THREADS |
+                       AV_CODEC_CAP_FRAME_THREADS,
+     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
+                       FF_CODEC_CAP_INIT_CLEANUP,
+ };
@@@ -1221,16 -899,7 +1221,16 @@@ int attribute_align_arg avcodec_open2(A
      if ((ret = av_opt_set_dict(avctx, &tmp)) < 0)
          goto free_and_end;
  
 -    if (avctx->coded_width && avctx->coded_height && !avctx->width && !avctx->height)
 +    if (avctx->codec_whitelist && av_match_list(codec->name, avctx->codec_whitelist, ',') <= 0) {
 +        av_log(avctx, AV_LOG_ERROR, "Codec (%s) not on whitelist\n", codec->name);
 +        ret = AVERROR(EINVAL);
 +        goto free_and_end;
 +    }
 +
-     // only call ff_set_dimensions() for non H.264/VP6F codecs so as not to overwrite previously setup dimensions
++    // only call ff_set_dimensions() for non H.264/VP6F/DXV codecs so as not to overwrite previously setup dimensions
 +    if (!(avctx->coded_width && avctx->coded_height && avctx->width && avctx->height &&
-           (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_VP6F))) {
++          (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_VP6F || avctx->codec_id == AV_CODEC_ID_DXV))) {
 +    if (avctx->coded_width && avctx->coded_height)
          ret = ff_set_dimensions(avctx, avctx->coded_width, avctx->coded_height);
      else if (avctx->width && avctx->height)
          ret = ff_set_dimensions(avctx, avctx->width, avctx->height);
@@@ -28,9 -28,9 +28,9 @@@
  
  #include "libavutil/version.h"
  
 -#define LIBAVCODEC_VERSION_MAJOR 57
 -#define LIBAVCODEC_VERSION_MINOR  1
 -#define LIBAVCODEC_VERSION_MICRO  0
 +#define LIBAVCODEC_VERSION_MAJOR  57
- #define LIBAVCODEC_VERSION_MINOR   0
++#define LIBAVCODEC_VERSION_MINOR   1
 +#define LIBAVCODEC_VERSION_MICRO 100
  
  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                 LIBAVCODEC_VERSION_MINOR, \
Simple merge
@@@ -141,10 -133,25 +141,25 @@@ fate-dxa-feeble: CMD = framecrc -i $(TA
  FATE_DXA += fate-dxa-scummvm
  fate-dxa-scummvm: CMD = framecrc -i $(TARGET_SAMPLES)/dxa/scummvm.dxa -pix_fmt rgb24
  
 -FATE_SAMPLES_AVCONV-$(call DEMDEC, DXA, DXA) += $(FATE_DXA)
 +FATE_VIDEO-$(call DEMDEC, DXA, DXA) += $(FATE_DXA)
  fate-dxa: $(FATE_DXA)
  
 -FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, DXV) += $(FATE_DXV)
+ FATE_DXV += fate-dxv-dxt1
+ fate-dxv-dxt1: CMD = framecrc -i $(TARGET_SAMPLES)/dxv/dxv-na.mov
+ FATE_DXV += fate-dxv-dxt5
+ fate-dxv-dxt5: CMD = framecrc -i $(TARGET_SAMPLES)/dxv/dxv-wa.mov
+ FATE_DXV += fate-dxv3-dxt1
+ fate-dxv3-dxt1: CMD = framecrc -i $(TARGET_SAMPLES)/dxv/dxv3-nqna.mov
+ FATE_DXV += fate-dxv3-dxt5
+ fate-dxv3-dxt5: CMD = framecrc -i $(TARGET_SAMPLES)/dxv/dxv3-nqwa.mov
 -FATE_SAMPLES_AVCONV-$(call DEMDEC, SEGAFILM, CINEPAK) += fate-film-cvid
++FATE_VIDEO-$(call DEMDEC, MOV, DXV) += $(FATE_DXV)
+ fate-dxv: $(FATE_DXV)
 +FATE_VIDEO-$(call DEMDEC, SEGAFILM, CINEPAK) += fate-film-cvid
  fate-film-cvid: CMD = framecrc -i $(TARGET_SAMPLES)/film/logo-capcom.cpk -an
  
  FATE_FLIC += fate-flic-af11-palette-change
index 0000000,9b49380..128daba
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,2 +1,2 @@@
 -#tb 0: 1/30000
 -0,          0,          0,        0,  8294400, 0x0797cd53
++#tb 0: 1001/30000
++0,          0,          0,        1,  8294400, 0x0797cd53
index 0000000,9b49380..128daba
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,2 +1,2 @@@
 -#tb 0: 1/30000
 -0,          0,          0,        0,  8294400, 0x0797cd53
++#tb 0: 1001/30000
++0,          0,          0,        1,  8294400, 0x0797cd53
index 0000000,c65ead9..e0f1f94
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,2 +1,2 @@@
 -#tb 0: 1/30000
 -0,          0,          0,        0,  8294400, 0x98bbcc85
++#tb 0: 1001/30000
++0,          0,          0,        1,  8294400, 0x98bbcc85
index 0000000,9b49380..128daba
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,2 +1,2 @@@
 -#tb 0: 1/30000
 -0,          0,          0,        0,  8294400, 0x0797cd53
++#tb 0: 1001/30000
++0,          0,          0,        1,  8294400, 0x0797cd53