FFmpeg
Loading...
Searching...
No Matches
screenpresso.c
Go to the documentation of this file.
1/*
2 * Screenpresso decoder
3 * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22/**
23 * @file
24 * Screenpresso decoder
25 *
26 * Fourcc: SPV1
27 *
28 * Screenpresso simply horizontally flips and then deflates frames,
29 * alternating full pictures and deltas. Deltas are related to the currently
30 * rebuilt frame (not the reference), and since there is no coordinate system
31 * they contain exactly as many pixel as the keyframe.
32 *
33 * Supports: BGR0, BGR24, RGB555
34 */
35
36#include <stdint.h>
37#include <zlib.h>
38
39#include "libavutil/imgutils.h"
40#include "libavutil/internal.h"
41#include "libavutil/mem.h"
42
43#include "avcodec.h"
44#include "codec_internal.h"
45#include "decode.h"
46
47typedef struct ScreenpressoContext {
49
50 /* zlib interaction */
51 uint8_t *inflated_buf;
54
56{
58
59 av_frame_free(&ctx->current);
60 av_freep(&ctx->inflated_buf);
61
62 return 0;
63}
64
66{
68
69 /* These needs to be set to estimate uncompressed buffer */
70 int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
71 if (ret < 0) {
72 av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n",
73 avctx->width, avctx->height);
74 return ret;
75 }
76
77 /* Allocate current frame */
78 ctx->current = av_frame_alloc();
79 if (!ctx->current)
80 return AVERROR(ENOMEM);
81
82 /* Allocate maximum size possible, a full RGBA frame */
83 ctx->inflated_size = avctx->width * avctx->height * 4;
84 ctx->inflated_buf = av_malloc(ctx->inflated_size);
85 if (!ctx->inflated_buf)
86 return AVERROR(ENOMEM);
87
88 return 0;
89}
90
91static void sum_delta_flipped(uint8_t *dst, int dst_linesize,
92 const uint8_t *src, int src_linesize,
93 int bytewidth, int height)
94{
95 int i;
96 for (; height > 0; height--) {
97 const uint8_t *src1 = &src[(height - 1) * src_linesize];
98 for (i = 0; i < bytewidth; i++)
99 dst[i] += src1[i];
100 dst += dst_linesize;
101 }
102}
103
105 int *got_frame, AVPacket *avpkt)
106{
108 uLongf length = ctx->inflated_size;
109 int keyframe, component_size, src_linesize;
110 int ret;
111
112 /* Size check */
113 if (avpkt->size < 3) {
114 av_log(avctx, AV_LOG_ERROR, "Packet too small (%d)\n", avpkt->size);
115 return AVERROR_INVALIDDATA;
116 }
117
118 /* Compression level (4 bits) and keyframe information (1 bit) */
119 av_log(avctx, AV_LOG_DEBUG, "Compression level %d\n", avpkt->data[0] >> 4);
120 keyframe = avpkt->data[0] & 1;
121
122 /* Pixel size */
123 component_size = ((avpkt->data[1] >> 2) & 0x03) + 1;
124 switch (component_size) {
125 case 2:
127 break;
128 case 3:
129 avctx->pix_fmt = AV_PIX_FMT_BGR24;
130 break;
131 case 4:
132 avctx->pix_fmt = AV_PIX_FMT_BGR0;
133 break;
134 default:
135 av_log(avctx, AV_LOG_ERROR, "Invalid bits per pixel value (%d)\n",
136 component_size);
137 return AVERROR_INVALIDDATA;
138 }
139
140 /* Codec has aligned strides */
141 src_linesize = FFALIGN(avctx->width * component_size, 4);
142
143 /* Inflate the frame after the 2 byte header */
144 ret = uncompress(ctx->inflated_buf, &length,
145 avpkt->data + 2, avpkt->size - 2);
146 if (ret) {
147 av_log(avctx, AV_LOG_ERROR, "Deflate error %d.\n", ret);
148 return AVERROR_UNKNOWN;
149 }
150 if (length < src_linesize * avctx->height) {
151 av_log(avctx, AV_LOG_ERROR, "Deflated %lu bytes, but %d are needed\n",
152 length, src_linesize * avctx->height);
153 return AVERROR_INVALIDDATA;
154 }
155
156 ret = ff_reget_buffer(avctx, ctx->current, 0);
157 if (ret < 0)
158 return ret;
159
160 /* When a keyframe is found, copy it (flipped) */
161 if (keyframe)
162 av_image_copy_plane(ctx->current->data[0] +
163 ctx->current->linesize[0] * (avctx->height - 1),
164 -1 * ctx->current->linesize[0],
165 ctx->inflated_buf, src_linesize,
166 avctx->width * component_size, avctx->height);
167 /* Otherwise sum the delta on top of the current frame */
168 else
169 sum_delta_flipped(ctx->current->data[0], ctx->current->linesize[0],
170 ctx->inflated_buf, src_linesize,
171 avctx->width * component_size, avctx->height);
172
173 /* Frame is ready to be output */
174 ret = av_frame_ref(frame, ctx->current);
175 if (ret < 0)
176 return ret;
177
178 /* Usual properties */
179 if (keyframe) {
180 frame->pict_type = AV_PICTURE_TYPE_I;
181 frame->flags |= AV_FRAME_FLAG_KEY;
182 } else {
183 frame->pict_type = AV_PICTURE_TYPE_P;
184 }
185 *got_frame = 1;
186
187 return avpkt->size;
188}
189
191 .p.name = "screenpresso",
192 CODEC_LONG_NAME("Screenpresso"),
193 .p.type = AVMEDIA_TYPE_VIDEO,
195 .init = screenpresso_init,
197 .close = screenpresso_close,
198 .priv_data_size = sizeof(ScreenpressoContext),
199 .p.capabilities = AV_CODEC_CAP_DR1,
200 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
201};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
const FFCodec ff_screenpresso_decoder
Libavcodec external API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define FF_CODEC_DECODE_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Identical in function to ff_get_buffer(), except it reuses the existing buffer if available.
Definition decode.c:1906
static AVFrame * frame
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
@ AV_CODEC_ID_SCREENPRESSO
Definition codec_id.h:241
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition error.h:73
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
#define AV_FRAME_FLAG_KEY
A flag to mark frames that are keyframes.
Definition frame.h:687
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition frame.c:278
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition imgutils.c:318
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition imgutils.c:374
@ AV_PICTURE_TYPE_I
Intra.
Definition avutil.h:278
@ AV_PICTURE_TYPE_P
Predicted.
Definition avutil.h:279
misc image utilities
#define av_cold
Definition attributes.h:117
common internal API header
#define FFALIGN(x, a)
Definition macros.h:78
Memory handling functions.
#define av_malloc(s)
Definition ops_static.c:52
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition pixfmt.h:265
@ AV_PIX_FMT_RGB555LE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
Definition pixfmt.h:115
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition pixfmt.h:76
static void sum_delta_flipped(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
static av_cold int screenpresso_close(AVCodecContext *avctx)
static av_cold int screenpresso_init(AVCodecContext *avctx)
static int screenpresso_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt)
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
int width
picture width / height.
Definition avcodec.h:604
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
#define av_freep(p)
#define av_log(a,...)
#define src1
Definition h264pred.c:141
#define src
Definition vp8dsp.c:248
static AVFormatContext * ctx
Definition movenc.c:49
#define height
Definition dsp.h:89