You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
5.2KB

  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. #include "libavutil/intreadwrite.h"
  24. #include "libavutil/imgutils.h"
  25. #include "bytestream.h"
  26. #include "avcodec.h"
  27. #include "internal.h"
  28. #include "texturedsp.h"
  29. #define TXD_DXT1 0x31545844
  30. #define TXD_DXT3 0x33545844
  31. static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
  32. AVPacket *avpkt) {
  33. GetByteContext gb;
  34. TextureDSPContext dxtc;
  35. AVFrame * const p = data;
  36. unsigned int version, w, h, d3d_format, depth, stride, flags;
  37. unsigned int y, v;
  38. uint8_t *ptr;
  39. uint32_t *pal;
  40. int i, j;
  41. int ret;
  42. ff_texturedsp_init(&dxtc);
  43. bytestream2_init(&gb, avpkt->data, avpkt->size);
  44. version = bytestream2_get_le32(&gb);
  45. bytestream2_skip(&gb, 72);
  46. d3d_format = bytestream2_get_le32(&gb);
  47. w = bytestream2_get_le16(&gb);
  48. h = bytestream2_get_le16(&gb);
  49. depth = bytestream2_get_byte(&gb);
  50. bytestream2_skip(&gb, 2);
  51. flags = bytestream2_get_byte(&gb);
  52. if (version < 8 || version > 9) {
  53. av_log(avctx, AV_LOG_ERROR, "texture data version %i is unsupported\n",
  54. version);
  55. return AVERROR_PATCHWELCOME;
  56. }
  57. if (depth == 8) {
  58. avctx->pix_fmt = AV_PIX_FMT_PAL8;
  59. } else if (depth == 16 || depth == 32) {
  60. avctx->pix_fmt = AV_PIX_FMT_RGBA;
  61. } else {
  62. av_log(avctx, AV_LOG_ERROR, "depth of %i is unsupported\n", depth);
  63. return AVERROR_PATCHWELCOME;
  64. }
  65. if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
  66. return ret;
  67. avctx->coded_width = FFALIGN(w, 4);
  68. avctx->coded_height = FFALIGN(h, 4);
  69. if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
  70. return ret;
  71. p->pict_type = AV_PICTURE_TYPE_I;
  72. ptr = p->data[0];
  73. stride = p->linesize[0];
  74. if (depth == 8) {
  75. pal = (uint32_t *) p->data[1];
  76. for (y = 0; y < 256; y++) {
  77. v = bytestream2_get_be32(&gb);
  78. pal[y] = (v >> 8) + (v << 24);
  79. }
  80. if (bytestream2_get_bytes_left(&gb) < w * h)
  81. return AVERROR_INVALIDDATA;
  82. bytestream2_skip(&gb, 4);
  83. for (y=0; y<h; y++) {
  84. bytestream2_get_buffer(&gb, ptr, w);
  85. ptr += stride;
  86. }
  87. } else if (depth == 16) {
  88. bytestream2_skip(&gb, 4);
  89. switch (d3d_format) {
  90. case 0:
  91. if (!(flags & 1))
  92. goto unsupported;
  93. case TXD_DXT1:
  94. if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 8)
  95. return AVERROR_INVALIDDATA;
  96. for (j = 0; j < avctx->height; j += 4) {
  97. for (i = 0; i < avctx->width; i += 4) {
  98. uint8_t *p = ptr + i * 4 + j * stride;
  99. int step = dxtc.dxt1_block(p, stride, gb.buffer);
  100. bytestream2_skip(&gb, step);
  101. }
  102. }
  103. break;
  104. case TXD_DXT3:
  105. if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 16)
  106. return AVERROR_INVALIDDATA;
  107. for (j = 0; j < avctx->height; j += 4) {
  108. for (i = 0; i < avctx->width; i += 4) {
  109. uint8_t *p = ptr + i * 4 + j * stride;
  110. int step = dxtc.dxt3_block(p, stride, gb.buffer);
  111. bytestream2_skip(&gb, step);
  112. }
  113. }
  114. break;
  115. default:
  116. goto unsupported;
  117. }
  118. } else if (depth == 32) {
  119. switch (d3d_format) {
  120. case 0x15:
  121. case 0x16:
  122. if (bytestream2_get_bytes_left(&gb) < h * w * 4)
  123. return AVERROR_INVALIDDATA;
  124. for (y=0; y<h; y++) {
  125. bytestream2_get_buffer(&gb, ptr, w * 4);
  126. ptr += stride;
  127. }
  128. break;
  129. default:
  130. goto unsupported;
  131. }
  132. }
  133. *got_frame = 1;
  134. return avpkt->size;
  135. unsupported:
  136. av_log(avctx, AV_LOG_ERROR, "unsupported d3d format (%08x)\n", d3d_format);
  137. return AVERROR_PATCHWELCOME;
  138. }
  139. AVCodec ff_txd_decoder = {
  140. .name = "txd",
  141. .long_name = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"),
  142. .type = AVMEDIA_TYPE_VIDEO,
  143. .id = AV_CODEC_ID_TXD,
  144. .decode = txd_decode_frame,
  145. .capabilities = AV_CODEC_CAP_DR1,
  146. };