FFmpeg
Loading...
Searching...
No Matches
lscrdec.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 Paul B Mahol
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <stdint.h>
22#include <zlib.h>
23
24#include "libavutil/frame.h"
25#include "libavutil/error.h"
26#include "libavutil/log.h"
27#include "libavutil/mem.h"
28
29#include "avcodec.h"
30#include "bytestream.h"
31#include "codec.h"
32#include "codec_internal.h"
33#include "decode.h"
34#include "packet.h"
35#include "png.h"
36#include "pngdsp.h"
37#include "zlib_wrapper.h"
38
60
62{
63 uint8_t *ptr, *last_row;
64
65 ptr = s->image_buf + s->image_linesize * s->y;
66 if (s->y == 0)
67 last_row = s->last_row;
68 else
69 last_row = ptr - s->image_linesize;
70
71 ff_png_filter_row(&s->dsp, ptr, s->crow_buf[0], s->crow_buf + 1,
72 last_row, s->row_size, 3);
73
74 s->y++;
75}
76
77static int decode_idat(LSCRContext *s, z_stream *zstream, int length)
78{
79 int ret;
80 zstream->avail_in = FFMIN(length, bytestream2_get_bytes_left(&s->gb));
81 zstream->next_in = s->gb.buffer;
82
83 if (length <= 0)
85
86 bytestream2_skip(&s->gb, length);
87
88 /* decode one line if possible */
89 while (zstream->avail_in > 0) {
90 ret = inflate(zstream, Z_PARTIAL_FLUSH);
91 if (ret != Z_OK && ret != Z_STREAM_END) {
92 av_log(s->avctx, AV_LOG_ERROR, "inflate returned error %d\n", ret);
93 return AVERROR_EXTERNAL;
94 }
95 if (zstream->avail_out == 0) {
96 if (s->y < s->cur_h) {
98 }
99 zstream->avail_out = s->crow_size;
100 zstream->next_out = s->crow_buf;
101 }
102 if (ret == Z_STREAM_END && zstream->avail_in > 0) {
103 av_log(s->avctx, AV_LOG_WARNING,
104 "%d undecompressed bytes left in buffer\n", zstream->avail_in);
105 return 0;
106 }
107 }
108 return 0;
109}
110
111static int decode_frame_lscr(AVCodecContext *avctx, AVFrame *rframe,
112 int *got_frame, AVPacket *avpkt)
113{
114 LSCRContext *const s = avctx->priv_data;
115 GetByteContext *gb = &s->gb;
116 AVFrame *frame = s->last_picture;
117 int ret, nb_blocks, offset = 0;
118
119 if (avpkt->size < 2)
120 return AVERROR_INVALIDDATA;
121 if (avpkt->size == 2)
122 return 0;
123
124 bytestream2_init(gb, avpkt->data, avpkt->size);
125
126 nb_blocks = bytestream2_get_le16(gb);
127 if (bytestream2_get_bytes_left(gb) < 2 + nb_blocks * (12 + 8))
128 return AVERROR_INVALIDDATA;
129
130 ret = ff_reget_buffer(avctx, frame,
131 nb_blocks ? 0 : FF_REGET_BUFFER_FLAG_READONLY);
132 if (ret < 0)
133 return ret;
134
135 for (int b = 0; b < nb_blocks; b++) {
136 z_stream *const zstream = &s->zstream.zstream;
137 int x, y, x2, y2, w, h, left;
138 uint32_t csize, size;
139
140 if (inflateReset(zstream) != Z_OK)
141 return AVERROR_EXTERNAL;
142
143 bytestream2_seek(gb, 2 + b * 12, SEEK_SET);
144
145 x = bytestream2_get_le16(gb);
146 y = bytestream2_get_le16(gb);
147 x2 = bytestream2_get_le16(gb);
148 y2 = bytestream2_get_le16(gb);
149 w = x2-x;
150 s->cur_h = h = y2-y;
151
152 if (w <= 0 || x < 0 || x >= avctx->width || w + x > avctx->width ||
153 h <= 0 || y < 0 || y >= avctx->height || h + y > avctx->height)
154 return AVERROR_INVALIDDATA;
155
156 size = bytestream2_get_le32(gb);
157
158 if ((nb_blocks == 1) &&
159 (w == avctx->width) &&
160 (h == avctx->height) &&
161 (x == 0) && (y == 0))
162 frame->flags |= AV_FRAME_FLAG_KEY;
163 else
164 frame->flags &= ~AV_FRAME_FLAG_KEY;
165
166 bytestream2_seek(gb, 2 + nb_blocks * 12 + offset, SEEK_SET);
167 csize = bytestream2_get_be32(gb);
168 if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T'))
169 return AVERROR_INVALIDDATA;
170
171 offset += size;
172 left = size;
173
174 s->y = 0;
175 s->row_size = w * 3;
176
177 av_fast_padded_malloc(&s->buffer, &s->buffer_size, s->row_size + 16);
178 if (!s->buffer)
179 return AVERROR(ENOMEM);
180
181 av_fast_padded_malloc(&s->last_row, &s->last_row_size, s->row_size);
182 if (!s->last_row)
183 return AVERROR(ENOMEM);
184
185 s->crow_size = w * 3 + 1;
186 s->crow_buf = s->buffer + 15;
187 zstream->avail_out = s->crow_size;
188 zstream->next_out = s->crow_buf;
189 s->image_buf = frame->data[0] + (avctx->height - y - 1) * frame->linesize[0] + x * 3;
190 s->image_linesize =-frame->linesize[0];
191
192 while (left > 16) {
193 ret = decode_idat(s, zstream, csize);
194 if (ret < 0)
195 return ret;
196 left -= csize + 16;
197 if (left > 16) {
198 bytestream2_skip(gb, 4);
199 csize = bytestream2_get_be32(gb);
200 if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T'))
201 return AVERROR_INVALIDDATA;
202 }
203 }
204 }
205
207
208 if ((ret = av_frame_ref(rframe, frame)) < 0)
209 return ret;
210
211 *got_frame = 1;
212
213 return avpkt->size;
214}
215
217{
218 LSCRContext *s = avctx->priv_data;
219
220 av_frame_free(&s->last_picture);
221 av_freep(&s->buffer);
222 av_freep(&s->last_row);
223 ff_inflate_end(&s->zstream);
224
225 return 0;
226}
227
229{
230 LSCRContext *s = avctx->priv_data;
231
233 avctx->pix_fmt = AV_PIX_FMT_BGR24;
234
235 s->avctx = avctx;
236 s->last_picture = av_frame_alloc();
237 if (!s->last_picture)
238 return AVERROR(ENOMEM);
239
240 ff_pngdsp_init(&s->dsp);
241
242 return ff_inflate_init(&s->zstream, avctx);
243}
244
246{
247 LSCRContext *s = avctx->priv_data;
248 av_frame_unref(s->last_picture);
249}
250
252 .p.name = "lscr",
253 CODEC_LONG_NAME("LEAD Screen Capture"),
254 .p.type = AVMEDIA_TYPE_VIDEO,
255 .p.id = AV_CODEC_ID_LSCR,
256 .p.capabilities = AV_CODEC_CAP_DR1,
257 .priv_data_size = sizeof(LSCRContext),
261 .flush = lscr_decode_flush,
262 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
263};
const FFCodec ff_lscr_decoder
Definition lscrdec.c:251
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
Libavcodec external API header.
static int BS_FUNC left(const BSCTX *bc)
Return the number of the bits left in a buffer.
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
Definition bytestream.h:158
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition bytestream.h:137
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition bytestream.h:168
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition bytestream.h:212
#define s(width, name)
Definition cbs_vp9.c:198
#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
#define FF_REGET_BUFFER_FLAG_READONLY
the returned buffer does not need to be writable
Definition decode.h:137
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
error code definitions
reference-counted frame API
#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_LSCR
Definition codec_id.h:290
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
Same behaviour av_fast_malloc but the buffer has additional AV_INPUT_BUFFER_PADDING_SIZE at the end w...
Definition utils.c:53
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#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
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition frame.c:496
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_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
@ AV_PICTURE_TYPE_I
Intra.
Definition avutil.h:278
@ AV_PICTURE_TYPE_P
Predicted.
Definition avutil.h:279
#define b
Definition input.c:43
unsigned offset
Definition libaomenc.c:763
#define av_cold
Definition attributes.h:117
uint8_t w
Definition llvidencdsp.c:39
static int decode_frame_lscr(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt)
Definition lscrdec.c:111
static av_cold int lscr_decode_init(AVCodecContext *avctx)
Definition lscrdec.c:228
static int decode_idat(LSCRContext *s, z_stream *zstream, int length)
Definition lscrdec.c:77
static av_cold int lscr_decode_close(AVCodecContext *avctx)
Definition lscrdec.c:216
static av_cold void lscr_decode_flush(AVCodecContext *avctx)
Definition lscrdec.c:245
static void handle_row(LSCRContext *s)
Definition lscrdec.c:61
#define FFMIN(a, b)
Definition macros.h:49
#define MKTAG(a, b, c, d)
Definition macros.h:55
Memory handling functions.
@ AVCOL_RANGE_JPEG
Full range content.
Definition pixfmt.h:783
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition pixfmt.h:76
void ff_png_filter_row(PNGDSPContext *dsp, uint8_t *dst, int filter_type, const uint8_t *src, const uint8_t *last, int size, int bpp)
Definition pngdec.c:260
av_cold void ff_pngdsp_init(PNGDSPContext *dsp)
Definition pngdsp.c:85
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
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition avcodec.h:681
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
AVCodecContext * avctx
Definition lscrdec.c:41
GetByteContext gb
Definition lscrdec.c:51
int row_size
Definition lscrdec.c:54
int buffer_size
Definition lscrdec.c:45
PNGDSPContext dsp
Definition lscrdec.c:40
int crow_size
Definition lscrdec.c:47
FFZStream zstream
Definition lscrdec.c:58
unsigned int last_row_size
Definition lscrdec.c:49
int image_linesize
Definition lscrdec.c:53
AVFrame * last_picture
Definition lscrdec.c:43
uint8_t * image_buf
Definition lscrdec.c:52
uint8_t * crow_buf
Definition lscrdec.c:46
int cur_h
Definition lscrdec.c:55
uint8_t * buffer
Definition lscrdec.c:44
uint8_t * last_row
Definition lscrdec.c:48
#define av_freep(p)
#define av_log(a,...)
int size
static void inflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord, int maxc)
void ff_inflate_end(FFZStream *zstream)
Wrapper around inflateEnd().
int ff_inflate_init(FFZStream *zstream, void *logctx)
Wrapper around inflateInit().