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.

199 lines
6.1KB

  1. /*
  2. * Screenpresso decoder
  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. * Screenpresso decoder
  24. *
  25. * Fourcc: SPV1
  26. *
  27. * Screenpresso simply horizontally flips and then deflates frames,
  28. * alternating full pictures and deltas. Deltas are related to the currently
  29. * rebuilt frame (not the reference), and since there is no coordinate system
  30. * they contain exactly as many pixel as the keyframe.
  31. *
  32. * Supports: BGRA, BGR24, RGB555
  33. */
  34. #include <stdint.h>
  35. #include <string.h>
  36. #include <zlib.h>
  37. #include "libavutil/imgutils.h"
  38. #include "libavutil/internal.h"
  39. #include "libavutil/mem.h"
  40. #include "avcodec.h"
  41. #include "internal.h"
  42. typedef struct ScreenpressoContext {
  43. AVFrame *current;
  44. /* zlib interation */
  45. uint8_t *inflated_buf;
  46. uLongf inflated_size;
  47. } ScreenpressoContext;
  48. static av_cold int screenpresso_close(AVCodecContext *avctx)
  49. {
  50. ScreenpressoContext *ctx = avctx->priv_data;
  51. av_frame_free(&ctx->current);
  52. av_freep(&ctx->inflated_buf);
  53. return 0;
  54. }
  55. static av_cold int screenpresso_init(AVCodecContext *avctx)
  56. {
  57. ScreenpressoContext *ctx = avctx->priv_data;
  58. /* These needs to be set to estimate uncompressed buffer */
  59. int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
  60. if (ret < 0) {
  61. av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n",
  62. avctx->width, avctx->height);
  63. return ret;
  64. }
  65. /* Allocate current frame */
  66. ctx->current = av_frame_alloc();
  67. if (!ctx->current)
  68. return AVERROR(ENOMEM);
  69. /* Allocate maximum size possible, a full RGBA frame */
  70. ctx->inflated_size = avctx->width * avctx->height * 4;
  71. ctx->inflated_buf = av_malloc(ctx->inflated_size);
  72. if (!ctx->inflated_buf)
  73. return AVERROR(ENOMEM);
  74. return 0;
  75. }
  76. static void sum_delta_flipped(uint8_t *dst, int dst_linesize,
  77. const uint8_t *src, int src_linesize,
  78. int bytewidth, int height)
  79. {
  80. int i;
  81. for (; height > 0; height--) {
  82. for (i = 0; i < bytewidth; i++)
  83. dst[i] += src[(height - 1) * src_linesize + i];
  84. dst += dst_linesize;
  85. }
  86. }
  87. static int screenpresso_decode_frame(AVCodecContext *avctx, void *data,
  88. int *got_frame, AVPacket *avpkt)
  89. {
  90. ScreenpressoContext *ctx = avctx->priv_data;
  91. AVFrame *frame = data;
  92. uLongf length = ctx->inflated_size;
  93. int keyframe, component_size, src_linesize;
  94. int ret;
  95. /* Size check */
  96. if (avpkt->size < 3) {
  97. av_log(avctx, AV_LOG_ERROR, "Packet too small (%d)\n", avpkt->size);
  98. return AVERROR_INVALIDDATA;
  99. }
  100. /* Basic sanity check, but not really harmful */
  101. if (avpkt->data[0] != 0x73 && avpkt->data[0] != 0x72)
  102. av_log(avctx, AV_LOG_WARNING, "Unknown header 0x%02X\n", avpkt->data[0]);
  103. keyframe = (avpkt->data[0] == 0x73);
  104. /* Pixel size */
  105. component_size = ((avpkt->data[1] >> 2) & 0x03) + 1;
  106. switch (component_size) {
  107. case 2:
  108. avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
  109. break;
  110. case 3:
  111. avctx->pix_fmt = AV_PIX_FMT_BGR24;
  112. break;
  113. case 4:
  114. avctx->pix_fmt = AV_PIX_FMT_BGRA;
  115. break;
  116. default:
  117. av_log(avctx, AV_LOG_ERROR, "Invalid bits per pixel value (%d)\n",
  118. component_size);
  119. return AVERROR_INVALIDDATA;
  120. }
  121. /* Inflate the frame after the 2 byte header */
  122. ret = uncompress(ctx->inflated_buf, &length,
  123. avpkt->data + 2, avpkt->size - 2);
  124. if (ret) {
  125. av_log(avctx, AV_LOG_ERROR, "Deflate error %d.\n", ret);
  126. return AVERROR_UNKNOWN;
  127. }
  128. ret = ff_reget_buffer(avctx, ctx->current);
  129. if (ret < 0)
  130. return ret;
  131. /* Codec has aligned strides */
  132. src_linesize = FFALIGN(avctx->width * component_size, 4);
  133. /* When a keyframe is found, copy it (flipped) */
  134. if (keyframe)
  135. av_image_copy_plane(ctx->current->data[0] +
  136. ctx->current->linesize[0] * (avctx->height - 1),
  137. -1 * ctx->current->linesize[0],
  138. ctx->inflated_buf, src_linesize,
  139. avctx->width * component_size, avctx->height);
  140. /* Otherwise sum the delta on top of the current frame */
  141. else
  142. sum_delta_flipped(ctx->current->data[0], ctx->current->linesize[0],
  143. ctx->inflated_buf, src_linesize,
  144. avctx->width * component_size, avctx->height);
  145. /* Frame is ready to be output */
  146. ret = av_frame_ref(frame, ctx->current);
  147. if (ret < 0)
  148. return ret;
  149. /* Usual properties */
  150. if (keyframe) {
  151. frame->pict_type = AV_PICTURE_TYPE_I;
  152. frame->key_frame = 1;
  153. } else {
  154. frame->pict_type = AV_PICTURE_TYPE_P;
  155. }
  156. *got_frame = 1;
  157. return 0;
  158. }
  159. AVCodec ff_screenpresso_decoder = {
  160. .name = "screenpresso",
  161. .long_name = NULL_IF_CONFIG_SMALL("Screenpresso"),
  162. .type = AVMEDIA_TYPE_VIDEO,
  163. .id = AV_CODEC_ID_SCREENPRESSO,
  164. .init = screenpresso_init,
  165. .decode = screenpresso_decode_frame,
  166. .close = screenpresso_close,
  167. .priv_data_size = sizeof(ScreenpressoContext),
  168. .capabilities = AV_CODEC_CAP_DR1,
  169. .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
  170. FF_CODEC_CAP_INIT_CLEANUP,
  171. };