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.

220 lines
6.3KB

  1. /*
  2. * Micrsoft RLE Video Decoder
  3. * Copyright (C) 2003 the ffmpeg project
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. /**
  20. * @file msrle.c
  21. * MS RLE Video Decoder by Mike Melanson (melanson@pcisys.net)
  22. * For more information about the MS RLE format, visit:
  23. * http://www.pcisys.net/~melanson/codecs/
  24. *
  25. * The MS RLE decoder outputs PAL8 colorspace data.
  26. *
  27. * Note that this decoder expects the palette colors from the end of the
  28. * BITMAPINFO header passed through extradata.
  29. */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <unistd.h>
  34. #include "common.h"
  35. #include "avcodec.h"
  36. #include "dsputil.h"
  37. typedef struct MsrleContext {
  38. AVCodecContext *avctx;
  39. AVFrame frame;
  40. AVFrame prev_frame;
  41. unsigned char *buf;
  42. int size;
  43. unsigned int palette[256];
  44. } MsrleContext;
  45. #define FETCH_NEXT_STREAM_BYTE() \
  46. if (stream_ptr >= s->size) \
  47. { \
  48. printf(" MS RLE: stream ptr just went out of bounds (1)\n"); \
  49. return; \
  50. } \
  51. stream_byte = s->buf[stream_ptr++];
  52. static void msrle_decode_pal8(MsrleContext *s)
  53. {
  54. int stream_ptr = 0;
  55. unsigned char rle_code;
  56. unsigned char extra_byte;
  57. unsigned char stream_byte;
  58. int pixel_ptr = 0;
  59. int row_dec = s->frame.linesize[0];
  60. int row_ptr = (s->avctx->height - 1) * row_dec;
  61. int frame_size = row_dec * s->avctx->height;
  62. while (row_ptr >= 0) {
  63. FETCH_NEXT_STREAM_BYTE();
  64. rle_code = stream_byte;
  65. if (rle_code == 0) {
  66. /* fetch the next byte to see how to handle escape code */
  67. FETCH_NEXT_STREAM_BYTE();
  68. if (stream_byte == 0) {
  69. /* line is done, goto the next one */
  70. row_ptr -= row_dec;
  71. pixel_ptr = 0;
  72. } else if (stream_byte == 1) {
  73. /* decode is done */
  74. return;
  75. } else if (stream_byte == 2) {
  76. /* reposition frame decode coordinates */
  77. FETCH_NEXT_STREAM_BYTE();
  78. pixel_ptr += stream_byte;
  79. FETCH_NEXT_STREAM_BYTE();
  80. row_ptr -= stream_byte * row_dec;
  81. } else {
  82. /* copy pixels from encoded stream */
  83. if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
  84. (row_ptr < 0)) {
  85. printf(" MS RLE: frame ptr just went out of bounds (1)\n");
  86. return;
  87. }
  88. rle_code = stream_byte;
  89. extra_byte = stream_byte & 0x01;
  90. if (stream_ptr + rle_code + extra_byte > s->size) {
  91. printf(" MS RLE: stream ptr just went out of bounds (2)\n");
  92. return;
  93. }
  94. while (rle_code--) {
  95. FETCH_NEXT_STREAM_BYTE();
  96. s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
  97. pixel_ptr++;
  98. }
  99. /* if the RLE code is odd, skip a byte in the stream */
  100. if (extra_byte)
  101. stream_ptr++;
  102. }
  103. } else {
  104. /* decode a run of data */
  105. if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
  106. (row_ptr < 0)) {
  107. printf(" MS RLE: frame ptr just went out of bounds (2)\n");
  108. return;
  109. }
  110. FETCH_NEXT_STREAM_BYTE();
  111. while(rle_code--) {
  112. s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
  113. pixel_ptr++;
  114. }
  115. }
  116. }
  117. /* make the palette available */
  118. memcpy(s->frame.data[1], s->palette, 256 * 4);
  119. /* one last sanity check on the way out */
  120. if (stream_ptr < s->size)
  121. printf(" MS RLE: ended frame decode with bytes left over (%d < %d)\n",
  122. stream_ptr, s->size);
  123. }
  124. static int msrle_decode_init(AVCodecContext *avctx)
  125. {
  126. MsrleContext *s = (MsrleContext *)avctx->priv_data;
  127. int i, j;
  128. unsigned char *palette;
  129. s->avctx = avctx;
  130. avctx->pix_fmt = PIX_FMT_PAL8;
  131. avctx->has_b_frames = 0;
  132. s->frame.data[0] = s->prev_frame.data[0] = NULL;
  133. /* convert palette */
  134. palette = (unsigned char *)s->avctx->extradata;
  135. memset (s->palette, 0, 256 * 4);
  136. for (i = 0, j = 0; i < s->avctx->extradata_size / 4; i++, j += 4)
  137. s->palette[i] =
  138. (palette[j + 2] << 16) |
  139. (palette[j + 1] << 8) |
  140. (palette[j + 0] << 0);
  141. return 0;
  142. }
  143. static int msrle_decode_frame(AVCodecContext *avctx,
  144. void *data, int *data_size,
  145. uint8_t *buf, int buf_size)
  146. {
  147. MsrleContext *s = (MsrleContext *)avctx->priv_data;
  148. s->buf = buf;
  149. s->size = buf_size;
  150. if (avctx->get_buffer(avctx, &s->frame)) {
  151. printf (" MS RLE: get_buffer() failed\n");
  152. return -1;
  153. }
  154. /* grossly inefficient, but...oh well */
  155. memcpy(s->frame.data[0], s->prev_frame.data[0],
  156. s->frame.linesize[0] * s->avctx->height);
  157. msrle_decode_pal8(s);
  158. if (s->frame.data[0])
  159. avctx->release_buffer(avctx, &s->frame);
  160. /* shuffle frames */
  161. s->prev_frame = s->frame;
  162. *data_size = sizeof(AVFrame);
  163. *(AVFrame*)data = s->frame;
  164. /* report that the buffer was completely consumed */
  165. return buf_size;
  166. }
  167. static int msrle_decode_end(AVCodecContext *avctx)
  168. {
  169. MsrleContext *s = (MsrleContext *)avctx->priv_data;
  170. /* release the last frame */
  171. if (s->prev_frame.data[0])
  172. avctx->release_buffer(avctx, &s->prev_frame);
  173. return 0;
  174. }
  175. AVCodec msrle_decoder = {
  176. "msrle",
  177. CODEC_TYPE_VIDEO,
  178. CODEC_ID_MSRLE,
  179. sizeof(MsrleContext),
  180. msrle_decode_init,
  181. NULL,
  182. msrle_decode_end,
  183. msrle_decode_frame,
  184. CODEC_CAP_DR1,
  185. };