/libavcodec/msrledec.c

https://github.com/f0xx/ffmpeg-android · C · 265 lines · 213 code · 16 blank · 36 comment · 76 complexity · 518f8b3555f2633983dd847238c98ef7 MD5 · raw file

  1. /*
  2. * Microsoft RLE decoder
  3. * Copyright (C) 2008 Konstantin Shishkov
  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. * @file
  23. * MS RLE decoder based on decoder by Mike Melanson and my own for TSCC
  24. * For more information about the MS RLE format, visit:
  25. * http://www.multimedia.cx/msrle.txt
  26. */
  27. #include "libavutil/intreadwrite.h"
  28. #include "avcodec.h"
  29. #include "msrledec.h"
  30. static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic,
  31. GetByteContext *gb)
  32. {
  33. unsigned char rle_code;
  34. unsigned char extra_byte, odd_pixel;
  35. unsigned char stream_byte;
  36. unsigned int pixel_ptr = 0;
  37. int row_dec = pic->linesize[0];
  38. int row_ptr = (avctx->height - 1) * row_dec;
  39. int frame_size = row_dec * avctx->height;
  40. int i;
  41. while (row_ptr >= 0) {
  42. if (bytestream2_get_bytes_left(gb) <= 0) {
  43. av_log(avctx, AV_LOG_ERROR,
  44. "MS RLE: bytestream overrun, %d rows left\n",
  45. row_ptr);
  46. return AVERROR_INVALIDDATA;
  47. }
  48. rle_code = stream_byte = bytestream2_get_byteu(gb);
  49. if (rle_code == 0) {
  50. /* fetch the next byte to see how to handle escape code */
  51. stream_byte = bytestream2_get_byte(gb);
  52. if (stream_byte == 0) {
  53. /* line is done, goto the next one */
  54. row_ptr -= row_dec;
  55. pixel_ptr = 0;
  56. } else if (stream_byte == 1) {
  57. /* decode is done */
  58. return 0;
  59. } else if (stream_byte == 2) {
  60. /* reposition frame decode coordinates */
  61. stream_byte = bytestream2_get_byte(gb);
  62. pixel_ptr += stream_byte;
  63. stream_byte = bytestream2_get_byte(gb);
  64. row_ptr -= stream_byte * row_dec;
  65. } else {
  66. // copy pixels from encoded stream
  67. odd_pixel = stream_byte & 1;
  68. rle_code = (stream_byte + 1) / 2;
  69. extra_byte = rle_code & 0x01;
  70. if (row_ptr + pixel_ptr + stream_byte > frame_size ||
  71. bytestream2_get_bytes_left(gb) < rle_code) {
  72. av_log(avctx, AV_LOG_ERROR,
  73. "MS RLE: frame/stream ptr just went out of bounds (copy)\n");
  74. return AVERROR_INVALIDDATA;
  75. }
  76. for (i = 0; i < rle_code; i++) {
  77. if (pixel_ptr >= avctx->width)
  78. break;
  79. stream_byte = bytestream2_get_byteu(gb);
  80. pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
  81. pixel_ptr++;
  82. if (i + 1 == rle_code && odd_pixel)
  83. break;
  84. if (pixel_ptr >= avctx->width)
  85. break;
  86. pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
  87. pixel_ptr++;
  88. }
  89. // if the RLE code is odd, skip a byte in the stream
  90. if (extra_byte)
  91. bytestream2_skip(gb, 1);
  92. }
  93. } else {
  94. // decode a run of data
  95. if (row_ptr + pixel_ptr + stream_byte > frame_size) {
  96. av_log(avctx, AV_LOG_ERROR,
  97. "MS RLE: frame ptr just went out of bounds (run)\n");
  98. return AVERROR_INVALIDDATA;
  99. }
  100. stream_byte = bytestream2_get_byte(gb);
  101. for (i = 0; i < rle_code; i++) {
  102. if (pixel_ptr >= avctx->width)
  103. break;
  104. if ((i & 1) == 0)
  105. pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
  106. else
  107. pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
  108. pixel_ptr++;
  109. }
  110. }
  111. }
  112. /* one last sanity check on the way out */
  113. if (bytestream2_get_bytes_left(gb)) {
  114. av_log(avctx, AV_LOG_ERROR,
  115. "MS RLE: ended frame decode with %d bytes left over\n",
  116. bytestream2_get_bytes_left(gb));
  117. return AVERROR_INVALIDDATA;
  118. }
  119. return 0;
  120. }
  121. static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic,
  122. int depth, GetByteContext *gb)
  123. {
  124. uint8_t *output, *output_end;
  125. int p1, p2, line=avctx->height - 1, pos=0, i;
  126. uint16_t pix16;
  127. uint32_t pix32;
  128. unsigned int width= FFABS(pic->linesize[0]) / (depth >> 3);
  129. output = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
  130. output_end = pic->data[0] + avctx->height * pic->linesize[0];
  131. while (bytestream2_get_bytes_left(gb) > 0) {
  132. p1 = bytestream2_get_byteu(gb);
  133. if(p1 == 0) { //Escape code
  134. p2 = bytestream2_get_byte(gb);
  135. if(p2 == 0) { //End-of-line
  136. if (--line < 0) {
  137. if (bytestream2_get_be16(gb) == 1) { // end-of-picture
  138. return 0;
  139. } else {
  140. av_log(avctx, AV_LOG_ERROR,
  141. "Next line is beyond picture bounds (%d bytes left)\n",
  142. bytestream2_get_bytes_left(gb));
  143. return AVERROR_INVALIDDATA;
  144. }
  145. }
  146. output = pic->data[0] + line * pic->linesize[0];
  147. pos = 0;
  148. continue;
  149. } else if(p2 == 1) { //End-of-picture
  150. return 0;
  151. } else if(p2 == 2) { //Skip
  152. p1 = bytestream2_get_byte(gb);
  153. p2 = bytestream2_get_byte(gb);
  154. line -= p2;
  155. pos += p1;
  156. if (line < 0 || pos >= width){
  157. av_log(avctx, AV_LOG_ERROR, "Skip beyond picture bounds\n");
  158. return -1;
  159. }
  160. output = pic->data[0] + line * pic->linesize[0] + pos * (depth >> 3);
  161. continue;
  162. }
  163. // Copy data
  164. if ((pic->linesize[0] > 0 && output + p2 * (depth >> 3) > output_end) ||
  165. (pic->linesize[0] < 0 && output + p2 * (depth >> 3) < output_end)) {
  166. bytestream2_skip(gb, 2 * (depth >> 3));
  167. continue;
  168. } else if (bytestream2_get_bytes_left(gb) < p2 * (depth >> 3)) {
  169. av_log(avctx, AV_LOG_ERROR, "bytestream overrun\n");
  170. return AVERROR_INVALIDDATA;
  171. }
  172. if ((depth == 8) || (depth == 24)) {
  173. for(i = 0; i < p2 * (depth >> 3); i++) {
  174. *output++ = bytestream2_get_byteu(gb);
  175. }
  176. // RLE8 copy is actually padded - and runs are not!
  177. if(depth == 8 && (p2 & 1)) {
  178. bytestream2_skip(gb, 1);
  179. }
  180. } else if (depth == 16) {
  181. for(i = 0; i < p2; i++) {
  182. *(uint16_t*)output = bytestream2_get_le16u(gb);
  183. output += 2;
  184. }
  185. } else if (depth == 32) {
  186. for(i = 0; i < p2; i++) {
  187. *(uint32_t*)output = bytestream2_get_le32u(gb);
  188. output += 4;
  189. }
  190. }
  191. pos += p2;
  192. } else { //run of pixels
  193. uint8_t pix[3]; //original pixel
  194. if ((pic->linesize[0] > 0 && output + p1 * (depth >> 3) > output_end) ||
  195. (pic->linesize[0] < 0 && output + p1 * (depth >> 3) < output_end))
  196. continue;
  197. switch(depth){
  198. case 8:
  199. pix[0] = bytestream2_get_byte(gb);
  200. for(i = 0; i < p1; i++)
  201. *output++ = pix[0];
  202. break;
  203. case 16:
  204. pix16 = bytestream2_get_le16(gb);
  205. for(i = 0; i < p1; i++) {
  206. *(uint16_t*)output = pix16;
  207. output += 2;
  208. }
  209. break;
  210. case 24:
  211. pix[0] = bytestream2_get_byte(gb);
  212. pix[1] = bytestream2_get_byte(gb);
  213. pix[2] = bytestream2_get_byte(gb);
  214. for(i = 0; i < p1; i++) {
  215. *output++ = pix[0];
  216. *output++ = pix[1];
  217. *output++ = pix[2];
  218. }
  219. break;
  220. case 32:
  221. pix32 = bytestream2_get_le32(gb);
  222. for(i = 0; i < p1; i++) {
  223. *(uint32_t*)output = pix32;
  224. output += 4;
  225. }
  226. break;
  227. }
  228. pos += p1;
  229. }
  230. }
  231. av_log(avctx, AV_LOG_WARNING, "MS RLE warning: no end-of-picture code\n");
  232. return 0;
  233. }
  234. int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic,
  235. int depth, GetByteContext *gb)
  236. {
  237. switch(depth){
  238. case 4:
  239. return msrle_decode_pal4(avctx, pic, gb);
  240. case 8:
  241. case 16:
  242. case 24:
  243. case 32:
  244. return msrle_decode_8_16_24_32(avctx, pic, depth, gb);
  245. default:
  246. av_log(avctx, AV_LOG_ERROR, "Unknown depth %d\n", depth);
  247. return -1;
  248. }
  249. }