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.

285 lines
9.1KB

  1. /*
  2. * innoHeim/Rsupport Screen Capture Codec
  3. * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
  4. *
  5. * This file is part of Libav.
  6. *
  7. * Libav 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. * Libav 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 Libav; 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. * innoHeim/Rsupport Screen Capture Codec decoder
  24. *
  25. * Fourcc: ISCC, RSCC
  26. *
  27. * Lossless codec, data stored in tiles, with optional deflate compression.
  28. *
  29. * Header contains the number of tiles in a frame with the tile coordinates,
  30. * and it can be deflated or not. Similarly, pixel data comes after the header
  31. * and a variable size value, and it can be deflated or just raw.
  32. *
  33. * Supports: BGRA
  34. */
  35. #include <stdint.h>
  36. #include <string.h>
  37. #include <zlib.h>
  38. #include "libavutil/imgutils.h"
  39. #include "libavutil/internal.h"
  40. #include "avcodec.h"
  41. #include "bytestream.h"
  42. #include "internal.h"
  43. #define TILE_SIZE 8
  44. typedef struct Tile {
  45. int x, y;
  46. int w, h;
  47. } Tile;
  48. typedef struct RsccContext {
  49. GetByteContext gbc;
  50. AVFrame *reference;
  51. Tile *tiles;
  52. unsigned int tiles_size;
  53. /* zlib interaction */
  54. uint8_t *inflated_buf;
  55. uLongf inflated_size;
  56. } RsccContext;
  57. static av_cold int rscc_init(AVCodecContext *avctx)
  58. {
  59. RsccContext *ctx = avctx->priv_data;
  60. /* These needs to be set to estimate uncompressed buffer */
  61. int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
  62. if (ret < 0) {
  63. av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n",
  64. avctx->width, avctx->height);
  65. return ret;
  66. }
  67. /* Allocate reference frame */
  68. ctx->reference = av_frame_alloc();
  69. if (!ctx->reference)
  70. return AVERROR(ENOMEM);
  71. avctx->pix_fmt = AV_PIX_FMT_BGRA;
  72. /* Store the value to check for keyframes */
  73. ctx->inflated_size = avctx->width * avctx->height * 4;
  74. /* Allocate maximum size possible, a full frame */
  75. ctx->inflated_buf = av_malloc(ctx->inflated_size);
  76. if (!ctx->inflated_buf)
  77. return AVERROR(ENOMEM);
  78. return 0;
  79. }
  80. static av_cold int rscc_close(AVCodecContext *avctx)
  81. {
  82. RsccContext *ctx = avctx->priv_data;
  83. av_freep(&ctx->tiles);
  84. av_freep(&ctx->inflated_buf);
  85. av_frame_free(&ctx->reference);
  86. return 0;
  87. }
  88. static int rscc_decode_frame(AVCodecContext *avctx, void *data,
  89. int *got_frame, AVPacket *avpkt)
  90. {
  91. RsccContext *ctx = avctx->priv_data;
  92. GetByteContext *gbc = &ctx->gbc;
  93. GetByteContext tiles_gbc;
  94. AVFrame *frame = data;
  95. const uint8_t *pixels, *raw;
  96. uint8_t *inflated_tiles = NULL;
  97. int tiles_nb, packed_size, pixel_size = 0;
  98. int i, ret = 0;
  99. bytestream2_init(gbc, avpkt->data, avpkt->size);
  100. /* Size check */
  101. if (bytestream2_get_bytes_left(gbc) < 12) {
  102. av_log(avctx, AV_LOG_ERROR, "Packet too small (%d)\n", avpkt->size);
  103. return AVERROR_INVALIDDATA;
  104. }
  105. /* Read number of tiles, and allocate the array */
  106. tiles_nb = bytestream2_get_le16(gbc);
  107. av_fast_malloc(&ctx->tiles, &ctx->tiles_size,
  108. tiles_nb * sizeof(*ctx->tiles));
  109. if (!ctx->tiles) {
  110. ret = AVERROR(ENOMEM);
  111. goto end;
  112. }
  113. av_log(avctx, AV_LOG_DEBUG, "Frame with %d tiles.\n", tiles_nb);
  114. /* When there are more than 5 tiles, they are packed together with
  115. * a size header. When that size does not match the number of tiles
  116. * times the tile size, it means it needs to be inflated as well */
  117. if (tiles_nb > 5) {
  118. uLongf packed_tiles_size;
  119. if (tiles_nb < 32)
  120. packed_tiles_size = bytestream2_get_byte(gbc);
  121. else
  122. packed_tiles_size = bytestream2_get_le16(gbc);
  123. ff_dlog(avctx, "packed tiles of size %lu.\n", packed_tiles_size);
  124. /* If necessary, uncompress tiles, and hijack the bytestream reader */
  125. if (packed_tiles_size != tiles_nb * TILE_SIZE) {
  126. uLongf length = tiles_nb * TILE_SIZE;
  127. inflated_tiles = av_malloc(length);
  128. if (!inflated_tiles) {
  129. ret = AVERROR(ENOMEM);
  130. goto end;
  131. }
  132. ret = uncompress(inflated_tiles, &length,
  133. gbc->buffer, packed_tiles_size);
  134. if (ret) {
  135. av_log(avctx, AV_LOG_ERROR, "Tile deflate error %d.\n", ret);
  136. ret = AVERROR_UNKNOWN;
  137. goto end;
  138. }
  139. /* Skip the compressed tile section in the main byte reader,
  140. * and point it to read the newly uncompressed data */
  141. bytestream2_skip(gbc, packed_tiles_size);
  142. bytestream2_init(&tiles_gbc, inflated_tiles, length);
  143. gbc = &tiles_gbc;
  144. }
  145. }
  146. /* Fill in array of tiles, keeping track of how many pixels are updated */
  147. for (i = 0; i < tiles_nb; i++) {
  148. ctx->tiles[i].x = bytestream2_get_le16(gbc);
  149. ctx->tiles[i].w = bytestream2_get_le16(gbc);
  150. ctx->tiles[i].y = bytestream2_get_le16(gbc);
  151. ctx->tiles[i].h = bytestream2_get_le16(gbc);
  152. pixel_size += ctx->tiles[i].w * ctx->tiles[i].h * 4;
  153. ff_dlog(avctx, "tile %d orig(%d,%d) %dx%d.\n", i,
  154. ctx->tiles[i].x, ctx->tiles[i].y,
  155. ctx->tiles[i].w, ctx->tiles[i].h);
  156. if (ctx->tiles[i].w == 0 || ctx->tiles[i].h == 0) {
  157. av_log(avctx, AV_LOG_ERROR,
  158. "invalid tile %d at (%d.%d) with size %dx%d.\n", i,
  159. ctx->tiles[i].x, ctx->tiles[i].y,
  160. ctx->tiles[i].w, ctx->tiles[i].h);
  161. ret = AVERROR_INVALIDDATA;
  162. goto end;
  163. } else if (ctx->tiles[i].x + ctx->tiles[i].w > avctx->width ||
  164. ctx->tiles[i].y + ctx->tiles[i].h > avctx->height) {
  165. av_log(avctx, AV_LOG_ERROR,
  166. "out of bounds tile %d at (%d.%d) with size %dx%d.\n", i,
  167. ctx->tiles[i].x, ctx->tiles[i].y,
  168. ctx->tiles[i].w, ctx->tiles[i].h);
  169. ret = AVERROR_INVALIDDATA;
  170. goto end;
  171. }
  172. }
  173. /* Reset the reader in case it had been modified before */
  174. gbc = &ctx->gbc;
  175. /* Extract how much pixel data the tiles contain */
  176. if (pixel_size < 0x100)
  177. packed_size = bytestream2_get_byte(gbc);
  178. else if (pixel_size < 0x10000)
  179. packed_size = bytestream2_get_le16(gbc);
  180. else if (pixel_size < 0x1000000)
  181. packed_size = bytestream2_get_le24(gbc);
  182. else
  183. packed_size = bytestream2_get_le32(gbc);
  184. ff_dlog(avctx, "pixel_size %d packed_size %d.\n", pixel_size, packed_size);
  185. /* Get pixels buffer, it may be deflated or just raw */
  186. if (pixel_size == packed_size) {
  187. pixels = gbc->buffer;
  188. } else {
  189. uLongf len = ctx->inflated_size;
  190. ret = uncompress(ctx->inflated_buf, &len, gbc->buffer, packed_size);
  191. if (ret) {
  192. av_log(avctx, AV_LOG_ERROR, "Pixel deflate error %d.\n", ret);
  193. ret = AVERROR_UNKNOWN;
  194. goto end;
  195. }
  196. pixels = ctx->inflated_buf;
  197. }
  198. /* Allocate when needed */
  199. ret = ff_reget_buffer(avctx, ctx->reference);
  200. if (ret < 0)
  201. goto end;
  202. /* Pointer to actual pixels, will be updated when data is consumed */
  203. raw = pixels;
  204. for (i = 0; i < tiles_nb; i++) {
  205. uint8_t *dst = ctx->reference->data[0] + ctx->reference->linesize[0] *
  206. (avctx->height - ctx->tiles[i].y - 1) +
  207. ctx->tiles[i].x * 4;
  208. av_image_copy_plane(dst, -1 * ctx->reference->linesize[0],
  209. raw, ctx->tiles[i].w * 4,
  210. ctx->tiles[i].w * 4, ctx->tiles[i].h);
  211. raw += ctx->tiles[i].w * 4 * ctx->tiles[i].h;
  212. }
  213. /* Frame is ready to be output */
  214. ret = av_frame_ref(frame, ctx->reference);
  215. if (ret < 0)
  216. goto end;
  217. /* Keyframe when the number of pixels updated matches the whole surface */
  218. if (pixel_size == ctx->inflated_size) {
  219. frame->pict_type = AV_PICTURE_TYPE_I;
  220. frame->key_frame = 1;
  221. } else {
  222. frame->pict_type = AV_PICTURE_TYPE_P;
  223. }
  224. *got_frame = 1;
  225. end:
  226. av_free(inflated_tiles);
  227. return ret;
  228. }
  229. AVCodec ff_rscc_decoder = {
  230. .name = "rscc",
  231. .long_name = NULL_IF_CONFIG_SMALL("innoHeim/Rsupport Screen Capture Codec"),
  232. .type = AVMEDIA_TYPE_VIDEO,
  233. .id = AV_CODEC_ID_RSCC,
  234. .init = rscc_init,
  235. .decode = rscc_decode_frame,
  236. .close = rscc_close,
  237. .priv_data_size = sizeof(RsccContext),
  238. .capabilities = AV_CODEC_CAP_DR1,
  239. .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
  240. FF_CODEC_CAP_INIT_CLEANUP,
  241. };