FFmpeg
txd.c
Go to the documentation of this file.
1 /*
2  * Renderware TeXture Dictionary (.txd) image decoder
3  * Copyright (c) 2007 Ivo van Poorten
4  *
5  * See also: http://wiki.multimedia.cx/index.php?title=TXD
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/imgutils.h"
26 #include "bytestream.h"
27 #include "avcodec.h"
28 #include "internal.h"
29 #include "texturedsp.h"
30 
31 #define TXD_DXT1 0x31545844
32 #define TXD_DXT3 0x33545844
33 
34 static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
35  AVPacket *avpkt) {
36  GetByteContext gb;
37  TextureDSPContext dxtc;
38  AVFrame * const p = data;
39  unsigned int version, w, h, d3d_format, depth, stride, flags;
40  unsigned int y, v;
41  uint8_t *ptr;
42  uint32_t *pal;
43  int i, j;
44  int ret;
45 
46  ff_texturedsp_init(&dxtc);
47 
48  bytestream2_init(&gb, avpkt->data, avpkt->size);
49  version = bytestream2_get_le32(&gb);
50  bytestream2_skip(&gb, 72);
51  d3d_format = bytestream2_get_le32(&gb);
52  w = bytestream2_get_le16(&gb);
53  h = bytestream2_get_le16(&gb);
54  depth = bytestream2_get_byte(&gb);
55  bytestream2_skip(&gb, 2);
56  flags = bytestream2_get_byte(&gb);
57 
58  if (version < 8 || version > 9) {
59  avpriv_report_missing_feature(avctx, "Texture data version %u", version);
60  return AVERROR_PATCHWELCOME;
61  }
62 
63  if (depth == 8) {
64  avctx->pix_fmt = AV_PIX_FMT_PAL8;
65  } else if (depth == 16 || depth == 32) {
66  avctx->pix_fmt = AV_PIX_FMT_RGBA;
67  } else {
68  avpriv_report_missing_feature(avctx, "Color depth of %u", depth);
69  return AVERROR_PATCHWELCOME;
70  }
71 
72  if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
73  return ret;
74 
75  avctx->coded_width = FFALIGN(w, 4);
76  avctx->coded_height = FFALIGN(h, 4);
77 
78  if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
79  return ret;
80 
82 
83  ptr = p->data[0];
84  stride = p->linesize[0];
85 
86  if (depth == 8) {
87  pal = (uint32_t *) p->data[1];
88  for (y = 0; y < 256; y++) {
89  v = bytestream2_get_be32(&gb);
90  pal[y] = (v >> 8) + (v << 24);
91  }
92  if (bytestream2_get_bytes_left(&gb) < w * h)
93  return AVERROR_INVALIDDATA;
94  bytestream2_skip(&gb, 4);
95  for (y=0; y<h; y++) {
96  bytestream2_get_buffer(&gb, ptr, w);
97  ptr += stride;
98  }
99  } else if (depth == 16) {
100  bytestream2_skip(&gb, 4);
101  switch (d3d_format) {
102  case 0:
103  if (!(flags & 1))
104  goto unsupported;
105  case TXD_DXT1:
106  if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 8)
107  return AVERROR_INVALIDDATA;
108  for (j = 0; j < avctx->height; j += 4) {
109  for (i = 0; i < avctx->width; i += 4) {
110  uint8_t *p = ptr + i * 4 + j * stride;
111  int step = dxtc.dxt1_block(p, stride, gb.buffer);
112  bytestream2_skip(&gb, step);
113  }
114  }
115  break;
116  case TXD_DXT3:
117  if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 16)
118  return AVERROR_INVALIDDATA;
119  for (j = 0; j < avctx->height; j += 4) {
120  for (i = 0; i < avctx->width; i += 4) {
121  uint8_t *p = ptr + i * 4 + j * stride;
122  int step = dxtc.dxt3_block(p, stride, gb.buffer);
123  bytestream2_skip(&gb, step);
124  }
125  }
126  break;
127  default:
128  goto unsupported;
129  }
130  } else if (depth == 32) {
131  switch (d3d_format) {
132  case 0x15:
133  case 0x16:
134  if (bytestream2_get_bytes_left(&gb) < h * w * 4)
135  return AVERROR_INVALIDDATA;
136  for (y=0; y<h; y++) {
137  bytestream2_get_buffer(&gb, ptr, w * 4);
138  ptr += stride;
139  }
140  break;
141  default:
142  goto unsupported;
143  }
144  }
145 
146  *got_frame = 1;
147 
148  return avpkt->size;
149 
151  avpriv_report_missing_feature(avctx, "d3d format (%08x)", d3d_format);
152  return AVERROR_PATCHWELCOME;
153 }
154 
156  .name = "txd",
157  .long_name = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"),
158  .type = AVMEDIA_TYPE_VIDEO,
159  .id = AV_CODEC_ID_TXD,
160  .decode = txd_decode_frame,
161  .capabilities = AV_CODEC_CAP_DR1,
162 };
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:1756
misc image utilities
AVCodec ff_txd_decoder
Definition: txd.c:155
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:104
Texture block (4x4) module.
int size
Definition: avcodec.h:1481
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1778
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:133
int version
Definition: avisynth_c.h:858
AVCodec.
Definition: avcodec.h:3484
uint8_t
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:77
uint8_t * data
Definition: avcodec.h:1480
int(* dxt3_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)
Definition: texturedsp.h:49
const uint8_t * buffer
Definition: bytestream.h:34
#define FFALIGN(x, a)
Definition: macros.h:48
DXGI_FORMAT d3d_format
static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: txd.c:34
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:164
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:263
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:154
const char * name
Name of the codec implementation.
Definition: avcodec.h:3491
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
#define TXD_DXT1
Definition: txd.c:31
av_cold void ff_texturedsp_init(TextureDSPContext *c)
Definition: texturedsp.c:637
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:378
#define TXD_DXT3
Definition: txd.c:32
int width
picture width / height.
Definition: avcodec.h:1741
uint8_t w
Definition: llviddspenc.c:38
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
Libavcodec external API header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:326
main external API structure.
Definition: avcodec.h:1568
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1963
int(* dxt1_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)
Definition: texturedsp.h:46
int coded_height
Definition: avcodec.h:1756
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
#define flags(name, subs,...)
Definition: cbs_av1.c:561
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:309
common internal api header.
#define stride
static int unsupported(AVCodecContext *avctx)
Definition: iff.c:1495
This structure stores compressed data.
Definition: avcodec.h:1457
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:984
for(j=16;j >0;--j)
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58