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.

163 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. avpriv_report_missing_feature(avctx, "Texture data version %u", version);
  54. return AVERROR_PATCHWELCOME;
  55. }
  56. if (depth == 8) {
  57. avctx->pix_fmt = AV_PIX_FMT_PAL8;
  58. } else if (depth == 16 || depth == 32) {
  59. avctx->pix_fmt = AV_PIX_FMT_RGBA;
  60. } else {
  61. avpriv_report_missing_feature(avctx, "Color depth of %u", depth);
  62. return AVERROR_PATCHWELCOME;
  63. }
  64. if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
  65. return ret;
  66. avctx->coded_width = FFALIGN(w, 4);
  67. avctx->coded_height = FFALIGN(h, 4);
  68. if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
  69. return ret;
  70. p->pict_type = AV_PICTURE_TYPE_I;
  71. ptr = p->data[0];
  72. stride = p->linesize[0];
  73. if (depth == 8) {
  74. pal = (uint32_t *) p->data[1];
  75. for (y = 0; y < 256; y++) {
  76. v = bytestream2_get_be32(&gb);
  77. pal[y] = (v >> 8) + (v << 24);
  78. }
  79. if (bytestream2_get_bytes_left(&gb) < w * h)
  80. return AVERROR_INVALIDDATA;
  81. bytestream2_skip(&gb, 4);
  82. for (y=0; y<h; y++) {
  83. bytestream2_get_buffer(&gb, ptr, w);
  84. ptr += stride;
  85. }
  86. } else if (depth == 16) {
  87. bytestream2_skip(&gb, 4);
  88. switch (d3d_format) {
  89. case 0:
  90. if (!(flags & 1))
  91. goto unsupported;
  92. case TXD_DXT1:
  93. if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 8)
  94. return AVERROR_INVALIDDATA;
  95. for (j = 0; j < avctx->height; j += 4) {
  96. for (i = 0; i < avctx->width; i += 4) {
  97. uint8_t *p = ptr + i * 4 + j * stride;
  98. int step = dxtc.dxt1_block(p, stride, gb.buffer);
  99. bytestream2_skip(&gb, step);
  100. }
  101. }
  102. break;
  103. case TXD_DXT3:
  104. if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 16)
  105. return AVERROR_INVALIDDATA;
  106. for (j = 0; j < avctx->height; j += 4) {
  107. for (i = 0; i < avctx->width; i += 4) {
  108. uint8_t *p = ptr + i * 4 + j * stride;
  109. int step = dxtc.dxt3_block(p, stride, gb.buffer);
  110. bytestream2_skip(&gb, step);
  111. }
  112. }
  113. break;
  114. default:
  115. goto unsupported;
  116. }
  117. } else if (depth == 32) {
  118. switch (d3d_format) {
  119. case 0x15:
  120. case 0x16:
  121. if (bytestream2_get_bytes_left(&gb) < h * w * 4)
  122. return AVERROR_INVALIDDATA;
  123. for (y=0; y<h; y++) {
  124. bytestream2_get_buffer(&gb, ptr, w * 4);
  125. ptr += stride;
  126. }
  127. break;
  128. default:
  129. goto unsupported;
  130. }
  131. }
  132. *got_frame = 1;
  133. return avpkt->size;
  134. unsupported:
  135. avpriv_report_missing_feature(avctx, "d3d format (%08x)", d3d_format);
  136. return AVERROR_PATCHWELCOME;
  137. }
  138. AVCodec ff_txd_decoder = {
  139. .name = "txd",
  140. .long_name = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"),
  141. .type = AVMEDIA_TYPE_VIDEO,
  142. .id = AV_CODEC_ID_TXD,
  143. .decode = txd_decode_frame,
  144. .capabilities = AV_CODEC_CAP_DR1,
  145. };