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.

187 lines
5.8KB

  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: BGR24
  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 "avcodec.h"
  40. #include "internal.h"
  41. typedef struct ScreenpressoContext {
  42. AVFrame *current;
  43. /* zlib interation */
  44. uint8_t *inflated_buf;
  45. uLongf inflated_size;
  46. } ScreenpressoContext;
  47. static av_cold int screenpresso_close(AVCodecContext *avctx)
  48. {
  49. ScreenpressoContext *ctx = avctx->priv_data;
  50. av_frame_free(&ctx->current);
  51. av_freep(&ctx->inflated_buf);
  52. return 0;
  53. }
  54. static av_cold int screenpresso_init(AVCodecContext *avctx)
  55. {
  56. ScreenpressoContext *ctx = avctx->priv_data;
  57. /* These needs to be set to estimate uncompressed buffer */
  58. int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
  59. if (ret < 0) {
  60. av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n",
  61. avctx->width, avctx->height);
  62. return ret;
  63. }
  64. /* Allocate current frame */
  65. ctx->current = av_frame_alloc();
  66. if (!ctx->current)
  67. return AVERROR(ENOMEM);
  68. avctx->pix_fmt = AV_PIX_FMT_BGR24;
  69. return 0;
  70. }
  71. static void sum_delta_flipped(uint8_t *dst, int dst_linesize,
  72. const uint8_t *src, int src_linesize,
  73. int bytewidth, int height)
  74. {
  75. int i;
  76. for (; height > 0; height--) {
  77. for (i = 0; i < bytewidth; i++)
  78. dst[i] += src[(height - 1) * src_linesize + i];
  79. dst += dst_linesize;
  80. }
  81. }
  82. static int screenpresso_decode_frame(AVCodecContext *avctx, void *data,
  83. int *got_frame, AVPacket *avpkt)
  84. {
  85. ScreenpressoContext *ctx = avctx->priv_data;
  86. AVFrame *frame = data;
  87. int keyframe;
  88. int ret;
  89. /* Size check */
  90. if (avpkt->size < 3) {
  91. av_log(avctx, AV_LOG_ERROR, "Packet too small (%d)\n", avpkt->size);
  92. return AVERROR_INVALIDDATA;
  93. }
  94. /* Basic sanity check, but not really harmful */
  95. if ((avpkt->data[0] != 0x73 && avpkt->data[0] != 0x72) ||
  96. avpkt->data[1] != 8) { // bpp probably
  97. av_log(avctx, AV_LOG_WARNING, "Unknown header 0x%02X%02X\n",
  98. avpkt->data[0], avpkt->data[1]);
  99. }
  100. keyframe = (avpkt->data[0] == 0x73);
  101. /* Resize deflate buffer and frame on resolution change */
  102. if (ctx->inflated_size != avctx->width * avctx->height * 3) {
  103. av_frame_unref(ctx->current);
  104. ret = ff_get_buffer(avctx, ctx->current, AV_GET_BUFFER_FLAG_REF);
  105. if (ret < 0)
  106. return ret;
  107. /* If malloc fails, reset len to avoid preserving an invalid value */
  108. ctx->inflated_size = avctx->width * avctx->height * 3;
  109. ret = av_reallocp(&ctx->inflated_buf, ctx->inflated_size);
  110. if (ret < 0) {
  111. ctx->inflated_size = 0;
  112. return ret;
  113. }
  114. }
  115. /* Inflate the frame after the 2 byte header */
  116. ret = uncompress(ctx->inflated_buf, &ctx->inflated_size,
  117. avpkt->data + 2, avpkt->size - 2);
  118. if (ret) {
  119. av_log(avctx, AV_LOG_ERROR, "Deflate error %d.\n", ret);
  120. return AVERROR_UNKNOWN;
  121. }
  122. /* When a keyframe is found, copy it (flipped) */
  123. if (keyframe)
  124. av_image_copy_plane(ctx->current->data[0] +
  125. ctx->current->linesize[0] * (avctx->height - 1),
  126. -1 * ctx->current->linesize[0],
  127. ctx->inflated_buf, avctx->width * 3,
  128. avctx->width * 3, avctx->height);
  129. /* Otherwise sum the delta on top of the current frame */
  130. else
  131. sum_delta_flipped(ctx->current->data[0], ctx->current->linesize[0],
  132. ctx->inflated_buf, avctx->width * 3,
  133. avctx->width * 3, avctx->height);
  134. /* Frame is ready to be output */
  135. ret = av_frame_ref(frame, ctx->current);
  136. if (ret < 0)
  137. return ret;
  138. /* Usual properties */
  139. if (keyframe) {
  140. frame->pict_type = AV_PICTURE_TYPE_I;
  141. frame->key_frame = 1;
  142. } else {
  143. frame->pict_type = AV_PICTURE_TYPE_P;
  144. }
  145. *got_frame = 1;
  146. return 0;
  147. }
  148. AVCodec ff_screenpresso_decoder = {
  149. .name = "screenpresso",
  150. .long_name = NULL_IF_CONFIG_SMALL("Screenpresso"),
  151. .type = AVMEDIA_TYPE_VIDEO,
  152. .id = AV_CODEC_ID_SCREENPRESSO,
  153. .init = screenpresso_init,
  154. .decode = screenpresso_decode_frame,
  155. .close = screenpresso_close,
  156. .priv_data_size = sizeof(ScreenpressoContext),
  157. .capabilities = AV_CODEC_CAP_DR1,
  158. .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
  159. FF_CODEC_CAP_INIT_CLEANUP,
  160. };