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  if (avpkt->size < 88)
47  return AVERROR_INVALIDDATA;
48 
49  ff_texturedsp_init(&dxtc);
50 
51  bytestream2_init(&gb, avpkt->data, avpkt->size);
52  version = bytestream2_get_le32(&gb);
53  bytestream2_skip(&gb, 72);
54  d3d_format = bytestream2_get_le32(&gb);
55  w = bytestream2_get_le16(&gb);
56  h = bytestream2_get_le16(&gb);
57  depth = bytestream2_get_byte(&gb);
58  bytestream2_skip(&gb, 2);
59  flags = bytestream2_get_byte(&gb);
60 
61  if (version < 8 || version > 9) {
62  avpriv_report_missing_feature(avctx, "Texture data version %u", version);
63  return AVERROR_PATCHWELCOME;
64  }
65 
66  if (depth == 8) {
67  avctx->pix_fmt = AV_PIX_FMT_PAL8;
68  } else if (depth == 16 || depth == 32) {
69  avctx->pix_fmt = AV_PIX_FMT_RGBA;
70  } else {
71  avpriv_report_missing_feature(avctx, "Color depth of %u", depth);
72  return AVERROR_PATCHWELCOME;
73  }
74 
75  if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
76  return ret;
77 
78  avctx->coded_width = FFALIGN(w, 4);
79  avctx->coded_height = FFALIGN(h, 4);
80 
81  if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
82  return ret;
83 
85 
86  ptr = p->data[0];
87  stride = p->linesize[0];
88 
89  if (depth == 8) {
90  pal = (uint32_t *) p->data[1];
91  for (y = 0; y < 256; y++) {
92  v = bytestream2_get_be32(&gb);
93  pal[y] = (v >> 8) + (v << 24);
94  }
95  if (bytestream2_get_bytes_left(&gb) < w * h)
96  return AVERROR_INVALIDDATA;
97  bytestream2_skip(&gb, 4);
98  for (y=0; y<h; y++) {
99  bytestream2_get_buffer(&gb, ptr, w);
100  ptr += stride;
101  }
102  } else if (depth == 16) {
103  bytestream2_skip(&gb, 4);
104  switch (d3d_format) {
105  case 0:
106  if (!(flags & 1))
107  goto unsupported;
108  case TXD_DXT1:
109  if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 8)
110  return AVERROR_INVALIDDATA;
111  for (j = 0; j < avctx->height; j += 4) {
112  for (i = 0; i < avctx->width; i += 4) {
113  uint8_t *p = ptr + i * 4 + j * stride;
114  int step = dxtc.dxt1_block(p, stride, gb.buffer);
115  bytestream2_skip(&gb, step);
116  }
117  }
118  break;
119  case TXD_DXT3:
120  if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 16)
121  return AVERROR_INVALIDDATA;
122  for (j = 0; j < avctx->height; j += 4) {
123  for (i = 0; i < avctx->width; i += 4) {
124  uint8_t *p = ptr + i * 4 + j * stride;
125  int step = dxtc.dxt3_block(p, stride, gb.buffer);
126  bytestream2_skip(&gb, step);
127  }
128  }
129  break;
130  default:
131  goto unsupported;
132  }
133  } else if (depth == 32) {
134  switch (d3d_format) {
135  case 0x15:
136  case 0x16:
137  if (bytestream2_get_bytes_left(&gb) < h * w * 4)
138  return AVERROR_INVALIDDATA;
139  for (y=0; y<h; y++) {
140  bytestream2_get_buffer(&gb, ptr, w * 4);
141  ptr += stride;
142  }
143  break;
144  default:
145  goto unsupported;
146  }
147  }
148 
149  *got_frame = 1;
150 
151  return avpkt->size;
152 
154  avpriv_report_missing_feature(avctx, "d3d format (%08x)", d3d_format);
155  return AVERROR_PATCHWELCOME;
156 }
157 
159  .name = "txd",
160  .long_name = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"),
161  .type = AVMEDIA_TYPE_VIDEO,
162  .id = AV_CODEC_ID_TXD,
163  .decode = txd_decode_frame,
164  .capabilities = AV_CODEC_CAP_DR1,
165 };
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
version
Definition: libkvazaar.c:317
This structure describes decoded (raw) audio or video data.
Definition: frame.h:308
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:714
misc image utilities
AVCodec ff_txd_decoder
Definition: txd.c:158
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:106
Texture block (4x4) module.
int size
Definition: packet.h:364
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:736
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:133
AVCodec.
Definition: codec.h:190
uint8_t
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:77
uint8_t * data
Definition: packet.h:363
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
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:154
DXGI_FORMAT d3d_format
static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: txd.c:34
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:153
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:263
const char * name
Name of the codec implementation.
Definition: codec.h:197
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:391
#define TXD_DXT3
Definition: txd.c:32
int width
picture width / height.
Definition: avcodec.h:699
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:339
main external API structure.
Definition: avcodec.h:526
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1872
int(* dxt1_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)
Definition: texturedsp.h:46
int coded_height
Definition: avcodec.h:714
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:560
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:322
common internal api header.
#define stride
static int unsupported(AVCodecContext *avctx)
Definition: iff.c:1516
This structure stores compressed data.
Definition: packet.h:340
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:50
for(j=16;j >0;--j)
int i
Definition: input.c:407
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