Coverage Report

Created: 2026-01-16 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/mscc.c
Line
Count
Source
1
/*
2
 * Mandsoft Screen Capture Codec decoder
3
 *
4
 * Copyright (c) 2017 Paul B Mahol
5
 *
6
 * This file is part of FFmpeg.
7
 *
8
 * FFmpeg is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * FFmpeg is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with FFmpeg; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22
23
#include <stdio.h>
24
#include <string.h>
25
26
#include "libavutil/mem.h"
27
#include "avcodec.h"
28
#include "bytestream.h"
29
#include "codec_internal.h"
30
#include "decode.h"
31
#include "zlib_wrapper.h"
32
33
#include <zlib.h>
34
35
typedef struct MSCCContext {
36
    unsigned          bpp;
37
    unsigned int      decomp_size;
38
    uint8_t          *decomp_buf;
39
    unsigned int      uncomp_size;
40
    uint8_t          *uncomp_buf;
41
    FFZStream         zstream;
42
43
    uint32_t          pal[256];
44
} MSCCContext;
45
46
static int rle_uncompress(AVCodecContext *avctx, GetByteContext *gb, PutByteContext *pb)
47
24.4k
{
48
24.4k
    MSCCContext *s = avctx->priv_data;
49
24.4k
    unsigned x = 0, y = 0;
50
51
46.3k
    while (bytestream2_get_bytes_left(gb) > 0) {
52
29.0k
        uint32_t fill;
53
29.0k
        int j;
54
29.0k
        unsigned run = bytestream2_get_byte(gb);
55
56
29.0k
        if (run) {
57
13.9k
            if (bytestream2_get_bytes_left_p(pb) < run * s->bpp)
58
3.58k
                return AVERROR_INVALIDDATA;
59
60
10.4k
            switch (avctx->bits_per_coded_sample) {
61
5.05k
            case 8:
62
5.05k
                fill = bytestream2_get_byte(gb);
63
5.05k
                break;
64
1.42k
            case 16:
65
1.42k
                fill = bytestream2_get_le16(gb);
66
1.42k
                break;
67
2.22k
            case 24:
68
2.22k
                fill = bytestream2_get_le24(gb);
69
2.22k
                break;
70
1.71k
            case 32:
71
1.71k
                fill = bytestream2_get_le32(gb);
72
1.71k
                break;
73
10.4k
            }
74
75
92.0k
            for (j = 0; j < run; j++) {
76
81.6k
                switch (avctx->bits_per_coded_sample) {
77
40.3k
                case 8:
78
40.3k
                    bytestream2_put_byte(pb, fill);
79
40.3k
                    break;
80
10.9k
                case 16:
81
10.9k
                    bytestream2_put_le16(pb, fill);
82
10.9k
                    break;
83
16.8k
                case 24:
84
16.8k
                    bytestream2_put_le24(pb, fill);
85
16.8k
                    break;
86
13.3k
                case 32:
87
13.3k
                    bytestream2_put_le32(pb, fill);
88
13.3k
                    break;
89
81.6k
                }
90
81.6k
            }
91
10.4k
            x += run;
92
15.0k
        } else {
93
15.0k
            unsigned copy = bytestream2_get_byte(gb);
94
95
15.0k
            if (copy == 0) {
96
4.94k
                x = 0;
97
4.94k
                y++;
98
4.94k
                bytestream2_seek_p(pb, y * avctx->width * s->bpp, SEEK_SET);
99
10.1k
            } else if (copy == 1) {
100
2.95k
                return 0;
101
7.15k
            } else if (copy == 2) {
102
103
1.01k
                x += bytestream2_get_byte(gb);
104
1.01k
                y += bytestream2_get_byte(gb);
105
106
1.01k
                bytestream2_seek_p(pb, y * avctx->width * s->bpp + x * s->bpp, SEEK_SET);
107
6.14k
            } else {
108
6.14k
                if (bytestream2_get_bytes_left_p(pb) < copy * s->bpp)
109
635
                    return AVERROR_INVALIDDATA;
110
111
37.5k
                for (j = 0; j < copy; j++) {
112
32.0k
                    switch (avctx->bits_per_coded_sample) {
113
10.1k
                    case 8:
114
10.1k
                        bytestream2_put_byte(pb, bytestream2_get_byte(gb));
115
10.1k
                        break;
116
10.1k
                    case 16:
117
10.1k
                        bytestream2_put_le16(pb, bytestream2_get_le16(gb));
118
10.1k
                        break;
119
7.94k
                    case 24:
120
7.94k
                        bytestream2_put_le24(pb, bytestream2_get_le24(gb));
121
7.94k
                        break;
122
3.74k
                    case 32:
123
3.74k
                        bytestream2_put_le32(pb, bytestream2_get_le32(gb));
124
3.74k
                        break;
125
32.0k
                    }
126
32.0k
                }
127
128
5.50k
                if (s->bpp == 1 && (copy & 1))
129
602
                    bytestream2_skip(gb, 1);
130
5.50k
                x += copy;
131
5.50k
            }
132
15.0k
        }
133
29.0k
    }
134
135
17.2k
    return AVERROR_INVALIDDATA;
136
24.4k
}
137
138
static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
139
                        int *got_frame, AVPacket *avpkt)
140
424k
{
141
424k
    MSCCContext *s = avctx->priv_data;
142
424k
    z_stream *const zstream = &s->zstream.zstream;
143
424k
    const uint8_t *buf = avpkt->data;
144
424k
    int buf_size = avpkt->size;
145
424k
    GetByteContext gb;
146
424k
    PutByteContext pb;
147
424k
    int ret, j;
148
149
424k
    if (avpkt->size < 3)
150
290k
        return buf_size;
151
152
134k
    ret = inflateReset(zstream);
153
134k
    if (ret != Z_OK) {
154
0
        av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret);
155
0
        return AVERROR_UNKNOWN;
156
0
    }
157
134k
    zstream->next_out  = s->decomp_buf;
158
134k
    zstream->avail_out = s->decomp_size;
159
134k
    if (avctx->codec_id == AV_CODEC_ID_MSCC) {
160
86.3k
        const uint8_t start = avpkt->data[2] ^ avpkt->data[0];
161
162
86.3k
        zstream->next_in  = &start;
163
86.3k
        zstream->avail_in = 1;
164
86.3k
        ret = inflate(zstream, Z_NO_FLUSH);
165
86.3k
        if (ret != Z_OK || zstream->avail_in != 0)
166
0
            goto inflate_error;
167
168
86.3k
        buf      += 3;
169
86.3k
        buf_size -= 3;
170
86.3k
    }
171
134k
    zstream->next_in   = buf;
172
134k
    zstream->avail_in  = buf_size;
173
134k
    ret = inflate(zstream, Z_FINISH);
174
134k
    if (ret != Z_STREAM_END) {
175
108k
inflate_error:
176
108k
        av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", ret);
177
108k
        return AVERROR_UNKNOWN;
178
108k
    }
179
25.9k
    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
180
1.44k
        return ret;
181
182
24.4k
    if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
183
9.62k
        size_t size;
184
9.62k
        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size);
185
186
9.62k
        if (pal && size == AVPALETTE_SIZE) {
187
0
            for (j = 0; j < 256; j++)
188
0
                s->pal[j] = 0xFF000000 | AV_RL32(pal + j * 4);
189
9.62k
        } else if (pal) {
190
0
            av_log(avctx, AV_LOG_ERROR,
191
0
                   "Palette size %zu is wrong\n", size);
192
0
        }
193
9.62k
        memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
194
9.62k
    }
195
196
24.4k
    bytestream2_init(&gb, s->decomp_buf, zstream->total_out);
197
24.4k
    bytestream2_init_writer(&pb, s->uncomp_buf, s->uncomp_size);
198
199
24.4k
    ret = rle_uncompress(avctx, &gb, &pb);
200
24.4k
    if (ret)
201
21.5k
        return ret;
202
203
15.4M
    for (j = 0; j < avctx->height; j++) {
204
15.4M
        memcpy(frame->data[0] + (avctx->height - j - 1) * frame->linesize[0],
205
15.4M
               s->uncomp_buf + s->bpp * j * avctx->width, s->bpp * avctx->width);
206
15.4M
    }
207
208
2.95k
    *got_frame = 1;
209
210
2.95k
    return avpkt->size;
211
24.4k
}
212
213
static av_cold int decode_init(AVCodecContext *avctx)
214
2.37k
{
215
2.37k
    MSCCContext *s = avctx->priv_data;
216
2.37k
    int stride;
217
218
2.37k
    switch (avctx->bits_per_coded_sample) {
219
790
    case  8: avctx->pix_fmt = AV_PIX_FMT_PAL8;   break;
220
359
    case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
221
404
    case 24: avctx->pix_fmt = AV_PIX_FMT_BGR24;  break;
222
573
    case 32: avctx->pix_fmt = AV_PIX_FMT_BGRA;   break;
223
247
    default:
224
247
        av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", avctx->bits_per_coded_sample);
225
247
        return AVERROR_INVALIDDATA;
226
2.37k
    }
227
228
2.12k
    s->bpp = avctx->bits_per_coded_sample >> 3;
229
2.12k
    stride = 4 * ((avctx->width * avctx->bits_per_coded_sample + 31) / 32);
230
231
2.12k
    s->decomp_size = 2 * avctx->height * stride;
232
2.12k
    if (!(s->decomp_buf = av_malloc(s->decomp_size)))
233
0
        return AVERROR(ENOMEM);
234
235
2.12k
    s->uncomp_size = avctx->height * stride;
236
2.12k
    if (!(s->uncomp_buf = av_malloc(s->uncomp_size)))
237
0
        return AVERROR(ENOMEM);
238
239
2.12k
    return ff_inflate_init(&s->zstream, avctx);
240
2.12k
}
241
242
static av_cold int decode_close(AVCodecContext *avctx)
243
2.37k
{
244
2.37k
    MSCCContext *s = avctx->priv_data;
245
246
2.37k
    av_freep(&s->decomp_buf);
247
2.37k
    s->decomp_size = 0;
248
2.37k
    av_freep(&s->uncomp_buf);
249
2.37k
    s->uncomp_size = 0;
250
2.37k
    ff_inflate_end(&s->zstream);
251
252
2.37k
    return 0;
253
2.37k
}
254
255
const FFCodec ff_mscc_decoder = {
256
    .p.name           = "mscc",
257
    CODEC_LONG_NAME("Mandsoft Screen Capture Codec"),
258
    .p.type           = AVMEDIA_TYPE_VIDEO,
259
    .p.id             = AV_CODEC_ID_MSCC,
260
    .priv_data_size   = sizeof(MSCCContext),
261
    .init             = decode_init,
262
    .close            = decode_close,
263
    FF_CODEC_DECODE_CB(decode_frame),
264
    .p.capabilities   = AV_CODEC_CAP_DR1,
265
    .caps_internal    = FF_CODEC_CAP_INIT_CLEANUP,
266
};
267
268
const FFCodec ff_srgc_decoder = {
269
    .p.name           = "srgc",
270
    CODEC_LONG_NAME("Screen Recorder Gold Codec"),
271
    .p.type           = AVMEDIA_TYPE_VIDEO,
272
    .p.id             = AV_CODEC_ID_SRGC,
273
    .priv_data_size   = sizeof(MSCCContext),
274
    .init             = decode_init,
275
    .close            = decode_close,
276
    FF_CODEC_DECODE_CB(decode_frame),
277
    .p.capabilities   = AV_CODEC_CAP_DR1,
278
    .caps_internal    = FF_CODEC_CAP_INIT_CLEANUP,
279
};