Libav 0.7.1
|
00001 /* 00002 * Renderware TeXture Dictionary (.txd) image decoder 00003 * Copyright (c) 2007 Ivo van Poorten 00004 * 00005 * See also: http://wiki.multimedia.cx/index.php?title=TXD 00006 * 00007 * This file is part of Libav. 00008 * 00009 * Libav is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 * Libav is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with Libav; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 */ 00023 00024 #include "libavutil/intreadwrite.h" 00025 #include "libavutil/imgutils.h" 00026 #include "avcodec.h" 00027 #include "s3tc.h" 00028 00029 typedef struct TXDContext { 00030 AVFrame picture; 00031 } TXDContext; 00032 00033 static av_cold int txd_init(AVCodecContext *avctx) { 00034 TXDContext *s = avctx->priv_data; 00035 00036 avcodec_get_frame_defaults(&s->picture); 00037 avctx->coded_frame = &s->picture; 00038 00039 return 0; 00040 } 00041 00042 static int txd_decode_frame(AVCodecContext *avctx, void *data, int *data_size, 00043 AVPacket *avpkt) { 00044 const uint8_t *buf = avpkt->data; 00045 TXDContext * const s = avctx->priv_data; 00046 AVFrame *picture = data; 00047 AVFrame * const p = &s->picture; 00048 unsigned int version, w, h, d3d_format, depth, stride, mipmap_count, flags; 00049 unsigned int y, v; 00050 uint8_t *ptr; 00051 const uint8_t *cur = buf; 00052 const uint32_t *palette = (const uint32_t *)(cur + 88); 00053 uint32_t *pal; 00054 00055 version = AV_RL32(cur); 00056 d3d_format = AV_RL32(cur+76); 00057 w = AV_RL16(cur+80); 00058 h = AV_RL16(cur+82); 00059 depth = AV_RL8 (cur+84); 00060 mipmap_count = AV_RL8 (cur+85); 00061 flags = AV_RL8 (cur+87); 00062 cur += 92; 00063 00064 if (version < 8 || version > 9) { 00065 av_log(avctx, AV_LOG_ERROR, "texture data version %i is unsupported\n", 00066 version); 00067 return -1; 00068 } 00069 00070 if (depth == 8) { 00071 avctx->pix_fmt = PIX_FMT_PAL8; 00072 cur += 1024; 00073 } else if (depth == 16 || depth == 32) 00074 avctx->pix_fmt = PIX_FMT_RGB32; 00075 else { 00076 av_log(avctx, AV_LOG_ERROR, "depth of %i is unsupported\n", depth); 00077 return -1; 00078 } 00079 00080 if (p->data[0]) 00081 avctx->release_buffer(avctx, p); 00082 00083 if (av_image_check_size(w, h, 0, avctx)) 00084 return -1; 00085 if (w != avctx->width || h != avctx->height) 00086 avcodec_set_dimensions(avctx, w, h); 00087 if (avctx->get_buffer(avctx, p) < 0) { 00088 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 00089 return -1; 00090 } 00091 00092 p->pict_type = AV_PICTURE_TYPE_I; 00093 00094 ptr = p->data[0]; 00095 stride = p->linesize[0]; 00096 00097 if (depth == 8) { 00098 pal = (uint32_t *) p->data[1]; 00099 for (y=0; y<256; y++) { 00100 v = AV_RB32(palette+y); 00101 pal[y] = (v>>8) + (v<<24); 00102 } 00103 for (y=0; y<h; y++) { 00104 memcpy(ptr, cur, w); 00105 ptr += stride; 00106 cur += w; 00107 } 00108 } else if (depth == 16) { 00109 switch (d3d_format) { 00110 case 0: 00111 if (!flags&1) goto unsupported; 00112 case FF_S3TC_DXT1: 00113 ff_decode_dxt1(cur, ptr, w, h, stride); 00114 break; 00115 case FF_S3TC_DXT3: 00116 ff_decode_dxt3(cur, ptr, w, h, stride); 00117 break; 00118 default: 00119 goto unsupported; 00120 } 00121 } else if (depth == 32) { 00122 switch (d3d_format) { 00123 case 0x15: 00124 case 0x16: 00125 for (y=0; y<h; y++) { 00126 memcpy(ptr, cur, w*4); 00127 ptr += stride; 00128 cur += w*4; 00129 } 00130 break; 00131 default: 00132 goto unsupported; 00133 } 00134 } 00135 00136 for (; mipmap_count > 1; mipmap_count--) 00137 cur += AV_RL32(cur) + 4; 00138 00139 *picture = s->picture; 00140 *data_size = sizeof(AVPicture); 00141 00142 return cur - buf; 00143 00144 unsupported: 00145 av_log(avctx, AV_LOG_ERROR, "unsupported d3d format (%08x)\n", d3d_format); 00146 return -1; 00147 } 00148 00149 static av_cold int txd_end(AVCodecContext *avctx) { 00150 TXDContext *s = avctx->priv_data; 00151 00152 if (s->picture.data[0]) 00153 avctx->release_buffer(avctx, &s->picture); 00154 00155 return 0; 00156 } 00157 00158 AVCodec ff_txd_decoder = { 00159 "txd", 00160 AVMEDIA_TYPE_VIDEO, 00161 CODEC_ID_TXD, 00162 sizeof(TXDContext), 00163 txd_init, 00164 NULL, 00165 txd_end, 00166 txd_decode_frame, 00167 CODEC_CAP_DR1, 00168 NULL, 00169 .long_name = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"), 00170 };