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.

183 lines
5.6KB

  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 "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. avctx->pix_fmt = AV_PIX_FMT_BGR24;
  70. /* Allocate maximum size possible, a full frame */
  71. ctx->inflated_size = avctx->width * avctx->height * 3;
  72. ctx->inflated_buf = av_malloc(ctx->inflated_size);
  73. if (!ctx->inflated_buf)
  74. return AVERROR(ENOMEM);
  75. return 0;
  76. }
  77. static void sum_delta_flipped(uint8_t *dst, int dst_linesize,
  78. const uint8_t *src, int src_linesize,
  79. int bytewidth, int height)
  80. {
  81. int i;
  82. for (; height > 0; height--) {
  83. for (i = 0; i < bytewidth; i++)
  84. dst[i] += src[(height - 1) * src_linesize + i];
  85. dst += dst_linesize;
  86. }
  87. }
  88. static int screenpresso_decode_frame(AVCodecContext *avctx, void *data,
  89. int *got_frame, AVPacket *avpkt)
  90. {
  91. ScreenpressoContext *ctx = avctx->priv_data;
  92. AVFrame *frame = data;
  93. uLongf length = ctx->inflated_size;
  94. int keyframe;
  95. int ret;
  96. /* Size check */
  97. if (avpkt->size < 3) {
  98. av_log(avctx, AV_LOG_ERROR, "Packet too small (%d)\n", avpkt->size);
  99. return AVERROR_INVALIDDATA;
  100. }
  101. /* Basic sanity check, but not really harmful */
  102. if ((avpkt->data[0] != 0x73 && avpkt->data[0] != 0x72) ||
  103. avpkt->data[1] != 8) { // bpp probably
  104. av_log(avctx, AV_LOG_WARNING, "Unknown header 0x%02X%02X\n",
  105. avpkt->data[0], avpkt->data[1]);
  106. }
  107. keyframe = (avpkt->data[0] == 0x73);
  108. /* Inflate the frame after the 2 byte header */
  109. ret = uncompress(ctx->inflated_buf, &length,
  110. avpkt->data + 2, avpkt->size - 2);
  111. if (ret) {
  112. av_log(avctx, AV_LOG_ERROR, "Deflate error %d.\n", ret);
  113. return AVERROR_UNKNOWN;
  114. }
  115. ret = ff_reget_buffer(avctx, ctx->current);
  116. if (ret < 0)
  117. return ret;
  118. /* When a keyframe is found, copy it (flipped) */
  119. if (keyframe)
  120. av_image_copy_plane(ctx->current->data[0] +
  121. ctx->current->linesize[0] * (avctx->height - 1),
  122. -1 * ctx->current->linesize[0],
  123. ctx->inflated_buf, avctx->width * 3,
  124. avctx->width * 3, avctx->height);
  125. /* Otherwise sum the delta on top of the current frame */
  126. else
  127. sum_delta_flipped(ctx->current->data[0], ctx->current->linesize[0],
  128. ctx->inflated_buf, avctx->width * 3,
  129. avctx->width * 3, avctx->height);
  130. /* Frame is ready to be output */
  131. ret = av_frame_ref(frame, ctx->current);
  132. if (ret < 0)
  133. return ret;
  134. /* Usual properties */
  135. if (keyframe) {
  136. frame->pict_type = AV_PICTURE_TYPE_I;
  137. frame->key_frame = 1;
  138. } else {
  139. frame->pict_type = AV_PICTURE_TYPE_P;
  140. }
  141. *got_frame = 1;
  142. return 0;
  143. }
  144. AVCodec ff_screenpresso_decoder = {
  145. .name = "screenpresso",
  146. .long_name = NULL_IF_CONFIG_SMALL("Screenpresso"),
  147. .type = AVMEDIA_TYPE_VIDEO,
  148. .id = AV_CODEC_ID_SCREENPRESSO,
  149. .init = screenpresso_init,
  150. .decode = screenpresso_decode_frame,
  151. .close = screenpresso_close,
  152. .priv_data_size = sizeof(ScreenpressoContext),
  153. .capabilities = AV_CODEC_CAP_DR1,
  154. .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
  155. FF_CODEC_CAP_INIT_CLEANUP,
  156. };