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.

182 lines
5.5KB

  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. /* Allocate maximum size possible, a full frame */
  70. ctx->inflated_size = avctx->width * avctx->height * 3;
  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;
  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. avpkt->data[1] != 8) { // bpp probably
  103. av_log(avctx, AV_LOG_WARNING, "Unknown header 0x%02X%02X\n",
  104. avpkt->data[0], avpkt->data[1]);
  105. }
  106. keyframe = (avpkt->data[0] == 0x73);
  107. /* Inflate the frame after the 2 byte header */
  108. ret = uncompress(ctx->inflated_buf, &length,
  109. avpkt->data + 2, avpkt->size - 2);
  110. if (ret) {
  111. av_log(avctx, AV_LOG_ERROR, "Deflate error %d.\n", ret);
  112. return AVERROR_UNKNOWN;
  113. }
  114. ret = ff_reget_buffer(avctx, ctx->current);
  115. if (ret < 0)
  116. return ret;
  117. /* When a keyframe is found, copy it (flipped) */
  118. if (keyframe)
  119. av_image_copy_plane(ctx->current->data[0] +
  120. ctx->current->linesize[0] * (avctx->height - 1),
  121. -1 * ctx->current->linesize[0],
  122. ctx->inflated_buf, avctx->width * 3,
  123. avctx->width * 3, avctx->height);
  124. /* Otherwise sum the delta on top of the current frame */
  125. else
  126. sum_delta_flipped(ctx->current->data[0], ctx->current->linesize[0],
  127. ctx->inflated_buf, avctx->width * 3,
  128. avctx->width * 3, avctx->height);
  129. /* Frame is ready to be output */
  130. ret = av_frame_ref(frame, ctx->current);
  131. if (ret < 0)
  132. return ret;
  133. /* Usual properties */
  134. if (keyframe) {
  135. frame->pict_type = AV_PICTURE_TYPE_I;
  136. frame->key_frame = 1;
  137. } else {
  138. frame->pict_type = AV_PICTURE_TYPE_P;
  139. }
  140. *got_frame = 1;
  141. return 0;
  142. }
  143. AVCodec ff_screenpresso_decoder = {
  144. .name = "screenpresso",
  145. .long_name = NULL_IF_CONFIG_SMALL("Screenpresso"),
  146. .type = AVMEDIA_TYPE_VIDEO,
  147. .id = AV_CODEC_ID_SCREENPRESSO,
  148. .init = screenpresso_init,
  149. .decode = screenpresso_decode_frame,
  150. .close = screenpresso_close,
  151. .priv_data_size = sizeof(ScreenpressoContext),
  152. .capabilities = AV_CODEC_CAP_DR1,
  153. .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
  154. FF_CODEC_CAP_INIT_CLEANUP,
  155. };