Mercurial > libavcodec.hg
comparison txd.c @ 4934:feba7e1adac5 libavcodec
Renderware TXD decoder
author | ivo |
---|---|
date | Mon, 07 May 2007 13:29:02 +0000 |
parents | |
children | 470601203f44 |
comparison
equal
deleted
inserted
replaced
4933:ed67837533b0 | 4934:feba7e1adac5 |
---|---|
1 /* | |
2 * Renderware TeXture Dictionary (.txd) image decoder | |
3 * Copyright (c) 2007 Ivo van Poorten | |
4 * | |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
18 * License along with FFmpeg; if not, write to the Free Software | |
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 * | |
21 * See also: http://wiki.multimedia.cx/index.php?title=TXD | |
22 */ | |
23 | |
24 #include "avcodec.h" | |
25 #include "s3tc.h" | |
26 | |
27 typedef struct TXDContext { | |
28 AVFrame picture; | |
29 } TXDContext; | |
30 | |
31 static int txd_init(AVCodecContext *avctx) { | |
32 TXDContext *s = avctx->priv_data; | |
33 | |
34 avcodec_get_frame_defaults(&s->picture); | |
35 avctx->coded_frame = &s->picture; | |
36 s->picture.data[0] = NULL; | |
37 | |
38 return 0; | |
39 } | |
40 | |
41 static int txd_decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |
42 uint8_t *buf, int buf_size) { | |
43 TXDContext * const s = avctx->priv_data; | |
44 AVFrame *picture = data; | |
45 AVFrame * const p = &s->picture; | |
46 unsigned int version, w, h, d3d_format, depth, stride, mipmap_count, flags; | |
47 unsigned int y, v; | |
48 uint8_t *ptr, *cur = buf; | |
49 uint32_t *palette = (uint32_t *)(cur + 88), *pal; | |
50 | |
51 version = AV_RL32(cur); | |
52 d3d_format = AV_RL32(cur+76); | |
53 w = AV_RL16(cur+80); | |
54 h = AV_RL16(cur+82); | |
55 depth = AV_RL8 (cur+84); | |
56 mipmap_count = AV_RL8 (cur+85); | |
57 flags = AV_RL8 (cur+87); | |
58 cur += 92; | |
59 | |
60 if (version < 8 || version > 9) { | |
61 av_log(avctx, AV_LOG_ERROR, "texture data version %i is unsupported\n", | |
62 version); | |
63 return -1; | |
64 } | |
65 | |
66 if (depth == 8) { | |
67 avctx->pix_fmt = PIX_FMT_PAL8; | |
68 cur += 1024; | |
69 } else if (depth == 16 || depth == 32) | |
70 avctx->pix_fmt = PIX_FMT_RGB32; | |
71 else { | |
72 av_log(avctx, AV_LOG_ERROR, "depth of %i is unsupported\n", depth); | |
73 return -1; | |
74 } | |
75 | |
76 if (p->data[0]) | |
77 avctx->release_buffer(avctx, p); | |
78 | |
79 if (avcodec_check_dimensions(avctx, w, h)) | |
80 return -1; | |
81 if (w != avctx->width || h != avctx->height) | |
82 avcodec_set_dimensions(avctx, w, h); | |
83 if (avctx->get_buffer(avctx, p) < 0) { | |
84 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
85 return -1; | |
86 } | |
87 | |
88 p->pict_type = FF_I_TYPE; | |
89 | |
90 ptr = p->data[0]; | |
91 stride = p->linesize[0]; | |
92 | |
93 if (depth == 8) { | |
94 pal = (uint32_t *) p->data[1]; | |
95 for (y=0; y<256; y++) { | |
96 v = AV_RB32(palette+y); | |
97 pal[y] = (v>>8) + (v<<24); | |
98 } | |
99 for (y=0; y<h; y++) { | |
100 memcpy(ptr, cur, w); | |
101 ptr += stride; | |
102 cur += w; | |
103 } | |
104 } else if (depth == 16) { | |
105 switch (d3d_format) { | |
106 case 0: | |
107 if (!flags&1) goto unsupported; | |
108 case FF_S3TC_DXT1: | |
109 ff_decode_dxt1(cur, ptr, w, h, stride); | |
110 break; | |
111 case FF_S3TC_DXT3: | |
112 ff_decode_dxt3(cur, ptr, w, h, stride); | |
113 break; | |
114 default: | |
115 goto unsupported; | |
116 } | |
117 } else if (depth == 32) { | |
118 switch (d3d_format) { | |
119 case 0x15: | |
120 case 0x16: | |
121 for (y=0; y<h; y++) { | |
122 memcpy(ptr, cur, w*4); | |
123 ptr += stride; | |
124 cur += w*4; | |
125 } | |
126 break; | |
127 default: | |
128 goto unsupported; | |
129 } | |
130 } | |
131 | |
132 for (; mipmap_count > 1; mipmap_count--) | |
133 cur += AV_RL32(cur) + 4; | |
134 | |
135 *picture = s->picture; | |
136 *data_size = sizeof(AVPicture); | |
137 | |
138 return cur - buf; | |
139 | |
140 unsupported: | |
141 av_log(avctx, AV_LOG_ERROR, "unsupported d3d format (%08x)\n", d3d_format); | |
142 return -1; | |
143 } | |
144 | |
145 static int txd_end(AVCodecContext *avctx) { | |
146 TXDContext *s = avctx->priv_data; | |
147 | |
148 if (s->picture.data[0]) | |
149 avctx->release_buffer(avctx, &s->picture); | |
150 | |
151 return 0; | |
152 } | |
153 | |
154 AVCodec txd_decoder = { | |
155 "txd", | |
156 CODEC_TYPE_VIDEO, | |
157 CODEC_ID_TXD, | |
158 sizeof(TXDContext), | |
159 txd_init, | |
160 NULL, | |
161 txd_end, | |
162 txd_decode_frame, | |
163 0, | |
164 NULL | |
165 }; |