avi_rle_decoder.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #include "avi_rle_decoder.h"
  2. #include "../Winamp/wa_ipc.h"
  3. #include <limits.h>
  4. #include "rle.h"
  5. #include <intsafe.h>
  6. AVIRLE *AVIRLE::CreateDecoder(nsavi::video_format *stream_format)
  7. {
  8. if (stream_format->bits_per_pixel == 4)
  9. return 0;
  10. size_t bytes_per_pixel = stream_format->bits_per_pixel / 8U;
  11. if (bytes_per_pixel > 4)
  12. return 0;
  13. size_t image_size=0;
  14. if (SizeTMult(stream_format->width, stream_format->height, &image_size) != S_OK || SizeTMult(image_size, bytes_per_pixel, &image_size) != S_OK)
  15. return 0;
  16. void *video_frame = (uint8_t *)malloc(image_size);
  17. if (!video_frame)
  18. return 0;
  19. AVIRLE *decoder = new AVIRLE(video_frame, stream_format, image_size);
  20. if (!decoder)
  21. {
  22. free(video_frame);
  23. return 0;
  24. }
  25. return decoder;
  26. }
  27. AVIRLE::AVIRLE(void *video_frame, nsavi::video_format *stream_format, size_t video_frame_size) : stream_format(stream_format), video_frame((uint8_t *)video_frame), video_frame_size(video_frame_size)
  28. {
  29. memset(palette, 0, sizeof(palette));
  30. memcpy(palette, (uint8_t *)stream_format + 44, 1024);
  31. video_outputted=false;
  32. palette_retrieved=false;
  33. }
  34. int AVIRLE::GetPalette(RGB32 **palette)
  35. {
  36. if (!palette_retrieved)
  37. {
  38. *palette = (RGB32 *)(this->palette);
  39. palette_retrieved=true;
  40. return AVI_SUCCESS;
  41. }
  42. else
  43. {
  44. return AVI_FAILURE;
  45. }
  46. }
  47. int AVIRLE::GetOutputProperties(int *x, int *y, int *color_format, double *aspect_ratio, int *flip)
  48. {
  49. if (stream_format)
  50. {
  51. *x = stream_format->width;
  52. *y = stream_format->height;
  53. *flip = 1;
  54. switch(stream_format->bits_per_pixel)
  55. {
  56. case 4:
  57. *color_format = '8BGR';
  58. break;
  59. case 8:
  60. *color_format = '8BGR';
  61. break;
  62. case 16:
  63. *color_format = '555R';
  64. break;
  65. case 24:
  66. *color_format = '42GR';
  67. break;
  68. case 32:
  69. *color_format = '23GR';
  70. break;
  71. default:
  72. return AVI_FAILURE;
  73. }
  74. return AVI_SUCCESS;
  75. }
  76. return AVI_FAILURE;
  77. }
  78. static bool CheckOverflow(size_t total_size, int current_position, int read_size)
  79. {
  80. if (read_size > (int)total_size) // check separate to avoid overflow
  81. return true;
  82. if (((int)total_size - read_size) < current_position)
  83. return true;
  84. return false;
  85. }
  86. int AVIRLE::DecodeChunk(uint16_t type, const void *inputBuffer, size_t inputBufferBytes)
  87. {
  88. if (stream_format)
  89. {
  90. uint32_t bytes_per_pixel = stream_format->bits_per_pixel / 8;
  91. const uint8_t * const rle = (const uint8_t *)inputBuffer;
  92. if (bytes_per_pixel == 2)
  93. {
  94. RLE16(rle, inputBufferBytes, (uint16_t *)video_frame, video_frame_size, stream_format->width);
  95. }
  96. else if (bytes_per_pixel == 1)
  97. {
  98. RLE8(rle, inputBufferBytes, (uint8_t *)video_frame, video_frame_size, stream_format->width);
  99. }
  100. else
  101. {
  102. int input = 0;
  103. int output = 0;
  104. int next_line = output + bytes_per_pixel*stream_format->width;
  105. while (input < (int)inputBufferBytes && output < (int)video_frame_size)
  106. {
  107. if (CheckOverflow(inputBufferBytes, input, 2)) // we always read at least two bytes
  108. break;
  109. uint8_t b0 = rle[input++];
  110. if (b0)
  111. {
  112. if (CheckOverflow(inputBufferBytes, input, bytes_per_pixel))
  113. break;
  114. if (CheckOverflow(video_frame_size, output, b0*bytes_per_pixel))
  115. break;
  116. uint8_t pixel[4];
  117. memcpy(pixel, &rle[input], bytes_per_pixel);
  118. input += bytes_per_pixel;
  119. while (b0--)
  120. {
  121. memcpy(&video_frame[output], &pixel, bytes_per_pixel);
  122. output+=bytes_per_pixel;
  123. }
  124. }
  125. else
  126. {
  127. uint8_t b1 = rle[input++];
  128. if (b1 == 0)
  129. {
  130. output = next_line;
  131. next_line = output + bytes_per_pixel*stream_format->width;
  132. }
  133. else if (b1 == 1)
  134. {
  135. break;
  136. }
  137. else if (b1 == 2)
  138. {
  139. if (CheckOverflow(inputBufferBytes, input, 2))
  140. break;
  141. uint8_t p1 = rle[input++];
  142. uint8_t p2 = rle[input++];
  143. output += bytes_per_pixel*p1;
  144. output += bytes_per_pixel*p2*stream_format->width;
  145. next_line += bytes_per_pixel*p2*stream_format->width;
  146. }
  147. else
  148. {
  149. if (CheckOverflow(inputBufferBytes, input, b1*bytes_per_pixel))
  150. break;
  151. if (CheckOverflow(video_frame_size, output, b1*bytes_per_pixel))
  152. break;
  153. memcpy(&video_frame[output], &rle[input], b1*bytes_per_pixel);
  154. input += b1*bytes_per_pixel;
  155. output += b1*bytes_per_pixel;
  156. if (bytes_per_pixel == 1 && (b1 & 1))
  157. input++;
  158. }
  159. }
  160. }
  161. }
  162. video_outputted=false;
  163. return AVI_SUCCESS;
  164. }
  165. return AVI_FAILURE;
  166. }
  167. void AVIRLE::Flush()
  168. {
  169. }
  170. int AVIRLE::GetPicture(void **data, void **decoder_data)
  171. {
  172. if (!video_outputted && video_frame)
  173. {
  174. *data = video_frame;
  175. *decoder_data=0;
  176. video_outputted=true;
  177. return AVI_SUCCESS;
  178. }
  179. return AVI_FAILURE;
  180. }
  181. void AVIRLE::Close()
  182. {
  183. free(video_frame);
  184. delete this;
  185. }
  186. #define CBCLASS AVIRLE
  187. START_DISPATCH;
  188. CB(GET_OUTPUT_PROPERTIES, GetOutputProperties)
  189. CB(DECODE_CHUNK, DecodeChunk)
  190. VCB(FLUSH, Flush)
  191. VCB(CLOSE, Close)
  192. CB(GET_PICTURE, GetPicture)
  193. CB(GET_PALETTE, GetPalette)
  194. END_DISPATCH;
  195. #undef CBCLASS