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.

246 lines
7.0KB

  1. /*
  2. * BRender PIX (.pix) image decoder
  3. * Copyright (c) 2012 Aleksi Nurmi
  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. /*
  22. * Tested against samples from I-War / Independence War and Defiance.
  23. * If the PIX file does not contain a palette, the
  24. * palette_has_changed property of the AVFrame is set to 0.
  25. */
  26. #include "libavutil/imgutils.h"
  27. #include "avcodec.h"
  28. #include "bytestream.h"
  29. #include "internal.h"
  30. typedef struct BRPixContext {
  31. AVFrame frame;
  32. } BRPixContext;
  33. typedef struct BRPixHeader {
  34. int format;
  35. unsigned int width, height;
  36. } BRPixHeader;
  37. static av_cold int brpix_init(AVCodecContext *avctx)
  38. {
  39. BRPixContext *s = avctx->priv_data;
  40. avcodec_get_frame_defaults(&s->frame);
  41. avctx->coded_frame = &s->frame;
  42. return 0;
  43. }
  44. static int brpix_decode_header(BRPixHeader *out, GetByteContext *pgb)
  45. {
  46. unsigned int header_len = bytestream2_get_be32(pgb);
  47. out->format = bytestream2_get_byte(pgb);
  48. bytestream2_skip(pgb, 2);
  49. out->width = bytestream2_get_be16(pgb);
  50. out->height = bytestream2_get_be16(pgb);
  51. // the header is at least 11 bytes long; we read the first 7
  52. if (header_len < 11) {
  53. return 0;
  54. }
  55. // skip the rest of the header
  56. bytestream2_skip(pgb, header_len-7);
  57. return 1;
  58. }
  59. static int brpix_decode_frame(AVCodecContext *avctx,
  60. void *data, int *got_frame,
  61. AVPacket *avpkt)
  62. {
  63. BRPixContext *s = avctx->priv_data;
  64. AVFrame *frame_out = data;
  65. int ret;
  66. GetByteContext gb;
  67. unsigned int bytes_pp;
  68. unsigned int magic[4];
  69. unsigned int chunk_type;
  70. unsigned int data_len;
  71. BRPixHeader hdr;
  72. bytestream2_init(&gb, avpkt->data, avpkt->size);
  73. magic[0] = bytestream2_get_be32(&gb);
  74. magic[1] = bytestream2_get_be32(&gb);
  75. magic[2] = bytestream2_get_be32(&gb);
  76. magic[3] = bytestream2_get_be32(&gb);
  77. if (magic[0] != 0x12 ||
  78. magic[1] != 0x8 ||
  79. magic[2] != 0x2 ||
  80. magic[3] != 0x2) {
  81. av_log(avctx, AV_LOG_ERROR, "Not a BRender PIX file\n");
  82. return AVERROR_INVALIDDATA;
  83. }
  84. chunk_type = bytestream2_get_be32(&gb);
  85. if (chunk_type != 0x3 && chunk_type != 0x3d) {
  86. av_log(avctx, AV_LOG_ERROR, "Invalid chunk type %d\n", chunk_type);
  87. return AVERROR_INVALIDDATA;
  88. }
  89. ret = brpix_decode_header(&hdr, &gb);
  90. if (!ret) {
  91. av_log(avctx, AV_LOG_ERROR, "Invalid header length\n");
  92. return AVERROR_INVALIDDATA;
  93. }
  94. switch (hdr.format) {
  95. case 3:
  96. avctx->pix_fmt = AV_PIX_FMT_PAL8;
  97. bytes_pp = 1;
  98. break;
  99. case 4:
  100. avctx->pix_fmt = AV_PIX_FMT_RGB555BE;
  101. bytes_pp = 2;
  102. break;
  103. case 5:
  104. avctx->pix_fmt = AV_PIX_FMT_RGB565BE;
  105. bytes_pp = 2;
  106. break;
  107. case 6:
  108. avctx->pix_fmt = AV_PIX_FMT_RGB24;
  109. bytes_pp = 3;
  110. break;
  111. case 7:
  112. avctx->pix_fmt = AV_PIX_FMT_0RGB;
  113. bytes_pp = 4;
  114. break;
  115. case 18:
  116. avctx->pix_fmt = AV_PIX_FMT_GRAY8A;
  117. bytes_pp = 2;
  118. break;
  119. default:
  120. av_log(avctx, AV_LOG_ERROR, "Format %d is not supported\n",
  121. hdr.format);
  122. return AVERROR_PATCHWELCOME;
  123. }
  124. if (s->frame.data[0])
  125. avctx->release_buffer(avctx, &s->frame);
  126. if (av_image_check_size(hdr.width, hdr.height, 0, avctx) < 0)
  127. return AVERROR_INVALIDDATA;
  128. if (hdr.width != avctx->width || hdr.height != avctx->height)
  129. avcodec_set_dimensions(avctx, hdr.width, hdr.height);
  130. if ((ret = ff_get_buffer(avctx, &s->frame)) < 0) {
  131. av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
  132. return ret;
  133. }
  134. chunk_type = bytestream2_get_be32(&gb);
  135. if (avctx->pix_fmt == AV_PIX_FMT_PAL8 &&
  136. (chunk_type == 0x3 || chunk_type == 0x3d)) {
  137. BRPixHeader palhdr;
  138. uint32_t *pal_out = (uint32_t *)s->frame.data[1];
  139. int i;
  140. ret = brpix_decode_header(&palhdr, &gb);
  141. if (!ret) {
  142. av_log(avctx, AV_LOG_ERROR, "Invalid palette header length\n");
  143. return AVERROR_INVALIDDATA;
  144. }
  145. if (palhdr.format != 7) {
  146. av_log(avctx, AV_LOG_ERROR, "Palette is not in 0RGB format\n");
  147. return AVERROR_INVALIDDATA;
  148. }
  149. chunk_type = bytestream2_get_be32(&gb);
  150. data_len = bytestream2_get_be32(&gb);
  151. bytestream2_skip(&gb, 8);
  152. if (chunk_type != 0x21 || data_len != 1032 ||
  153. bytestream2_get_bytes_left(&gb) < 1032) {
  154. av_log(avctx, AV_LOG_ERROR, "Invalid palette data\n");
  155. return AVERROR_INVALIDDATA;
  156. }
  157. // convert 0RGB to machine endian format (ARGB32)
  158. for (i = 0; i < 256; ++i) {
  159. bytestream2_skipu(&gb, 1);
  160. *pal_out++ = (0xFFU << 24) | bytestream2_get_be24u(&gb);
  161. }
  162. bytestream2_skip(&gb, 8);
  163. s->frame.palette_has_changed = 1;
  164. chunk_type = bytestream2_get_be32(&gb);
  165. }
  166. data_len = bytestream2_get_be32(&gb);
  167. bytestream2_skip(&gb, 8);
  168. // read the image data to the buffer
  169. {
  170. unsigned int bytes_per_scanline = bytes_pp * hdr.width;
  171. unsigned int bytes_left = bytestream2_get_bytes_left(&gb);
  172. if (chunk_type != 0x21 || data_len != bytes_left ||
  173. bytes_left / bytes_per_scanline < hdr.height)
  174. {
  175. av_log(avctx, AV_LOG_ERROR, "Invalid image data\n");
  176. return AVERROR_INVALIDDATA;
  177. }
  178. av_image_copy_plane(s->frame.data[0], s->frame.linesize[0],
  179. avpkt->data + bytestream2_tell(&gb),
  180. bytes_per_scanline,
  181. bytes_per_scanline, hdr.height);
  182. }
  183. *frame_out = s->frame;
  184. *got_frame = 1;
  185. return avpkt->size;
  186. }
  187. static av_cold int brpix_end(AVCodecContext *avctx)
  188. {
  189. BRPixContext *s = avctx->priv_data;
  190. if(s->frame.data[0])
  191. avctx->release_buffer(avctx, &s->frame);
  192. return 0;
  193. }
  194. AVCodec ff_brender_pix_decoder = {
  195. .name = "brender_pix",
  196. .type = AVMEDIA_TYPE_VIDEO,
  197. .id = AV_CODEC_ID_BRENDER_PIX,
  198. .priv_data_size = sizeof(BRPixContext),
  199. .init = brpix_init,
  200. .close = brpix_end,
  201. .decode = brpix_decode_frame,
  202. .capabilities = CODEC_CAP_DR1,
  203. .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"),
  204. };